diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..548bbe63 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "kbengine_demos_assets"] + path = kbengine_demos_assets + url = https://github.com/kbengine/kbengine_demos_assets.git diff --git a/Assets/CAI/Editor/cai-nav-u3d-editor.dll b/Assets/CAI/Editor/cai-nav-u3d-editor.dll index e72fac5d..e21c4a70 100644 Binary files a/Assets/CAI/Editor/cai-nav-u3d-editor.dll and b/Assets/CAI/Editor/cai-nav-u3d-editor.dll differ diff --git a/Assets/CAI/Editor/cai-nmbuild-extras-u3d-editor.dll b/Assets/CAI/Editor/cai-nmbuild-extras-u3d-editor.dll index 7dea08fd..074c6753 100644 Binary files a/Assets/CAI/Editor/cai-nmbuild-extras-u3d-editor.dll and b/Assets/CAI/Editor/cai-nmbuild-extras-u3d-editor.dll differ diff --git a/Assets/CAI/Editor/cai-nmbuild-u3d-editor.dll b/Assets/CAI/Editor/cai-nmbuild-u3d-editor.dll index a30cf921..0451e877 100644 Binary files a/Assets/CAI/Editor/cai-nmbuild-u3d-editor.dll and b/Assets/CAI/Editor/cai-nmbuild-u3d-editor.dll differ diff --git a/Assets/CAI/Editor/cai-nmbuild.dll b/Assets/CAI/Editor/cai-nmbuild.dll index fa6e3f95..96a39b4a 100644 Binary files a/Assets/CAI/Editor/cai-nmbuild.dll and b/Assets/CAI/Editor/cai-nmbuild.dll differ diff --git a/Assets/CAI/Editor/cai-nmgen.dll b/Assets/CAI/Editor/cai-nmgen.dll index bfd86972..febd4b7a 100644 Binary files a/Assets/CAI/Editor/cai-nmgen.dll and b/Assets/CAI/Editor/cai-nmgen.dll differ diff --git a/Assets/CAI/Editor/cai-util-u3d-editor.dll b/Assets/CAI/Editor/cai-util-u3d-editor.dll index 96b8d321..77bac951 100644 Binary files a/Assets/CAI/Editor/cai-util-u3d-editor.dll and b/Assets/CAI/Editor/cai-util-u3d-editor.dll differ diff --git a/Assets/CAI/cai-nav-u3d.dll b/Assets/CAI/cai-nav-u3d.dll index 8a167f29..9da8386a 100644 Binary files a/Assets/CAI/cai-nav-u3d.dll and b/Assets/CAI/cai-nav-u3d.dll differ diff --git a/Assets/CAI/cai-nav.dll b/Assets/CAI/cai-nav.dll index 4158a983..89a2a12a 100644 Binary files a/Assets/CAI/cai-nav.dll and b/Assets/CAI/cai-nav.dll differ diff --git a/Assets/CAI/cai-nmbuild-extras-u3d.dll b/Assets/CAI/cai-nmbuild-extras-u3d.dll index 48f92164..ecd30bcf 100644 Binary files a/Assets/CAI/cai-nmbuild-extras-u3d.dll and b/Assets/CAI/cai-nmbuild-extras-u3d.dll differ diff --git a/Assets/CAI/cai-util-u3d.dll b/Assets/CAI/cai-util-u3d.dll index e81d2ab0..b8e25c4e 100644 Binary files a/Assets/CAI/cai-util-u3d.dll and b/Assets/CAI/cai-util-u3d.dll differ diff --git a/Assets/CAI/cai-util.dll b/Assets/CAI/cai-util.dll index ed389024..2ffaf7cd 100644 Binary files a/Assets/CAI/cai-util.dll and b/Assets/CAI/cai-util.dll differ diff --git a/Assets/Editor/ExprotAssetBundles.cs b/Assets/Editor/ExprotAssetBundles.cs index d5a3317b..37ae0676 100644 Binary files a/Assets/Editor/ExprotAssetBundles.cs and b/Assets/Editor/ExprotAssetBundles.cs differ diff --git a/Assets/Nav_build/xinshoucun/CAIBakedNavmesh.asset b/Assets/Nav_build/xinshoucun/CAIBakedNavmesh.asset index 06482709..328e3819 100644 Binary files a/Assets/Nav_build/xinshoucun/CAIBakedNavmesh.asset and b/Assets/Nav_build/xinshoucun/CAIBakedNavmesh.asset differ diff --git a/Assets/Plugins/cai-nmgen-rcn(generate navmesh).zip b/Assets/Plugins/cai-nmgen-rcn(generate navmesh).zip index 31500287..7deb7eef 100644 Binary files a/Assets/Plugins/cai-nmgen-rcn(generate navmesh).zip and b/Assets/Plugins/cai-nmgen-rcn(generate navmesh).zip differ diff --git a/Assets/Plugins/kbengine/Account.cs b/Assets/Plugins/kbengine/Account.cs index a766e665..792699e2 100644 Binary files a/Assets/Plugins/kbengine/Account.cs and b/Assets/Plugins/kbengine/Account.cs differ diff --git a/Assets/Plugins/kbengine/Avatar.cs b/Assets/Plugins/kbengine/Avatar.cs index 8f2d6191..f2c06eb8 100644 Binary files a/Assets/Plugins/kbengine/Avatar.cs and b/Assets/Plugins/kbengine/Avatar.cs differ diff --git a/Assets/Plugins/kbengine/GameObject.cs b/Assets/Plugins/kbengine/GameObject.cs deleted file mode 100644 index 26f66edc..00000000 Binary files a/Assets/Plugins/kbengine/GameObject.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/GameObject.cs.meta b/Assets/Plugins/kbengine/GameObject.cs.meta deleted file mode 100644 index 67340158..00000000 --- a/Assets/Plugins/kbengine/GameObject.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f5cede5ec420c174f848957ba8ad33f6 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/Gate.cs b/Assets/Plugins/kbengine/Gate.cs index c608d3c5..ee1bc3e2 100644 Binary files a/Assets/Plugins/kbengine/Gate.cs and b/Assets/Plugins/kbengine/Gate.cs differ diff --git a/Assets/Plugins/kbengine/Monster.cs b/Assets/Plugins/kbengine/Monster.cs index 2c3b4976..7640ac2e 100644 Binary files a/Assets/Plugins/kbengine/Monster.cs and b/Assets/Plugins/kbengine/Monster.cs differ diff --git a/Assets/Plugins/kbengine/NPC.cs b/Assets/Plugins/kbengine/NPC.cs index d38e1e2c..3483bf0b 100644 Binary files a/Assets/Plugins/kbengine/NPC.cs and b/Assets/Plugins/kbengine/NPC.cs differ diff --git a/Assets/Plugins/kbengine/Skill.cs b/Assets/Plugins/kbengine/Skill.cs index 2cd5b970..a80c418f 100644 Binary files a/Assets/Plugins/kbengine/Skill.cs and b/Assets/Plugins/kbengine/Skill.cs differ diff --git a/Assets/Plugins/kbengine/clientapp.cs b/Assets/Plugins/kbengine/clientapp.cs deleted file mode 100644 index abad1a4c..00000000 Binary files a/Assets/Plugins/kbengine/clientapp.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/components.meta b/Assets/Plugins/kbengine/components.meta new file mode 100644 index 00000000..06fd78e9 --- /dev/null +++ b/Assets/Plugins/kbengine/components.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 42f9e3ca8baf51b438a387d05bff542e +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/kbengine/components/Test.cs b/Assets/Plugins/kbengine/components/Test.cs new file mode 100644 index 00000000..f198ff3b Binary files /dev/null and b/Assets/Plugins/kbengine/components/Test.cs differ diff --git a/Assets/Plugins/kbengine/components/Test.cs.meta b/Assets/Plugins/kbengine/components/Test.cs.meta new file mode 100644 index 00000000..0506c988 --- /dev/null +++ b/Assets/Plugins/kbengine/components/Test.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d8098767b8eaae04cb567520d3dc59ab +timeCreated: 1514875235 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/components/TestNoBase.cs b/Assets/Plugins/kbengine/components/TestNoBase.cs new file mode 100644 index 00000000..1fa28c07 Binary files /dev/null and b/Assets/Plugins/kbengine/components/TestNoBase.cs differ diff --git a/Assets/Plugins/kbengine/components/TestNoBase.cs.meta b/Assets/Plugins/kbengine/components/TestNoBase.cs.meta new file mode 100644 index 00000000..670b2924 --- /dev/null +++ b/Assets/Plugins/kbengine/components/TestNoBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 4e10edba801dca14fa5dfb37ac48c438 +timeCreated: 1517464316 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/core.meta b/Assets/Plugins/kbengine/core.meta deleted file mode 100644 index 814e7108..00000000 --- a/Assets/Plugins/kbengine/core.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: b3d190adbad467445a06452dd22eb691 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/Plugins/kbengine/core/Bundle.cs b/Assets/Plugins/kbengine/core/Bundle.cs deleted file mode 100644 index 74ffb575..00000000 Binary files a/Assets/Plugins/kbengine/core/Bundle.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Bundle.cs.meta b/Assets/Plugins/kbengine/core/Bundle.cs.meta deleted file mode 100644 index da5c7341..00000000 --- a/Assets/Plugins/kbengine/core/Bundle.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 5a638f2a129aad34482f638792936a53 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/DataTypes.cs b/Assets/Plugins/kbengine/core/DataTypes.cs deleted file mode 100644 index ae032d79..00000000 Binary files a/Assets/Plugins/kbengine/core/DataTypes.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/DataTypes.cs.meta b/Assets/Plugins/kbengine/core/DataTypes.cs.meta deleted file mode 100644 index 79e2874c..00000000 --- a/Assets/Plugins/kbengine/core/DataTypes.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 340fdfb2ad3602a459b2dab705aa0ac3 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Dbg.cs b/Assets/Plugins/kbengine/core/Dbg.cs deleted file mode 100644 index e62a3459..00000000 Binary files a/Assets/Plugins/kbengine/core/Dbg.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Dbg.cs.meta b/Assets/Plugins/kbengine/core/Dbg.cs.meta deleted file mode 100644 index 958e9e09..00000000 --- a/Assets/Plugins/kbengine/core/Dbg.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 49a2401932b29c04daf9e7a073f70844 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Entity.cs b/Assets/Plugins/kbengine/core/Entity.cs deleted file mode 100644 index eb60dc8f..00000000 Binary files a/Assets/Plugins/kbengine/core/Entity.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Entity.cs.meta b/Assets/Plugins/kbengine/core/Entity.cs.meta deleted file mode 100644 index 5f388a5c..00000000 --- a/Assets/Plugins/kbengine/core/Entity.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 21756054ef1114b48bec64809e14d6bc -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/EntityDef.cs b/Assets/Plugins/kbengine/core/EntityDef.cs deleted file mode 100644 index 3cab0850..00000000 Binary files a/Assets/Plugins/kbengine/core/EntityDef.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/EntityDef.cs.meta b/Assets/Plugins/kbengine/core/EntityDef.cs.meta deleted file mode 100644 index a04624e6..00000000 --- a/Assets/Plugins/kbengine/core/EntityDef.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: a548b32f0efab534e826a1efe0c836c6 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Event.cs b/Assets/Plugins/kbengine/core/Event.cs deleted file mode 100644 index 7c43b2a2..00000000 Binary files a/Assets/Plugins/kbengine/core/Event.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Event.cs.meta b/Assets/Plugins/kbengine/core/Event.cs.meta deleted file mode 100644 index f8fc7013..00000000 --- a/Assets/Plugins/kbengine/core/Event.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 957122c6ac3bdff43abc31a8fe1f24ce -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/KBEngine.cs b/Assets/Plugins/kbengine/core/KBEngine.cs deleted file mode 100644 index be1ab46a..00000000 Binary files a/Assets/Plugins/kbengine/core/KBEngine.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/KBEngine.cs.meta b/Assets/Plugins/kbengine/core/KBEngine.cs.meta deleted file mode 100644 index 3e53093c..00000000 --- a/Assets/Plugins/kbengine/core/KBEngine.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 2b2ff6108917da042ac83e9c114a30c6 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Mailbox.cs b/Assets/Plugins/kbengine/core/Mailbox.cs deleted file mode 100644 index df08676d..00000000 Binary files a/Assets/Plugins/kbengine/core/Mailbox.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Mailbox.cs.meta b/Assets/Plugins/kbengine/core/Mailbox.cs.meta deleted file mode 100644 index ade0b25b..00000000 --- a/Assets/Plugins/kbengine/core/Mailbox.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: f3903878f9ee579439c96b5b3326f87d -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Math.cs b/Assets/Plugins/kbengine/core/Math.cs deleted file mode 100644 index 105fc612..00000000 Binary files a/Assets/Plugins/kbengine/core/Math.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Math.cs.meta b/Assets/Plugins/kbengine/core/Math.cs.meta deleted file mode 100644 index 965e95de..00000000 --- a/Assets/Plugins/kbengine/core/Math.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e19fb5f5000e2f04db5bc7b13bcf9fc4 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/MemoryStream.cs b/Assets/Plugins/kbengine/core/MemoryStream.cs deleted file mode 100644 index 2f9d7b39..00000000 Binary files a/Assets/Plugins/kbengine/core/MemoryStream.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/MemoryStream.cs.meta b/Assets/Plugins/kbengine/core/MemoryStream.cs.meta deleted file mode 100644 index aeb7408e..00000000 --- a/Assets/Plugins/kbengine/core/MemoryStream.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7cd951599efe5c34b8eae455763dbc38 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Message.cs b/Assets/Plugins/kbengine/core/Message.cs deleted file mode 100644 index feec3410..00000000 Binary files a/Assets/Plugins/kbengine/core/Message.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Message.cs.meta b/Assets/Plugins/kbengine/core/Message.cs.meta deleted file mode 100644 index ef569c6f..00000000 --- a/Assets/Plugins/kbengine/core/Message.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: c930a8a27926f714c844d5195a830ebd -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/MessageReader.cs b/Assets/Plugins/kbengine/core/MessageReader.cs deleted file mode 100644 index d2f03827..00000000 Binary files a/Assets/Plugins/kbengine/core/MessageReader.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/MessageReader.cs.meta b/Assets/Plugins/kbengine/core/MessageReader.cs.meta deleted file mode 100644 index 5ba32424..00000000 --- a/Assets/Plugins/kbengine/core/MessageReader.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 769630dfa67afc34692c8b46a8e7e34e -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Method.cs b/Assets/Plugins/kbengine/core/Method.cs deleted file mode 100644 index c0651c7e..00000000 Binary files a/Assets/Plugins/kbengine/core/Method.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Method.cs.meta b/Assets/Plugins/kbengine/core/Method.cs.meta deleted file mode 100644 index 92f9306a..00000000 --- a/Assets/Plugins/kbengine/core/Method.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 76cfc9b80877e2448b3d931793332032 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/NetworkInterface.cs b/Assets/Plugins/kbengine/core/NetworkInterface.cs deleted file mode 100644 index c8d7f5cb..00000000 Binary files a/Assets/Plugins/kbengine/core/NetworkInterface.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/NetworkInterface.cs.meta b/Assets/Plugins/kbengine/core/NetworkInterface.cs.meta deleted file mode 100644 index a04bc5fa..00000000 --- a/Assets/Plugins/kbengine/core/NetworkInterface.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 7bc629056da1ae04fb6fd1ed464b97df -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Property.cs b/Assets/Plugins/kbengine/core/Property.cs deleted file mode 100644 index 07fa3e60..00000000 Binary files a/Assets/Plugins/kbengine/core/Property.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Property.cs.meta b/Assets/Plugins/kbengine/core/Property.cs.meta deleted file mode 100644 index aa2ad115..00000000 --- a/Assets/Plugins/kbengine/core/Property.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: dcb57a55272ffc842877a65bd4ce7da6 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/ScriptModule.cs b/Assets/Plugins/kbengine/core/ScriptModule.cs deleted file mode 100644 index e8ac9a43..00000000 Binary files a/Assets/Plugins/kbengine/core/ScriptModule.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/ScriptModule.cs.meta b/Assets/Plugins/kbengine/core/ScriptModule.cs.meta deleted file mode 100644 index c234cc06..00000000 --- a/Assets/Plugins/kbengine/core/ScriptModule.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 9dd3d50d2a5b7344bae542e9a348dbc9 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/StreamRWBinder.cs b/Assets/Plugins/kbengine/core/StreamRWBinder.cs deleted file mode 100644 index dd0c0111..00000000 Binary files a/Assets/Plugins/kbengine/core/StreamRWBinder.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/StreamRWBinder.cs.meta b/Assets/Plugins/kbengine/core/StreamRWBinder.cs.meta deleted file mode 100644 index 349dbd45..00000000 --- a/Assets/Plugins/kbengine/core/StreamRWBinder.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: e8aee5c94ecc41c43b67ae27651db345 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/core/Types.cs b/Assets/Plugins/kbengine/core/Types.cs deleted file mode 100644 index 0571cb98..00000000 Binary files a/Assets/Plugins/kbengine/core/Types.cs and /dev/null differ diff --git a/Assets/Plugins/kbengine/core/Types.cs.meta b/Assets/Plugins/kbengine/core/Types.cs.meta deleted file mode 100644 index d1a3a76a..00000000 --- a/Assets/Plugins/kbengine/core/Types.cs.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 850881ee44f9fb8459705da7d5b9fef6 -MonoImporter: - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins.meta new file mode 100644 index 00000000..4935d561 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: cf95b448738cc194a9bfd42cafee108c +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AccountBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AccountBase.cs new file mode 100644 index 00000000..4e22b9fd --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AccountBase.cs @@ -0,0 +1,307 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class Account : AccountBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Account.def + // Please inherit and implement "class Account : AccountBase" + public abstract class AccountBase : Entity + { + public EntityBaseEntityCall_AccountBase baseEntityCall = null; + public EntityCellEntityCall_AccountBase cellEntityCall = null; + + public UInt64 lastSelCharacter = 0; + public virtual void onLastSelCharacterChanged(UInt64 oldValue) {} + + public abstract void onCreateAvatarResult(Byte arg1, AVATAR_INFOS arg2); + public abstract void onRemoveAvatar(UInt64 arg1); + public abstract void onReqAvatarList(AVATAR_INFOS_LIST arg1); + + public AccountBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_AccountBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_AccountBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Account"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + case 10005: + Byte onCreateAvatarResult_arg1 = stream.readUint8(); + AVATAR_INFOS onCreateAvatarResult_arg2 = ((DATATYPE_AVATAR_INFOS)method.args[1]).createFromStreamEx(stream); + onCreateAvatarResult(onCreateAvatarResult_arg1, onCreateAvatarResult_arg2); + break; + case 3: + UInt64 onRemoveAvatar_arg1 = stream.readUint64(); + onRemoveAvatar(onRemoveAvatar_arg1); + break; + case 10003: + AVATAR_INFOS_LIST onReqAvatarList_arg1 = ((DATATYPE_AVATAR_INFOS_LIST)method.args[0]).createFromStreamEx(stream); + onReqAvatarList(onReqAvatarList_arg1); + break; + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Account"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 2: + UInt64 oldval_lastSelCharacter = lastSelCharacter; + lastSelCharacter = stream.readUint64(); + + if(prop.isBase()) + { + if(inited) + onLastSelCharacterChanged(oldval_lastSelCharacter); + } + else + { + if(inWorld) + onLastSelCharacterChanged(oldval_lastSelCharacter); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["Account"]; + Dictionary pdatas = sm.idpropertys; + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt64 oldval_lastSelCharacter = lastSelCharacter; + Property prop_lastSelCharacter = pdatas[4]; + if(prop_lastSelCharacter.isBase()) + { + if(inited && !inWorld) + onLastSelCharacterChanged(oldval_lastSelCharacter); + } + else + { + if(inWorld) + { + if(prop_lastSelCharacter.isOwnerOnly() && !isPlayer()) + { + } + else + { + onLastSelCharacterChanged(oldval_lastSelCharacter); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AccountBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AccountBase.cs.meta new file mode 100644 index 00000000..a782ab92 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AccountBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 00ce159568924944d93e882ffd3c5c6e +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AvatarBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AvatarBase.cs new file mode 100644 index 00000000..0daf1056 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AvatarBase.cs @@ -0,0 +1,1048 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class Avatar : AvatarBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Avatar.def + // Please inherit and implement "class Avatar : AvatarBase" + public abstract class AvatarBase : Entity + { + public EntityBaseEntityCall_AvatarBase baseEntityCall = null; + public EntityCellEntityCall_AvatarBase cellEntityCall = null; + + public Int32 HP = 0; + public virtual void onHPChanged(Int32 oldValue) {} + public Int32 HP_Max = 0; + public virtual void onHP_MaxChanged(Int32 oldValue) {} + public Int32 MP = 0; + public virtual void onMPChanged(Int32 oldValue) {} + public Int32 MP_Max = 0; + public virtual void onMP_MaxChanged(Int32 oldValue) {} + public TestBase component1 = null; + public TestBase component2 = null; + public TestNoBaseBase component3 = null; + public Int32 forbids = 0; + public virtual void onForbidsChanged(Int32 oldValue) {} + public UInt16 level = 0; + public virtual void onLevelChanged(UInt16 oldValue) {} + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public Byte moveSpeed = 50; + public virtual void onMoveSpeedChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public UInt16 own_val = 0; + public virtual void onOwn_valChanged(UInt16 oldValue) {} + public UInt32 spaceUType = 0; + public virtual void onSpaceUTypeChanged(UInt32 oldValue) {} + public SByte state = 0; + public virtual void onStateChanged(SByte oldValue) {} + public Byte subState = 0; + public virtual void onSubStateChanged(Byte oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + public abstract void dialog_addOption(Byte arg1, UInt32 arg2, string arg3, Int32 arg4); + public abstract void dialog_close(); + public abstract void dialog_setText(string arg1, Byte arg2, UInt32 arg3, string arg4); + public abstract void onAddSkill(Int32 arg1); + public abstract void onJump(); + public abstract void onRemoveSkill(Int32 arg1); + public abstract void recvDamage(Int32 arg1, Int32 arg2, Int32 arg3, Int32 arg4); + + public AvatarBase() + { + foreach (System.Reflection.Assembly ass in AppDomain.CurrentDomain.GetAssemblies()) + { + Type entityComponentScript = ass.GetType("KBEngine.Test"); + if(entityComponentScript != null) + { + component1 = (TestBase)Activator.CreateInstance(entityComponentScript); + component1.owner = this; + component1.entityComponentPropertyID = 16; + component1.name_ = "Test"; + } + } + + if(component1 == null) + throw new Exception("Please inherit and implement, such as: \"class Test : TestBase\""); + + foreach (System.Reflection.Assembly ass in AppDomain.CurrentDomain.GetAssemblies()) + { + Type entityComponentScript = ass.GetType("KBEngine.Test"); + if(entityComponentScript != null) + { + component2 = (TestBase)Activator.CreateInstance(entityComponentScript); + component2.owner = this; + component2.entityComponentPropertyID = 21; + component2.name_ = "Test"; + } + } + + if(component2 == null) + throw new Exception("Please inherit and implement, such as: \"class Test : TestBase\""); + + foreach (System.Reflection.Assembly ass in AppDomain.CurrentDomain.GetAssemblies()) + { + Type entityComponentScript = ass.GetType("KBEngine.TestNoBase"); + if(entityComponentScript != null) + { + component3 = (TestNoBaseBase)Activator.CreateInstance(entityComponentScript); + component3.owner = this; + component3.entityComponentPropertyID = 22; + component3.name_ = "TestNoBase"; + } + } + + if(component3 == null) + throw new Exception("Please inherit and implement, such as: \"class TestNoBase : TestNoBaseBase\""); + + } + + public override void onComponentsEnterworld() + { + component1.onEnterworld(); + component2.onEnterworld(); + component3.onEnterworld(); + } + + public override void onComponentsLeaveworld() + { + component1.onLeaveworld(); + component2.onLeaveworld(); + component3.onLeaveworld(); + } + + public override List getComponents(string componentName, bool all) + { + List founds = new List(); + + if (component1.name_ == componentName) + { + founds.Add(component1); + if (!all) + return founds; + } + + if (component2.name_ == componentName) + { + founds.Add(component2); + if (!all) + return founds; + } + + if (component3.name_ == componentName) + { + founds.Add(component3); + if (!all) + return founds; + } + + return founds; + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_AvatarBase(id, className); + component1.onGetBase(); + component2.onGetBase(); + component3.onGetBase(); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_AvatarBase(id, className); + component1.onGetCell(); + component2.onGetCell(); + component3.onGetCell(); + } + + public override void onLoseCell() + { + cellEntityCall = null; + component1.onLoseCell(); + component2.onLoseCell(); + component3.onLoseCell(); + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + component1.onAttached(this); + component2.onAttached(this); + component3.onAttached(this); + } + + public override void detachComponents() + { + component1.onDetached(this); + component2.onDetached(this); + component3.onDetached(this); + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Avatar"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + case 16: + component1.onRemoteMethodCall(methodUtype, stream); + break; + case 21: + component2.onRemoteMethodCall(methodUtype, stream); + break; + case 22: + component3.onRemoteMethodCall(methodUtype, stream); + break; + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + case 10101: + Byte dialog_addOption_arg1 = stream.readUint8(); + UInt32 dialog_addOption_arg2 = stream.readUint32(); + string dialog_addOption_arg3 = stream.readUnicode(); + Int32 dialog_addOption_arg4 = stream.readInt32(); + dialog_addOption(dialog_addOption_arg1, dialog_addOption_arg2, dialog_addOption_arg3, dialog_addOption_arg4); + break; + case 10104: + dialog_close(); + break; + case 10102: + string dialog_setText_arg1 = stream.readUnicode(); + Byte dialog_setText_arg2 = stream.readUint8(); + UInt32 dialog_setText_arg3 = stream.readUint32(); + string dialog_setText_arg4 = stream.readUnicode(); + dialog_setText(dialog_setText_arg1, dialog_setText_arg2, dialog_setText_arg3, dialog_setText_arg4); + break; + case 12: + Int32 onAddSkill_arg1 = stream.readInt32(); + onAddSkill(onAddSkill_arg1); + break; + case 7: + onJump(); + break; + case 13: + Int32 onRemoveSkill_arg1 = stream.readInt32(); + onRemoveSkill(onRemoveSkill_arg1); + break; + case 16: + Int32 recvDamage_arg1 = stream.readInt32(); + Int32 recvDamage_arg2 = stream.readInt32(); + Int32 recvDamage_arg3 = stream.readInt32(); + Int32 recvDamage_arg4 = stream.readInt32(); + recvDamage(recvDamage_arg1, recvDamage_arg2, recvDamage_arg3, recvDamage_arg4); + break; + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Avatar"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + case 16: + component1.onUpdatePropertys(_t_child_utype, stream, -1); + break; + case 21: + component2.onUpdatePropertys(_t_child_utype, stream, -1); + break; + case 22: + component3.onUpdatePropertys(_t_child_utype, stream, -1); + break; + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 47001: + Int32 oldval_HP = HP; + HP = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onHPChanged(oldval_HP); + } + else + { + if(inWorld) + onHPChanged(oldval_HP); + } + + break; + case 47002: + Int32 oldval_HP_Max = HP_Max; + HP_Max = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onHP_MaxChanged(oldval_HP_Max); + } + else + { + if(inWorld) + onHP_MaxChanged(oldval_HP_Max); + } + + break; + case 47003: + Int32 oldval_MP = MP; + MP = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onMPChanged(oldval_MP); + } + else + { + if(inWorld) + onMPChanged(oldval_MP); + } + + break; + case 47004: + Int32 oldval_MP_Max = MP_Max; + MP_Max = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onMP_MaxChanged(oldval_MP_Max); + } + else + { + if(inWorld) + onMP_MaxChanged(oldval_MP_Max); + } + + break; + case 16: + component1.createFromStream(stream); + break; + case 21: + component2.createFromStream(stream); + break; + case 22: + component3.createFromStream(stream); + break; + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 47005: + Int32 oldval_forbids = forbids; + forbids = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onForbidsChanged(oldval_forbids); + } + else + { + if(inWorld) + onForbidsChanged(oldval_forbids); + } + + break; + case 41002: + UInt16 oldval_level = level; + level = stream.readUint16(); + + if(prop.isBase()) + { + if(inited) + onLevelChanged(oldval_level); + } + else + { + if(inWorld) + onLevelChanged(oldval_level); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 11: + Byte oldval_moveSpeed = moveSpeed; + moveSpeed = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onMoveSpeedChanged(oldval_moveSpeed); + } + else + { + if(inWorld) + onMoveSpeedChanged(oldval_moveSpeed); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 6: + UInt16 oldval_own_val = own_val; + own_val = stream.readUint16(); + + if(prop.isBase()) + { + if(inited) + onOwn_valChanged(oldval_own_val); + } + else + { + if(inWorld) + onOwn_valChanged(oldval_own_val); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 41001: + UInt32 oldval_spaceUType = spaceUType; + spaceUType = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onSpaceUTypeChanged(oldval_spaceUType); + } + else + { + if(inWorld) + onSpaceUTypeChanged(oldval_spaceUType); + } + + break; + case 47006: + SByte oldval_state = state; + state = stream.readInt8(); + + if(prop.isBase()) + { + if(inited) + onStateChanged(oldval_state); + } + else + { + if(inWorld) + onStateChanged(oldval_state); + } + + break; + case 47007: + Byte oldval_subState = subState; + subState = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onSubStateChanged(oldval_subState); + } + else + { + if(inWorld) + onSubStateChanged(oldval_subState); + } + + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["Avatar"]; + Dictionary pdatas = sm.idpropertys; + + Int32 oldval_HP = HP; + Property prop_HP = pdatas[4]; + if(prop_HP.isBase()) + { + if(inited && !inWorld) + onHPChanged(oldval_HP); + } + else + { + if(inWorld) + { + if(prop_HP.isOwnerOnly() && !isPlayer()) + { + } + else + { + onHPChanged(oldval_HP); + } + } + } + + Int32 oldval_HP_Max = HP_Max; + Property prop_HP_Max = pdatas[5]; + if(prop_HP_Max.isBase()) + { + if(inited && !inWorld) + onHP_MaxChanged(oldval_HP_Max); + } + else + { + if(inWorld) + { + if(prop_HP_Max.isOwnerOnly() && !isPlayer()) + { + } + else + { + onHP_MaxChanged(oldval_HP_Max); + } + } + } + + Int32 oldval_MP = MP; + Property prop_MP = pdatas[6]; + if(prop_MP.isBase()) + { + if(inited && !inWorld) + onMPChanged(oldval_MP); + } + else + { + if(inWorld) + { + if(prop_MP.isOwnerOnly() && !isPlayer()) + { + } + else + { + onMPChanged(oldval_MP); + } + } + } + + Int32 oldval_MP_Max = MP_Max; + Property prop_MP_Max = pdatas[7]; + if(prop_MP_Max.isBase()) + { + if(inited && !inWorld) + onMP_MaxChanged(oldval_MP_Max); + } + else + { + if(inWorld) + { + if(prop_MP_Max.isOwnerOnly() && !isPlayer()) + { + } + else + { + onMP_MaxChanged(oldval_MP_Max); + } + } + } + + component1.callPropertysSetMethods(); + + component2.callPropertysSetMethods(); + + component3.callPropertysSetMethods(); + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + Int32 oldval_forbids = forbids; + Property prop_forbids = pdatas[11]; + if(prop_forbids.isBase()) + { + if(inited && !inWorld) + onForbidsChanged(oldval_forbids); + } + else + { + if(inWorld) + { + if(prop_forbids.isOwnerOnly() && !isPlayer()) + { + } + else + { + onForbidsChanged(oldval_forbids); + } + } + } + + UInt16 oldval_level = level; + Property prop_level = pdatas[12]; + if(prop_level.isBase()) + { + if(inited && !inWorld) + onLevelChanged(oldval_level); + } + else + { + if(inWorld) + { + if(prop_level.isOwnerOnly() && !isPlayer()) + { + } + else + { + onLevelChanged(oldval_level); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[13]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[14]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + Byte oldval_moveSpeed = moveSpeed; + Property prop_moveSpeed = pdatas[15]; + if(prop_moveSpeed.isBase()) + { + if(inited && !inWorld) + onMoveSpeedChanged(oldval_moveSpeed); + } + else + { + if(inWorld) + { + if(prop_moveSpeed.isOwnerOnly() && !isPlayer()) + { + } + else + { + onMoveSpeedChanged(oldval_moveSpeed); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[16]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + UInt16 oldval_own_val = own_val; + Property prop_own_val = pdatas[17]; + if(prop_own_val.isBase()) + { + if(inited && !inWorld) + onOwn_valChanged(oldval_own_val); + } + else + { + if(inWorld) + { + if(prop_own_val.isOwnerOnly() && !isPlayer()) + { + } + else + { + onOwn_valChanged(oldval_own_val); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + UInt32 oldval_spaceUType = spaceUType; + Property prop_spaceUType = pdatas[18]; + if(prop_spaceUType.isBase()) + { + if(inited && !inWorld) + onSpaceUTypeChanged(oldval_spaceUType); + } + else + { + if(inWorld) + { + if(prop_spaceUType.isOwnerOnly() && !isPlayer()) + { + } + else + { + onSpaceUTypeChanged(oldval_spaceUType); + } + } + } + + SByte oldval_state = state; + Property prop_state = pdatas[19]; + if(prop_state.isBase()) + { + if(inited && !inWorld) + onStateChanged(oldval_state); + } + else + { + if(inWorld) + { + if(prop_state.isOwnerOnly() && !isPlayer()) + { + } + else + { + onStateChanged(oldval_state); + } + } + } + + Byte oldval_subState = subState; + Property prop_subState = pdatas[20]; + if(prop_subState.isBase()) + { + if(inited && !inWorld) + onSubStateChanged(oldval_subState); + } + else + { + if(inWorld) + { + if(prop_subState.isOwnerOnly() && !isPlayer()) + { + } + else + { + onSubStateChanged(oldval_subState); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[21]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[22]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AvatarBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AvatarBase.cs.meta new file mode 100644 index 00000000..2671c72f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/AvatarBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: c10a27029579a474994c79bd193036de +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Blowfish.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Blowfish.cs new file mode 100644 index 00000000..7d32e650 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Blowfish.cs @@ -0,0 +1,531 @@ +namespace KBEngine +{ + using System; + using System.IO; + using System.Text; + using System.Collections; + using System.Collections.Generic; + using System.Security.Cryptography; + + public class Blowfish + { + const int N = 16; + const int KEYBYTES = 8; + private byte[] _key = new byte[0]; + private bool _isGood = true; + + private static RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider(); + + // key的最小和最大大小 + private const int MIN_KEY_SIZE = 32 / 8; + private const int MAX_KEY_SIZE = 448 / 8; + + // 默认key的大小 + private const int DEFAULT_KEY_SIZE = 128 / 8; + + static uint[] _P = + { + 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, + 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, + 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b + }; + static uint[,] _S = + { + { + 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, + 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, + 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, + 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, + 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, + 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, + 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, + 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, + 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, + 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, + 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, + 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, + 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, + 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, + 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, + 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, + 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, + 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, + 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, + 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, + 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, + 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, + 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, + 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, + 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, + 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, + 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, + 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, + 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, + 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, + 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, + 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, + 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, + 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, + 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, + 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, + 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, + 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, + 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, + 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, + 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, + 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, + 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a + }, + { + 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, + 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, + 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, + 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, + 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, + 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, + 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, + 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, + 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, + 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, + 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, + 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, + 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, + 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, + 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, + 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, + 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, + 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, + 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, + 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, + 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, + 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, + 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, + 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, + 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, + 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, + 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, + 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, + 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, + 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, + 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, + 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, + 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, + 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, + 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, + 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, + 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, + 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, + 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, + 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, + 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, + 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, + 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7 + }, + { + 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, + 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, + 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, + 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, + 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, + 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, + 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, + 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, + 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, + 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, + 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, + 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, + 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, + 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, + 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, + 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, + 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, + 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, + 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, + 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, + 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, + 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, + 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, + 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, + 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, + 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, + 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, + 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, + 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, + 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, + 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, + 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, + 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, + 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, + 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, + 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, + 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, + 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, + 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, + 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, + 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, + 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, + 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0 + }, + { + 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, + 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, + 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, + 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, + 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, + 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, + 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, + 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, + 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, + 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, + 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, + 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, + 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, + 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, + 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, + 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, + 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, + 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, + 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, + 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, + 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, + 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, + 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, + 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, + 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, + 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, + 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, + 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, + 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, + 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, + 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, + 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, + 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, + 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, + 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, + 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, + 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, + 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, + 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, + 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, + 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, + 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, + 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6 + } + }; + + uint[] P; + uint[,] S; + + public Blowfish(byte[] key) + { + _key = key; + init(); + } + + public Blowfish(string key) : this(Encoding.Unicode.GetBytes(key)) + { + + } + + public Blowfish(int keySize = DEFAULT_KEY_SIZE) + { + _key = new byte[keySize]; + rngCsp.GetBytes(_key); + init(); + } + + ~Blowfish() + { + } + + public bool isGood() + { + return _isGood; + } + + private void init() + { + if(_key.Length < MIN_KEY_SIZE || _key.Length > MAX_KEY_SIZE) + { + _isGood = false; + Dbg.ERROR_MSG("Blowfish::init: invalid length " + _key.Length); + return; + } + + short i; + short j; + short k; + uint data; + uint datal; + uint datar; + + P = _P.Clone() as uint[]; + S = _S.Clone() as uint[,]; + + j = 0; + for (i = 0; i < N + 2; ++i) + { + data = 0x00000000; + for (k = 0; k < 4; ++k) + { + data = (data << 8) | _key[j]; + j++; + if (j >= _key.Length) + { + j = 0; + } + } + P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) + { + encipher(ref datal, ref datar); + P[i] = datal; + P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) + { + for (j = 0; j < 256; j += 2) + { + encipher(ref datal, ref datar); + + S[i, j] = datal; + S[i, j + 1] = datar; + } + } + + _isGood = true; + } + + private uint f(uint x) + { + ushort a; + ushort b; + ushort c; + ushort d; + uint y; + + d = (ushort)(x & 0x00FF); + x >>= 8; + c = (ushort)(x & 0x00FF); + x >>= 8; + b = (ushort)(x & 0x00FF); + x >>= 8; + a = (ushort)(x & 0x00FF); + //y = ((S[0][a] + S[1][b]) ^ S[2][c]) + S[3][d]; + y = S[0, a] + S[1, b]; + y = y ^ S[2, c]; + y = y + S[3, d]; + + return y; + } + + /// + /// Encrypts a byte array in place. + /// + /// The array to encrypt. + /// The amount to encrypt. + public void encipher(byte[] data, int length) + { + if ((length % 8) != 0) + throw new Exception("Invalid Length"); + + uint xl, xr; + UInt64 prevBlock = 0; + + for (int i = 0; i < length; i += 8) + { + if (prevBlock != 0) + { + UInt64 oldValue = BitConverter.ToUInt64(data, i); + UInt64 ret = oldValue ^ prevBlock; + prevBlock = oldValue; + + data[i] = (byte)ret; + data[i + 1] = (byte)(ret >> 0x8); + data[i + 2] = (byte)(ret >> 0x10); + data[i + 3] = (byte)(ret >> 0x18); + data[i + 4] = (byte)(ret >> 0x20); + data[i + 5] = (byte)(ret >> 0x28); + data[i + 6] = (byte)(ret >> 0x30); + data[i + 7] = (byte)(ret >> 0x38); + } + else + { + prevBlock = BitConverter.ToUInt64(data, i); + } + + // Encode the data in 8 byte blocks. + xl = (uint)((data[i] << 24) | (data[i + 1] << 16) | (data[i + 2] << 8) | data[i + 3]); + xr = (uint)((data[i + 4] << 24) | (data[i + 5] << 16) | (data[i + 6] << 8) | data[i + 7]); + encipher(ref xl, ref xr); + // Now Replace the data. + data[i] = (byte)(xl >> 24); + data[i + 1] = (byte)(xl >> 16); + data[i + 2] = (byte)(xl >> 8); + data[i + 3] = (byte)(xl); + data[i + 4] = (byte)(xr >> 24); + data[i + 5] = (byte)(xr >> 16); + data[i + 6] = (byte)(xr >> 8); + data[i + 7] = (byte)(xr); + } + } + + /// + /// Encrypts 8 bytes of data (1 block) + /// + /// The left part of the 8 bytes. + /// The right part of the 8 bytes. + private void encipher(ref uint xl, ref uint xr) + { + uint Xl; + uint Xr; + uint temp; + short i; + + Xl = xl; + Xr = xr; + + for (i = 0; i < N; ++i) + { + Xl = Xl ^ P[i]; + Xr = f(Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ P[N]; + Xl = Xl ^ P[N + 1]; + + xl = Xl; + xr = Xr; + } + + /// + /// Encrypts string + /// + /// The string to encrypt + /// Encrypted string + public String encipher(String data) + { + byte[] b = Encoding.Unicode.GetBytes(data); + encipher(b, b.Length); + + return Convert.ToBase64String(b); + } + + /// + /// Decrypts a byte array in place. + /// + /// The array to decrypt. + /// The amount to decrypt. + public void decipher(byte[] data, int startIndex, int length) + { + uint xl, xr; + if ((length % 8) != 0) + throw new Exception("Invalid Length"); + + UInt64 prevBlock = 0; + for (int i = 0; i < length; i += 8) + { + // Encode the data in 8 byte blocks. + int index = startIndex + i; + xl = (uint)((data[index] << 24) | (data[index + 1] << 16) | (data[index + 2] << 8) | data[index + 3]); + xr = (uint)((data[index + 4] << 24) | (data[index + 5] << 16) | (data[index + 6] << 8) | data[index + 7]); + decipher(ref xl, ref xr); + // Now Replace the data. + data[index] = (byte)(xl >> 24); + data[index + 1] = (byte)(xl >> 16); + data[index + 2] = (byte)(xl >> 8); + data[index + 3] = (byte)(xl); + data[index + 4] = (byte)(xr >> 24); + data[index + 5] = (byte)(xr >> 16); + data[index + 6] = (byte)(xr >> 8); + data[index + 7] = (byte)(xr); + + if(prevBlock != 0) + { + UInt64 ret = BitConverter.ToUInt64(data, index) ^ prevBlock; + + data[index] = (byte)ret; + data[index + 1] = (byte)(ret >> 0x08); + data[index + 2] = (byte)(ret >> 0x10); + data[index + 3] = (byte)(ret >> 0x18); + data[index + 4] = (byte)(ret >> 0x20); + data[index + 5] = (byte)(ret >> 0x28); + data[index + 6] = (byte)(ret >> 0x30); + data[index + 7] = (byte)(ret >> 0x38); + } + + prevBlock = BitConverter.ToUInt64(data, index); + } + } + + /// + /// Decrypts 8 bytes of data (1 block) + /// + /// The left part of the 8 bytes. + /// The right part of the 8 bytes. + private void decipher(ref uint xl, ref uint xr) + { + uint Xl; + uint Xr; + uint temp; + short i; + + Xl = xl; + Xr = xr; + + for (i = N + 1; i > 1; --i) + { + Xl = Xl ^ P[i]; + Xr = f(Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ P[1]; + Xl = Xl ^ P[0]; + + xl = Xl; + xr = Xr; + } + + /// + /// Decrypt string + /// + /// The String to decrypt + /// Decrypted string + public String decipher(String data) + { + byte[] b = Convert.FromBase64String(data); + decipher(b, 0, b.Length); + + return Encoding.Unicode.GetString(b); + } + + public byte[] key() + { + return _key; + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Blowfish.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Blowfish.cs.meta new file mode 100644 index 00000000..c96b10b1 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Blowfish.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7057ec92d6de68f408c7d94d8abaf02e +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Bundle.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Bundle.cs new file mode 100644 index 00000000..3d1adba7 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Bundle.cs @@ -0,0 +1,261 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + /* + 这个模块将多个数据包打捆在一起 + 由于每个数据包都有最大上限, 向Bundle中写入大量数据将会在内部产生多个MemoryStream + 在send时会全部发送出去 + */ + public class Bundle : ObjectPool + { + public MemoryStream stream = new MemoryStream(); + public List streamList = new List(); + public int numMessage = 0; + public int messageLength = 0; + public Message msgtype = null; + private int _curMsgStreamIndex = 0; + + public Bundle() + { + } + + public void clear() + { + // 把不用的MemoryStream放回缓冲池,以减少垃圾回收的消耗 + for (int i = 0; i < streamList.Count; ++i) + { + if (stream != streamList[i]) + streamList[i].reclaimObject(); + } + + streamList.Clear(); + + if(stream != null) + stream.clear(); + else + stream = MemoryStream.createObject(); + + numMessage = 0; + messageLength = 0; + msgtype = null; + _curMsgStreamIndex = 0; + } + + /// + /// 把自己放回缓冲池 + /// + public void reclaimObject() + { + clear(); + reclaimObject(this); + } + + public void newMessage(Message mt) + { + fini(false); + + msgtype = mt; + numMessage += 1; + + writeUint16(msgtype.id); + + if(msgtype.msglen == -1) + { + writeUint16(0); + messageLength = 0; + } + + _curMsgStreamIndex = 0; + } + + public void writeMsgLength() + { + if(msgtype.msglen != -1) + return; + + MemoryStream stream = this.stream; + if(_curMsgStreamIndex > 0) + { + stream = streamList[streamList.Count - _curMsgStreamIndex]; + } + stream.data()[2] = (Byte)(messageLength & 0xff); + stream.data()[3] = (Byte)(messageLength >> 8 & 0xff); + } + + public void fini(bool issend) + { + if(numMessage > 0) + { + writeMsgLength(); + + streamList.Add(stream); + stream = MemoryStream.createObject(); + } + + if(issend) + { + numMessage = 0; + msgtype = null; + } + + _curMsgStreamIndex = 0; + } + + public void send(NetworkInterfaceBase networkInterface) + { + fini(true); + + if(networkInterface.valid()) + { + for(int i=0; i stream.space()) + { + streamList.Add(stream); + stream = MemoryStream.createObject(); + ++ _curMsgStreamIndex; + } + + messageLength += v; + } + + //--------------------------------------------------------------------------------- + public void writeInt8(SByte v) + { + checkStream(1); + stream.writeInt8(v); + } + + public void writeInt16(Int16 v) + { + checkStream(2); + stream.writeInt16(v); + } + + public void writeInt32(Int32 v) + { + checkStream(4); + stream.writeInt32(v); + } + + public void writeInt64(Int64 v) + { + checkStream(8); + stream.writeInt64(v); + } + + public void writeUint8(Byte v) + { + checkStream(1); + stream.writeUint8(v); + } + + public void writeUint16(UInt16 v) + { + checkStream(2); + stream.writeUint16(v); + } + + public void writeUint32(UInt32 v) + { + checkStream(4); + stream.writeUint32(v); + } + + public void writeUint64(UInt64 v) + { + checkStream(8); + stream.writeUint64(v); + } + + public void writeFloat(float v) + { + checkStream(4); + stream.writeFloat(v); + } + + public void writeDouble(double v) + { + checkStream(8); + stream.writeDouble(v); + } + + public void writeString(string v) + { + checkStream(v.Length + 1); + stream.writeString(v); + } + + public void writeUnicode(string v) + { + writeBlob(System.Text.Encoding.UTF8.GetBytes((string)v)); + } + + public void writeBlob(byte[] v) + { + checkStream(v.Length + 4); + stream.writeBlob(v); + } + + public void writePython(byte[] v) + { + writeBlob(v); + } + + public void writeVector2(Vector2 v) + { + checkStream(8); + stream.writeVector2(v); + } + + public void writeVector3(Vector3 v) + { + checkStream(12); + stream.writeVector3(v); + } + + public void writeVector4(Vector4 v) + { + checkStream(16); + stream.writeVector4(v); + } + + public void writeEntitycall(byte[] v) + { + checkStream(16); + + UInt64 cid = 0; + Int32 id = 0; + UInt16 type = 0; + UInt16 utype = 0; + + stream.writeUint64(cid); + stream.writeInt32(id); + stream.writeUint16(type); + stream.writeUint16(utype); + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Bundle.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Bundle.cs.meta new file mode 100644 index 00000000..d588eb34 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Bundle.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 92a3925a9aa2c6441b48903c3b914b65 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ClientSDKUpdater.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ClientSDKUpdater.cs new file mode 100644 index 00000000..acfa9548 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ClientSDKUpdater.cs @@ -0,0 +1,158 @@ +namespace KBEngine +{ +#if UNITY_EDITOR + using UnityEngine; + using UnityEditor; + using System.Collections; + using System; + using System.IO; + using KBEngine; + + public class ClientSDKUpdater : MonoBehaviour + { + string warnUpdateSDK = ""; + MemoryStream sdkFileStream = null; + int downloadFiles = 0; + string sdkPath = ""; + string sdkTempPath = ""; + string sdkBakPath = ""; + + void Start() + { + string kbengineCoreFile = "KBEngine.cs"; + string[] res = System.IO.Directory.GetFiles(Application.dataPath, kbengineCoreFile, SearchOption.AllDirectories); + sdkPath = res[0].Replace(kbengineCoreFile, "").Replace("\\", "/"); + sdkPath = sdkPath.Remove(sdkPath.Length - 1, 1); + + sdkTempPath = sdkPath + "_temp"; + sdkBakPath = sdkPath + "_bak"; + + warnUpdateSDK = "Version does not match the server.\nClick to update KBEnginePlugin!\nPull from: " + KBEngineApp.app.getInitArgs().ip + ":" + KBEngineApp.app.getInitArgs().port; + installEvents(); + + GameObject[] objs = FindObjectsOfType(typeof(GameObject)) as GameObject[]; + foreach (GameObject child in objs) + { + if (!child.gameObject.GetComponent() && + !child.gameObject.GetComponent() && + !child.gameObject.GetComponent()) + { + child.gameObject.SetActive(false); + } + } + } + + public virtual void installEvents() + { + Event.registerIn("onImportClientSDK", this, "onImportClientSDK"); + } + + protected virtual void OnDestroy() + { + KBEngine.Event.deregisterOut(this); + } + + public void onImportClientSDK(int remainingFiles, string fileName, int fileSize, byte[] fileDatas) + { + if (sdkFileStream == null) + sdkFileStream = MemoryStream.createObject(); + + sdkFileStream.append(fileDatas, (uint)sdkFileStream.rpos, (uint)fileDatas.Length); + + warnUpdateSDK = "Download:" + fileName + " -> " + sdkFileStream.length() + "/" + fileSize + "bytes! " + (int)(((float)downloadFiles / (float)(downloadFiles + remainingFiles)) * 100) + "%"; + Debug.Log(warnUpdateSDK); + + if (sdkFileStream.length() == fileSize) + { + Debug.Log("onImportClientSDK: " + fileName + "->" + fileSize + "bytes success!"); + + string path = Path.GetDirectoryName(sdkTempPath + "//" + fileName); + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + StreamWriter sw; + FileInfo t = new FileInfo(sdkTempPath + "//" + fileName); + string data = System.Text.Encoding.UTF8.GetString(sdkFileStream.data(), 0, fileSize); + sw = t.CreateText(); + sw.WriteLine(data); + sw.Close(); + sw.Dispose(); + + sdkFileStream.reclaimObject(); + sdkFileStream = null; + downloadFiles += 1; + + if (remainingFiles == 0) + { + warnUpdateSDK = ""; + downloadFiles = 0; + replaceNewSDK(); + } + } + } + + void downloadSDKFromServer() + { + downloadFiles = 0; + + if (Directory.Exists(sdkTempPath)) + Directory.Delete(sdkTempPath, true); + + Directory.CreateDirectory(sdkTempPath); + + if (sdkFileStream != null) + { + sdkFileStream.reclaimObject(); + sdkFileStream = null; + } + + // kbcmd options + string tool_options = "Unity"; + string callbackIP = ""; + UInt16 callbackPort = 0; + int clientWindowSize = (int)KBEngineApp.app.getInitArgs().TCP_RECV_BUFFER_MAX; + + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Loginapp_importClientSDK"]); + bundle.writeString(tool_options); + bundle.writeInt32(clientWindowSize); + bundle.writeString(callbackIP); + bundle.writeUint16(callbackPort); + bundle.send(KBEngineApp.app.networkInterface()); + } + + void replaceNewSDK() + { + System.IO.Directory.Move(sdkPath, sdkBakPath); + System.IO.Directory.Move(sdkTempPath, sdkPath); + + // 删除旧的SKD文件夹 + Directory.Delete(sdkBakPath, true); + + EditorApplication.isPlaying = false; + AssetDatabase.Refresh(); + } + + void OnGUI() + { + if (warnUpdateSDK.Length > 0) + { + GUI.contentColor = Color.red; + GUI.backgroundColor = Color.red; + + if (GUI.Button(new Rect(Screen.width * 0.25f, Screen.height * 0.4f, Screen.width * 0.5f, Screen.height * 0.2f), warnUpdateSDK)) + { + // 从服务器下载新的SDK + downloadSDKFromServer(); + } + } + } + + void Update() + { + + + } + } +#endif +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ClientSDKUpdater.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ClientSDKUpdater.cs.meta new file mode 100644 index 00000000..024f9661 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ClientSDKUpdater.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 33c007f050604fb44ab0afb745771062 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/CustomDataTypes.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/CustomDataTypes.cs new file mode 100644 index 00000000..4a5dc697 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/CustomDataTypes.cs @@ -0,0 +1,283 @@ +/* + Generated by KBEngine! + Please do not modify this file! + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + + + public class DATATYPE_ENTITY_FORBID_COUNTER : DATATYPE_BASE + { + public ENTITY_FORBID_COUNTER createFromStreamEx(MemoryStream stream) + { + UInt32 size = stream.readUint32(); + ENTITY_FORBID_COUNTER datas = new ENTITY_FORBID_COUNTER(); + + while(size > 0) + { + --size; + datas.Add(stream.readInt8()); + }; + + return datas; + } + + public void addToStreamEx(Bundle stream, ENTITY_FORBID_COUNTER v) + { + stream.writeUint32((UInt32)v.Count); + for(int i=0; i 0) + { + --size; + datas.Add(stream.readInt32()); + }; + + return datas; + } + + public void addToStreamEx(Bundle stream, ENTITYID_LIST v) + { + stream.writeUint32((UInt32)v.Count); + for(int i=0; i createFromStreamEx(MemoryStream stream) + { + UInt32 size = stream.readUint32(); + List datas = new List(); + + while(size > 0) + { + --size; + datas.Add(itemType.createFromStreamEx(stream)); + }; + + return datas; + } + + public void addToStreamEx(Bundle stream, List v) + { + stream.writeUint32((UInt32)v.Count); + for(int i=0; i createFromStreamEx(MemoryStream stream) + { + UInt32 size = stream.readUint32(); + List datas = new List(); + + while(size > 0) + { + --size; + datas.Add(stream.readInt64()); + }; + + return datas; + } + + public void addToStreamEx(Bundle stream, List v) + { + stream.writeUint32((UInt32)v.Count); + for(int i=0; i> createFromStreamEx(MemoryStream stream) + { + UInt32 size = stream.readUint32(); + List> datas = new List>(); + + while(size > 0) + { + --size; + datas.Add(itemType.createFromStreamEx(stream)); + }; + + return datas; + } + + public void addToStreamEx(Bundle stream, List> v) + { + stream.writeUint32((UInt32)v.Count); + for(int i=0; i createFromStreamEx(MemoryStream stream) + { + UInt32 size = stream.readUint32(); + List datas = new List(); + + while(size > 0) + { + --size; + datas.Add(stream.readInt32()); + }; + + return datas; + } + + public void addToStreamEx(Bundle stream, List v) + { + stream.writeUint32((UInt32)v.Count); + for(int i=0; i= sbyte.MinValue && v1 <= sbyte.MaxValue; + } + } + + public class DATATYPE_INT16 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readInt16(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeInt16(Convert.ToInt16(v)); + } + + public override object parseDefaultValStr(string v) + { + Int16 ret = 0; + Int16.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if (!KBEMath.isNumeric (v)) + return false; + + decimal v1 = Convert.ToDecimal (v); + return v1 >= Int16.MinValue && v1 <= Int16.MaxValue; + } + } + + public class DATATYPE_INT32 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readInt32(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeInt32(Convert.ToInt32(v)); + } + + public override object parseDefaultValStr(string v) + { + Int32 ret = 0; + Int32.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if (!KBEMath.isNumeric (v)) + return false; + + decimal v1 = Convert.ToDecimal (v); + return v1 >= Int32.MinValue && v1 <= Int32.MaxValue; + } + } + + public class DATATYPE_INT64 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readInt64(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeInt64(Convert.ToInt64(v)); + } + + public override object parseDefaultValStr(string v) + { + Int64 ret = 0; + Int64.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if (!KBEMath.isNumeric (v)) + return false; + + decimal v1 = Convert.ToDecimal (v); + return v1 >= Int64.MinValue && v1 <= Int64.MaxValue; + } + } + + public class DATATYPE_UINT8 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readUint8(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeUint8(Convert.ToByte(v)); + } + + public override object parseDefaultValStr(string v) + { + Byte ret = 0; + Byte.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if (!KBEMath.isNumeric (v)) + return false; + + decimal v1 = Convert.ToDecimal (v); + return v1 >= Byte.MinValue && v1 <= Byte.MaxValue; + } + } + + public class DATATYPE_UINT16 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readUint16(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeUint16(Convert.ToUInt16(v)); + } + + public override object parseDefaultValStr(string v) + { + UInt16 ret = 0; + UInt16.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if (!KBEMath.isNumeric (v)) + return false; + + decimal v1 = Convert.ToDecimal (v); + return v1 >= UInt16.MinValue && v1 <= UInt16.MaxValue; + } + } + + public class DATATYPE_UINT32 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readUint32(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeUint32(Convert.ToUInt32(v)); + } + + public override object parseDefaultValStr(string v) + { + UInt32 ret = 0; + UInt32.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if (!KBEMath.isNumeric (v)) + return false; + + decimal v1 = Convert.ToDecimal (v); + return v1 >= UInt32.MinValue && v1 <= UInt32.MaxValue; + } + } + + public class DATATYPE_UINT64 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readUint64(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeUint64(Convert.ToUInt64(v)); + } + + public override object parseDefaultValStr(string v) + { + UInt64 ret = 0; + UInt64.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if (!KBEMath.isNumeric (v)) + return false; + + decimal v1 = Convert.ToDecimal (v); + return v1 >= UInt64.MinValue && v1 <= UInt64.MaxValue; + } + } + + public class DATATYPE_FLOAT : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readFloat(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeFloat((float)Convert.ToDouble(v)); + } + + public override object parseDefaultValStr(string v) + { + float ret = 0.0f; + float.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if(v is float) + return (float)v >= float.MinValue && (float)v <= float.MaxValue; + else if(v is double) + return (double)v >= float.MinValue && (double)v <= float.MaxValue; + + return false; + } + } + + public class DATATYPE_DOUBLE : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readDouble(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeDouble(Convert.ToDouble(v)); + } + + public override object parseDefaultValStr(string v) + { + double ret = 0.0; + double.TryParse(v, out ret); + return ret; + } + + public override bool isSameType(object v) + { + if(v is float) + return (float)v >= double.MinValue && (float)v <= double.MaxValue; + else if(v is double) + return (double)v >= double.MinValue && (double)v <= double.MaxValue; + + return false; + } + } + + public class DATATYPE_STRING : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readString(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeString(Convert.ToString(v)); + } + + public override object parseDefaultValStr(string v) + { + return v; + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(string); + } + } + + public class DATATYPE_VECTOR2 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return new Vector2(stream.readFloat(), stream.readFloat()); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeFloat(((Vector2)v).x); + stream.writeFloat(((Vector2)v).y); + } + + public override object parseDefaultValStr(string v) + { + return new Vector2(0.0f, 0.0f); + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(Vector2); + } + } + + public class DATATYPE_VECTOR3 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return new Vector3(stream.readFloat(), stream.readFloat(), stream.readFloat()); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeFloat(((Vector3)v).x); + stream.writeFloat(((Vector3)v).y); + stream.writeFloat(((Vector3)v).z); + } + + public override object parseDefaultValStr(string v) + { + return new Vector3(0.0f, 0.0f, 0.0f); + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(Vector3); + } + } + + public class DATATYPE_VECTOR4 : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return new Vector4(stream.readFloat(), stream.readFloat(), stream.readFloat(), stream.readFloat()); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeFloat(((Vector4)v).x); + stream.writeFloat(((Vector4)v).y); + stream.writeFloat(((Vector4)v).z); + stream.writeFloat(((Vector4)v).w); + } + + public override object parseDefaultValStr(string v) + { + return new Vector4(0.0f, 0.0f, 0.0f, 0.0f); + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(Vector4); + } + } + + public class DATATYPE_PYTHON : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readBlob(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeBlob((byte[])v); + } + + public override object parseDefaultValStr(string v) + { + return new byte[0]; + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(byte[]); + } + } + + public class DATATYPE_UNICODE : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return System.Text.Encoding.UTF8.GetString(stream.readBlob()); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeBlob(System.Text.Encoding.UTF8.GetBytes((string)v)); + } + + public override object parseDefaultValStr(string v) + { + return v; + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(string); + } + } + + public class DATATYPE_ENTITYCALL : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readBlob(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeBlob((byte[])v); + } + + public override object parseDefaultValStr(string v) + { + return new byte[0]; + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(byte[]); + } + } + + public class DATATYPE_BLOB : DATATYPE_BASE + { + public override object createFromStream(MemoryStream stream) + { + return stream.readBlob(); + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeBlob((byte[])v); + } + + public override object parseDefaultValStr(string v) + { + return new byte[0]; + } + + public override bool isSameType(object v) + { + return v != null && v.GetType() == typeof(byte[]); + } + } + + public class DATATYPE_ARRAY : DATATYPE_BASE + { + public object vtype; + + public override void bind() + { + if(vtype.GetType ().BaseType.ToString() == "KBEngine.DATATYPE_BASE") + ((DATATYPE_BASE)vtype).bind(); + else + if(EntityDef.id2datatypes.ContainsKey((UInt16)vtype)) + vtype = EntityDef.id2datatypes[(UInt16)vtype]; + } + + public override object createFromStream(MemoryStream stream) + { + UInt32 size = stream.readUint32(); + List datas = new List(); + + while(size > 0) + { + size--; + // datas.Add(((DATATYPE_BASE)vtype).createFromStream(stream)); + }; + + return datas; + } + + public override void addToStream(Bundle stream, object v) + { + stream.writeUint32((UInt32)((List)v).Count); + for(int i=0; i<((List)v).Count; i++) + { + // ((DATATYPE_BASE)vtype).addToStream(stream, ((List)v)[i]); + } + } + + public override object parseDefaultValStr(string v) + { + return new byte[0]; + } + + public override bool isSameType(object v) + { + if(vtype.GetType ().BaseType.ToString() != "KBEngine.DATATYPE_BASE") + { + Dbg.ERROR_MSG(string.Format("DATATYPE_ARRAY::isSameType: has not bind! baseType={0}", + vtype.GetType ().BaseType.ToString())); + return false; + } + + if(v == null || v.GetType() != typeof(List)) + { + return false; + } + + for(int i=0; i<((List)v).Count; i++) + { + if(!((DATATYPE_BASE)vtype).isSameType(((List)v)[i])) + { + return false; + } + } + + return true; + } + } + + public class DATATYPE_FIXED_DICT : DATATYPE_BASE + { + public string implementedBy = ""; + public Dictionary dicttype = new Dictionary(); + + public override void bind() + { + string[] keys = new string[dicttype.Keys.Count]; + dicttype.Keys.CopyTo(keys, 0); + + foreach(string itemkey in keys) + { + object type = dicttype[itemkey]; + + if(type.GetType ().BaseType.ToString() == "KBEngine.DATATYPE_BASE") + ((DATATYPE_BASE)type).bind(); + else + if(EntityDef.id2datatypes.ContainsKey((UInt16)type)) + dicttype[itemkey] = EntityDef.id2datatypes[(UInt16)type]; + } + } + + public override object createFromStream(MemoryStream stream) + { + Dictionary datas = new Dictionary(); + foreach(string itemkey in dicttype.Keys) + { + // datas[itemkey] = ((DATATYPE_BASE)dicttype[itemkey]).createFromStream(stream); + } + + return datas; + } + + public override void addToStream(Bundle stream, object v) + { + foreach(string itemkey in dicttype.Keys) + { + // ((DATATYPE_BASE)dicttype[itemkey]).addToStream(stream, ((Dictionary)v)[itemkey]); + } + } + + public override object parseDefaultValStr(string v) + { + Dictionary datas = new Dictionary(); + foreach(string itemkey in dicttype.Keys) + { + datas[itemkey] = ((DATATYPE_BASE)dicttype[itemkey]).parseDefaultValStr(""); + } + + return datas; + } + + public override bool isSameType(object v) + { + if(v == null || v.GetType() != typeof(Dictionary)) + return false; + + foreach(KeyValuePair item in dicttype) + { + object value; + if(((Dictionary)v).TryGetValue(item.Key, out value)) + { + if(!((DATATYPE_BASE)item.Value).isSameType(value)) + { + return false; + } + } + else + { + return false; + } + } + + return true; + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/DataTypes.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/DataTypes.cs.meta new file mode 100644 index 00000000..09eb2e45 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/DataTypes.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 3b2697deb083d1149a9136accbc6a7ed +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Dbg.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Dbg.cs new file mode 100644 index 00000000..34f96032 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Dbg.cs @@ -0,0 +1,78 @@ +using UnityEngine; +using KBEngine; +using System; +using System.Collections; +using System.Collections.Generic; + +namespace KBEngine +{ + public enum DEBUGLEVEL : int + { + DEBUG = 0, + INFO, + WARNING, + ERROR, + + NOLOG, // 放在最后面,使用这个时表示不输出任何日志(!!!慎用!!!) + } + + public class Dbg + { + static public DEBUGLEVEL debugLevel = DEBUGLEVEL.DEBUG; + +#if UNITY_EDITOR + static Dictionary _profiles = new Dictionary(); +#endif + + public static string getHead() + { + return "[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff") + "] "; + } + + public static void INFO_MSG(object s) + { + if (DEBUGLEVEL.INFO >= debugLevel) + Debug.Log(getHead() + s); + } + + public static void DEBUG_MSG(object s) + { + if (DEBUGLEVEL.DEBUG >= debugLevel) + Debug.Log(getHead() + s); + } + + public static void WARNING_MSG(object s) + { + if (DEBUGLEVEL.WARNING >= debugLevel) + Debug.LogWarning(getHead() + s); + } + + public static void ERROR_MSG(object s) + { + if (DEBUGLEVEL.ERROR >= debugLevel) + Debug.LogError(getHead() + s); + } + + public static void profileStart(string name) + { +#if UNITY_EDITOR + Profile p = null; + if(!_profiles.TryGetValue(name, out p)) + { + p = new Profile(name); + _profiles.Add(name, p); + } + + p.start(); +#endif + } + + public static void profileEnd(string name) + { +#if UNITY_EDITOR + _profiles[name].end(); +#endif + } + + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Dbg.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Dbg.cs.meta new file mode 100644 index 00000000..c0aea1a1 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Dbg.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b11dea249324a154fb6a45f172eb36c9 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EncryptionFilter.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EncryptionFilter.cs new file mode 100644 index 00000000..cf96e9a9 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EncryptionFilter.cs @@ -0,0 +1,190 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + public abstract class EncryptionFilter + { + public abstract void encrypt(MemoryStream stream); + + public abstract void decrypt(MemoryStream stream); + public abstract void decrypt(byte[] buffer, int startIndex, int length); + + public abstract bool send(PacketSenderBase sender, MemoryStream stream); + public abstract bool recv(MessageReaderBase reader, byte[] buffer, UInt32 rpos, UInt32 len); + } + + + class BlowfishFilter : EncryptionFilter + { + private Blowfish _blowfish = new Blowfish(); + + private MemoryStream _packet = new MemoryStream(); + MemoryStream _enctyptStrem = new MemoryStream(); + + private UINT8 _padSize = 0; + private UInt16 _packLen = 0; + const UInt32 BLOCK_SIZE = 8; + const UInt32 MIN_PACKET_SIZE = sizeof(UInt16) + 1 + BLOCK_SIZE; + + public BlowfishFilter() + { + } + + ~BlowfishFilter() + { + } + + public byte[] key() + { + return _blowfish.key(); + } + + public override void encrypt(MemoryStream stream) + { + int padSize = 0; + if (stream.length() % BLOCK_SIZE != 0) + { + padSize = (int)(BLOCK_SIZE - (stream.length() % BLOCK_SIZE)); + stream.wpos += padSize; + + if(stream.wpos > MemoryStream.BUFFER_MAX) + Debug.LogError("BlowfishFilter::encrypt: stream.wpos(" + stream.wpos + ") > MemoryStream.BUFFER_MAX(" + MemoryStream.BUFFER_MAX + ")!"); + } + + _blowfish.encipher(stream.data(), (int)stream.length()); + + UInt16 packLen = (UInt16)(stream.length() + 1); + _enctyptStrem.writeUint16(packLen); + _enctyptStrem.writeUint8((UINT8)padSize); + _enctyptStrem.append(stream.data(), (UInt32)stream.rpos, stream.length()); + + stream.swap(_enctyptStrem); + _enctyptStrem.clear(); + } + + public override void decrypt(MemoryStream stream) + { + _blowfish.decipher(stream.data(), stream.rpos, (int)stream.length()); + } + + public override void decrypt(byte[] buffer, int startIndex, int length) + { + _blowfish.decipher(buffer, startIndex, length); + } + + public override bool send(PacketSenderBase sender, MemoryStream stream) + { + if(!_blowfish.isGood()) + { + Dbg.ERROR_MSG("BlowfishFilter::send: Dropping packet, due to invalid filter"); + return false; + } + + encrypt(stream); + return sender.send(stream); + } + + public override bool recv(MessageReaderBase reader, byte[] buffer, UInt32 rpos, UInt32 len) + { + if (!_blowfish.isGood()) + { + Dbg.ERROR_MSG("BlowfishFilter::recv: Dropping packet, due to invalid filter"); + return false; + } + + if (_packet.length() == 0 && len >= MIN_PACKET_SIZE && BitConverter.ToUInt16(buffer, (int)rpos) - 1 == len - 3) + { + int packLen = BitConverter.ToUInt16(buffer, (int)rpos) - 1; + int padSize = buffer[rpos + 2]; + + decrypt(buffer, (int)(rpos + 3), (int)(len - 3)); + + int length = packLen - padSize; + if (reader != null) + { + reader.process(buffer, rpos + 3, (UInt32)length); + } + + return true; + } + + _packet.append(buffer, rpos, len); + + while(_packet.length() > 0) + { + UInt32 currLen = 0; + int oldwpos = 0; + if (_packLen <= 0) + { + // 如果满足一个最小包则尝试解包, 否则缓存这个包待与下一个包合并然后解包 + if (_packet.length() >= MIN_PACKET_SIZE) + { + _packLen = _packet.readUint16(); + _padSize = _packet.readUint8(); + + _packLen -= 1; + + if (_packet.length() > _packLen) + { + currLen = (UInt32)(_packet.rpos + _packLen); + oldwpos = _packet.wpos; + _packet.wpos = (int)currLen; + } + else if (_packet.length() < _packLen) + { + return false; + } + } + else + { + return false; + } + } + else + { + // 如果上一次有做过解包行为但包还没有完整则继续处理 + // 如果包是完整的下面流程会解密, 如果有多余的内容需要将其剪裁出来待与下一个包合并 + if (_packet.length() > _packLen) + { + currLen = (UInt32)(_packet.rpos + _packLen); + oldwpos = _packet.wpos; + _packet.wpos = (int)currLen; + } + else if (_packet.length() < _packLen) + { + return false; + } + } + + decrypt(_packet); + _packet.wpos -= _padSize; + + // 上面的流程能保证wpos之后不会有多余的包 + // 如果有多余的包数据会放在_recvStream + if (reader != null) + { + reader.process(_packet.data(), (UInt32)_packet.rpos, _packet.length()); + } + + if (currLen > 0) + { + _packet.rpos = (int)currLen; + _packet.wpos = oldwpos; + } + else + { + _packet.clear(); + } + + _packLen = 0; + _padSize = 0; + } + + return true; + } + } +} + diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EncryptionFilter.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EncryptionFilter.cs.meta new file mode 100644 index 00000000..a701386b --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EncryptionFilter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5c3f0e88709430442944acb468015fa6 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Entity.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Entity.cs new file mode 100644 index 00000000..6d92881b --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Entity.cs @@ -0,0 +1,401 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + /* + KBEngine逻辑层的实体基础类 + 所有扩展出的游戏实体都应该继承于该模块 + */ + public class Entity + { + // 当前玩家最后一次同步到服务端的位置与朝向 + // 这两个属性是给引擎KBEngine.cs用的,别的地方不要修改 + public Vector3 _entityLastLocalPos = new Vector3(0f, 0f, 0f); + public Vector3 _entityLastLocalDir = new Vector3(0f, 0f, 0f); + + public Int32 id = 0; + public string className = ""; + public Vector3 position = new Vector3(0.0f, 0.0f, 0.0f); + public Vector3 direction = new Vector3(0.0f, 0.0f, 0.0f); + public float velocity = 0.0f; + + public bool isOnGround = true; + + public object renderObj = null; + + //public EntityCall baseEntityCall = null; + //public EntityCall cellEntityCall = null; + + // enterworld之后设置为true + public bool inWorld = false; + + /// + /// 对于玩家自身来说,它表示是否自己被其它玩家控制了; + /// 对于其它entity来说,表示我本机是否控制了这个entity + /// + public bool isControlled = false; + + // __init__调用之后设置为true + public bool inited = false; + + public static void clear() + { + } + + public Entity() + { + } + + public void destroy() + { + detachComponents(); + onDestroy(); + } + + public virtual void onDestroy() + { + } + + public bool isPlayer() + { + return id == KBEngineApp.app.entity_id; + } + + public virtual void onRemoteMethodCall(MemoryStream stream) + { + // 动态生成 + } + + public virtual void onUpdatePropertys(MemoryStream stream) + { + // 动态生成 + } + + public virtual void onGetBase() + { + // 动态生成 + } + + public virtual void onGetCell() + { + // 动态生成 + } + + public virtual void onLoseCell() + { + // 动态生成 + } + + public virtual void onComponentsEnterworld() + { + // 动态生成, 通知组件onEnterworld + } + + public virtual void onComponentsLeaveworld() + { + // 动态生成, 通知组件onLeaveworld + } + + public virtual EntityCall getBaseEntityCall() + { + // 动态生成 + return null; + } + + public virtual EntityCall getCellEntityCall() + { + // 动态生成 + return null; + } + + /* + KBEngine的实体构造函数,与服务器脚本对应。 + 存在于这样的构造函数是因为KBE需要创建好实体并将属性等数据填充好才能告诉脚本层初始化 + */ + public virtual void __init__() + { + } + + public virtual void callPropertysSetMethods() + { + // 动态生成 + } + + public virtual void attachComponents() + { + // 动态生成 + } + + public virtual void detachComponents() + { + // 动态生成 + } + + public void baseCall(string methodname, params object[] arguments) + { + if(KBEngineApp.app.currserver == "loginapp") + { + Dbg.ERROR_MSG(className + "::baseCall(" + methodname + "), currserver=!" + KBEngineApp.app.currserver); + return; + } + + ScriptModule module = null; + if(!EntityDef.moduledefs.TryGetValue(className, out module)) + { + Dbg.ERROR_MSG("entity::baseCall: entity-module(" + className + ") error, can not find from EntityDef.moduledefs"); + return; + } + + Method method = null; + if(!module.base_methods.TryGetValue(methodname, out method)) + { + Dbg.ERROR_MSG(className + "::baseCall(" + methodname + "), not found method!"); + return; + } + + UInt16 methodID = method.methodUtype; + + if(arguments.Length != method.args.Count) + { + Dbg.ERROR_MSG(className + "::baseCall(" + methodname + "): args(" + (arguments.Length) + "!= " + method.args.Count + ") size is error!"); + return; + } + + EntityCall baseEntityCall = getBaseEntityCall(); + + baseEntityCall.newCall(); + baseEntityCall.bundle.writeUint16(0); + baseEntityCall.bundle.writeUint16(methodID); + + try + { + for(var i=0; i " + v); + + if(isPlayer()) + KBEngineApp.app.entityServerPos(position); + + if(inWorld) + Event.fireOut(EventOutTypes.set_position, this); + } + + public virtual void onUpdateVolatileData() + { + } + + public virtual void onDirectionChanged(Vector3 oldValue) + { + //Dbg.DEBUG_MSG(className + "::set_direction: " + oldValue + " => " + v); + + if(inWorld) + { + direction.x = direction.x * 360 / ((float)System.Math.PI * 2); + direction.y = direction.y * 360 / ((float)System.Math.PI * 2); + direction.z = direction.z * 360 / ((float)System.Math.PI * 2); + Event.fireOut(EventOutTypes.set_direction, this); + } + else + { + direction = oldValue; + } + } + + /// + /// This callback method is called when the local entity control by the client has been enabled or disabled. + /// See the Entity.controlledBy() method in the CellApp server code for more infomation. + /// + /// + /// 对于玩家自身来说,它表示是否自己被其它玩家控制了; + /// 对于其它entity来说,表示我本机是否控制了这个entity + /// + public virtual void onControlled(bool isControlled_) + { + + } + + public virtual List getComponents(string componentName, bool all) + { + List founds = new List(); + return founds; + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Entity.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Entity.cs.meta new file mode 100644 index 00000000..10525c8f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Entity.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: fda3cf613809d294dac07a1cbdf9615e +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCall.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCall.cs new file mode 100644 index 00000000..9132f647 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCall.cs @@ -0,0 +1,116 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + /* + 实体的EntityCall + 关于EntityCall请参考API手册中对它的描述 + https://github.com/kbengine/kbengine/tree/master/docs/api + */ + public class EntityCall + { + // EntityCall的类别 + public enum ENTITYCALL_TYPE + { + ENTITYCALL_TYPE_CELL = 0, // CELL_ENTITYCALL_TYPE + ENTITYCALL_TYPE_BASE = 1 // BASE_ENTITYCALL_TYPE + } + + public Int32 id = 0; + public string className = ""; + public ENTITYCALL_TYPE type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + + public Bundle bundle = null; + + public EntityCall(Int32 eid, string ename) + { + id = eid; + className = ename; + } + + public virtual void __init__() + { + } + + public virtual bool isBase() + { + return type == ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + public virtual bool isCell() + { + return type == ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + /* + 创建新的mail + */ + public Bundle newCall() + { + if(bundle == null) + bundle = Bundle.createObject(); + + if(isCell()) + bundle.newMessage(Messages.messages["Baseapp_onRemoteCallCellMethodFromClient"]); + else + bundle.newMessage(Messages.messages["Entity_onRemoteMethodCall"]); + + bundle.writeInt32(this.id); + + return bundle; + } + + /* + 向服务端发送这个mail + */ + public void sendCall(Bundle inbundle) + { + if(inbundle == null) + inbundle = bundle; + + inbundle.send(KBEngineApp.app.networkInterface()); + + if(inbundle == bundle) + bundle = null; + } + + public Bundle newCall(string methodName, UInt16 entitycomponentPropertyID = 0) + { + if(KBEngineApp.app.currserver == "loginapp") + { + Dbg.ERROR_MSG(className + "::newCall(" + methodName + "), currserver=!" + KBEngineApp.app.currserver); + return null; + } + + ScriptModule module = null; + if(!EntityDef.moduledefs.TryGetValue(className, out module)) + { + Dbg.ERROR_MSG(className + "::newCall: entity-module(" + className + ") error, can not find from EntityDef.moduledefs"); + return null; + } + + Method method = null; + + if(isCell()) + { + method = module.cell_methods[methodName]; + } + else + { + method = module.base_methods[methodName]; + } + + UInt16 methodID = method.methodUtype; + + newCall(); + + bundle.writeUint16(entitycomponentPropertyID); + bundle.writeUint16(methodID); + return bundle; + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCall.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCall.cs.meta new file mode 100644 index 00000000..3f7dfdfd --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCall.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0f41ba7330f78b3409519d8af46f7247 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAccountBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAccountBase.cs new file mode 100644 index 00000000..b432881d --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAccountBase.cs @@ -0,0 +1,85 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Account.def + public class EntityBaseEntityCall_AccountBase : EntityCall + { + + public EntityBaseEntityCall_AccountBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + public void reqAvatarList() + { + Bundle pBundle = newCall("reqAvatarList", 0); + if(pBundle == null) + return; + + sendCall(null); + } + + public void reqCreateAvatar(Byte arg1, string arg2) + { + Bundle pBundle = newCall("reqCreateAvatar", 0); + if(pBundle == null) + return; + + bundle.writeUint8(arg1); + bundle.writeUnicode(arg2); + sendCall(null); + } + + public void reqRemoveAvatar(string arg1) + { + Bundle pBundle = newCall("reqRemoveAvatar", 0); + if(pBundle == null) + return; + + bundle.writeUnicode(arg1); + sendCall(null); + } + + public void reqRemoveAvatarDBID(UInt64 arg1) + { + Bundle pBundle = newCall("reqRemoveAvatarDBID", 0); + if(pBundle == null) + return; + + bundle.writeUint64(arg1); + sendCall(null); + } + + public void selectAvatarGame(UInt64 arg1) + { + Bundle pBundle = newCall("selectAvatarGame", 0); + if(pBundle == null) + return; + + bundle.writeUint64(arg1); + sendCall(null); + } + + } + + public class EntityCellEntityCall_AccountBase : EntityCall + { + + public EntityCellEntityCall_AccountBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAccountBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAccountBase.cs.meta new file mode 100644 index 00000000..f13899d3 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAccountBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 385a18d60b36b9a42808bef7ff8adc53 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAvatarBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAvatarBase.cs new file mode 100644 index 00000000..a83e0918 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAvatarBase.cs @@ -0,0 +1,97 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Avatar.def + public class EntityBaseEntityCall_AvatarBase : EntityCall + { + public EntityBaseEntityCall_TestBase component1 = null; + public EntityBaseEntityCall_TestBase component2 = null; + public EntityBaseEntityCall_TestNoBaseBase component3 = null; + + public EntityBaseEntityCall_AvatarBase(Int32 eid, string ename) : base(eid, ename) + { + component1 = new EntityBaseEntityCall_TestBase(16, id); + component2 = new EntityBaseEntityCall_TestBase(21, id); + component3 = new EntityBaseEntityCall_TestNoBaseBase(22, id); + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_AvatarBase : EntityCall + { + public EntityCellEntityCall_TestBase component1 = null; + public EntityCellEntityCall_TestBase component2 = null; + public EntityCellEntityCall_TestNoBaseBase component3 = null; + + public EntityCellEntityCall_AvatarBase(Int32 eid, string ename) : base(eid, ename) + { + component1 = new EntityCellEntityCall_TestBase(16, id); + component2 = new EntityCellEntityCall_TestBase(21, id); + component3 = new EntityCellEntityCall_TestNoBaseBase(22, id); + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + public void dialog(Int32 arg1, UInt32 arg2) + { + Bundle pBundle = newCall("dialog", 0); + if(pBundle == null) + return; + + bundle.writeInt32(arg1); + bundle.writeUint32(arg2); + sendCall(null); + } + + public void jump() + { + Bundle pBundle = newCall("jump", 0); + if(pBundle == null) + return; + + sendCall(null); + } + + public void relive(Byte arg1) + { + Bundle pBundle = newCall("relive", 0); + if(pBundle == null) + return; + + bundle.writeUint8(arg1); + sendCall(null); + } + + public void requestPull() + { + Bundle pBundle = newCall("requestPull", 0); + if(pBundle == null) + return; + + sendCall(null); + } + + public void useTargetSkill(Int32 arg1, Int32 arg2) + { + Bundle pBundle = newCall("useTargetSkill", 0); + if(pBundle == null) + return; + + bundle.writeInt32(arg1); + bundle.writeInt32(arg2); + sendCall(null); + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAvatarBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAvatarBase.cs.meta new file mode 100644 index 00000000..9184b18a --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallAvatarBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: bf96cbea9fc6161428cde3526c2495df +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallGateBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallGateBase.cs new file mode 100644 index 00000000..371840f9 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallGateBase.cs @@ -0,0 +1,35 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Gate.def + public class EntityBaseEntityCall_GateBase : EntityCall + { + + public EntityBaseEntityCall_GateBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_GateBase : EntityCall + { + + public EntityCellEntityCall_GateBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallGateBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallGateBase.cs.meta new file mode 100644 index 00000000..09ced531 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallGateBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: b264709e805426e4aad1f0a6bc8311db +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallMonsterBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallMonsterBase.cs new file mode 100644 index 00000000..653b3f59 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallMonsterBase.cs @@ -0,0 +1,35 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Monster.def + public class EntityBaseEntityCall_MonsterBase : EntityCall + { + + public EntityBaseEntityCall_MonsterBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_MonsterBase : EntityCall + { + + public EntityCellEntityCall_MonsterBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallMonsterBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallMonsterBase.cs.meta new file mode 100644 index 00000000..23dcf4a8 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallMonsterBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 20ea76de3ca34d2478addb5da4bd0c3d +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallNPCBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallNPCBase.cs new file mode 100644 index 00000000..a155781f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallNPCBase.cs @@ -0,0 +1,35 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/NPC.def + public class EntityBaseEntityCall_NPCBase : EntityCall + { + + public EntityBaseEntityCall_NPCBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_NPCBase : EntityCall + { + + public EntityCellEntityCall_NPCBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallNPCBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallNPCBase.cs.meta new file mode 100644 index 00000000..52152b6c --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallNPCBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ed641cfb63362f444b2ef1172a27ec55 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceBase.cs new file mode 100644 index 00000000..8e5dc35e --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceBase.cs @@ -0,0 +1,35 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Space.def + public class EntityBaseEntityCall_SpaceBase : EntityCall + { + + public EntityBaseEntityCall_SpaceBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_SpaceBase : EntityCall + { + + public EntityCellEntityCall_SpaceBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceBase.cs.meta new file mode 100644 index 00000000..368a8761 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d9250d51471244948a0c7e44bac925f9 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceDuplicateBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceDuplicateBase.cs new file mode 100644 index 00000000..c60d26e2 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceDuplicateBase.cs @@ -0,0 +1,35 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/SpaceDuplicate.def + public class EntityBaseEntityCall_SpaceDuplicateBase : EntityCall + { + + public EntityBaseEntityCall_SpaceDuplicateBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_SpaceDuplicateBase : EntityCall + { + + public EntityCellEntityCall_SpaceDuplicateBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceDuplicateBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceDuplicateBase.cs.meta new file mode 100644 index 00000000..7ab6ada2 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpaceDuplicateBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: bf5e5fef101c4f9408d0337250adada4 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpacesBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpacesBase.cs new file mode 100644 index 00000000..098a4766 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpacesBase.cs @@ -0,0 +1,35 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Spaces.def + public class EntityBaseEntityCall_SpacesBase : EntityCall + { + + public EntityBaseEntityCall_SpacesBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_SpacesBase : EntityCall + { + + public EntityCellEntityCall_SpacesBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpacesBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpacesBase.cs.meta new file mode 100644 index 00000000..a941d924 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpacesBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f6cd804f463e20c4d99bd55701b67f24 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpawnPointBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpawnPointBase.cs new file mode 100644 index 00000000..e772016c --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpawnPointBase.cs @@ -0,0 +1,35 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/SpawnPoint.def + public class EntityBaseEntityCall_SpawnPointBase : EntityCall + { + + public EntityBaseEntityCall_SpawnPointBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_SpawnPointBase : EntityCall + { + + public EntityCellEntityCall_SpawnPointBase(Int32 eid, string ename) : base(eid, ename) + { + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpawnPointBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpawnPointBase.cs.meta new file mode 100644 index 00000000..afb5eb1c --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallSpawnPointBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 4cc30709972eeca44a4dca8795a4b2cd +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestBase.cs new file mode 100644 index 00000000..cb211018 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestBase.cs @@ -0,0 +1,60 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Test.def + public class EntityBaseEntityCall_TestBase : EntityCall + { + public UInt16 entityComponentPropertyID = 0; + + public EntityBaseEntityCall_TestBase(UInt16 ecpID, Int32 eid) : base(eid, "Test") + { + entityComponentPropertyID = ecpID; + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + public void say(Int32 arg1) + { + Bundle pBundle = newCall("say", entityComponentPropertyID); + if(pBundle == null) + return; + + bundle.writeInt32(arg1); + sendCall(null); + } + + } + + public class EntityCellEntityCall_TestBase : EntityCall + { + public UInt16 entityComponentPropertyID = 0; + + public EntityCellEntityCall_TestBase(UInt16 ecpID, Int32 eid) : base(eid, "Test") + { + entityComponentPropertyID = ecpID; + className = "Test"; + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + public void hello(Int32 arg1) + { + Bundle pBundle = newCall("hello", entityComponentPropertyID); + if(pBundle == null) + return; + + bundle.writeInt32(arg1); + sendCall(null); + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestBase.cs.meta new file mode 100644 index 00000000..b506972f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f11acab330724b54a918e69b20b72253 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestNoBaseBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestNoBaseBase.cs new file mode 100644 index 00000000..c8630ec4 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestNoBaseBase.cs @@ -0,0 +1,50 @@ +/* + Generated by KBEngine! + Please do not modify this file! + + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/TestNoBase.def + public class EntityBaseEntityCall_TestNoBaseBase : EntityCall + { + public UInt16 entityComponentPropertyID = 0; + + public EntityBaseEntityCall_TestNoBaseBase(UInt16 ecpID, Int32 eid) : base(eid, "TestNoBase") + { + entityComponentPropertyID = ecpID; + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_BASE; + } + + } + + public class EntityCellEntityCall_TestNoBaseBase : EntityCall + { + public UInt16 entityComponentPropertyID = 0; + + public EntityCellEntityCall_TestNoBaseBase(UInt16 ecpID, Int32 eid) : base(eid, "TestNoBase") + { + entityComponentPropertyID = ecpID; + className = "TestNoBase"; + type = ENTITYCALL_TYPE.ENTITYCALL_TYPE_CELL; + } + + public void hello(Int32 arg1) + { + Bundle pBundle = newCall("hello", entityComponentPropertyID); + if(pBundle == null) + return; + + bundle.writeInt32(arg1); + sendCall(null); + } + + } + } diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestNoBaseBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestNoBaseBase.cs.meta new file mode 100644 index 00000000..940cce9d --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityCallTestNoBaseBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 73e8a8c8a667efe4e9435edd5447f51b +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityComponent.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityComponent.cs new file mode 100644 index 00000000..5e0abdf9 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityComponent.cs @@ -0,0 +1,88 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + using System.Threading; + + /* + 实体组件模块基础类 + */ + public class EntityComponent + { + public UInt16 entityComponentPropertyID = 0; + public UInt16 componentType = 0; + public Int32 ownerID = 0; + public Entity owner = null; + public string name_ = ""; + + public virtual void onAttached(Entity ownerEntity) + { + + } + + public virtual void onDetached(Entity ownerEntity) + { + + } + + public virtual void onEnterworld() + { + } + + public virtual void onLeaveworld() + { + } + + public virtual void onGetBase() + { + // 动态生成 + } + + public virtual void onGetCell() + { + // 动态生成 + } + + public virtual void onLoseCell() + { + // 动态生成 + } + + public virtual ScriptModule getScriptModule() + { + // 动态生成 + return null; + } + + public virtual void onRemoteMethodCall(UInt16 methodUtype, MemoryStream stream) + { + // 动态生成 + } + + public virtual void onUpdatePropertys(UInt16 propUtype, MemoryStream stream, int maxCount) + { + // 动态生成 + } + + public virtual void callPropertysSetMethods() + { + // 动态生成 + } + + public virtual void createFromStream(MemoryStream stream) + { + componentType = (UInt16)stream.readInt32(); + ownerID = stream.readInt32(); + + //UInt16 ComponentDescrsType; + stream.readUint16(); + + UInt16 count = stream.readUint16(); + + if(count > 0) + onUpdatePropertys(0, stream, count); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityComponent.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityComponent.cs.meta new file mode 100644 index 00000000..fc14b16e --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityComponent.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9e6ee1e6ba791f848aa0454cab39a69e +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityDef.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityDef.cs new file mode 100644 index 00000000..6c3c5463 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityDef.cs @@ -0,0 +1,1928 @@ +/* + Generated by KBEngine! + Please do not modify this file! + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + public class EntityDef + { + public static Dictionary datatype2id = new Dictionary(); + public static Dictionary datatypes = new Dictionary(); + public static Dictionary id2datatypes = new Dictionary(); + public static Dictionary entityclass = new Dictionary(); + public static Dictionary moduledefs = new Dictionary(); + public static Dictionary idmoduledefs = new Dictionary(); + + public static bool init() + { + initDataTypes(); + initDefTypes(); + initScriptModules(); + return true; + } + + public static bool reset() + { + clear(); + return init(); + } + + public static void clear() + { + datatype2id.Clear(); + datatypes.Clear(); + id2datatypes.Clear(); + entityclass.Clear(); + moduledefs.Clear(); + idmoduledefs.Clear(); + } + + public static void initDataTypes() + { + datatypes["UINT8"] = new DATATYPE_UINT8(); + datatypes["UINT16"] = new DATATYPE_UINT16(); + datatypes["UINT32"] = new DATATYPE_UINT32(); + datatypes["UINT64"] = new DATATYPE_UINT64(); + + datatypes["INT8"] = new DATATYPE_INT8(); + datatypes["INT16"] = new DATATYPE_INT16(); + datatypes["INT32"] = new DATATYPE_INT32(); + datatypes["INT64"] = new DATATYPE_INT64(); + + datatypes["FLOAT"] = new DATATYPE_FLOAT(); + datatypes["DOUBLE"] = new DATATYPE_DOUBLE(); + + datatypes["STRING"] = new DATATYPE_STRING(); + datatypes["VECTOR2"] = new DATATYPE_VECTOR2(); + + datatypes["VECTOR3"] = new DATATYPE_VECTOR3(); + + datatypes["VECTOR4"] = new DATATYPE_VECTOR4(); + datatypes["PYTHON"] = new DATATYPE_PYTHON(); + + datatypes["UNICODE"] = new DATATYPE_UNICODE(); + datatypes["ENTITYCALL"] = new DATATYPE_ENTITYCALL(); + + datatypes["BLOB"] = new DATATYPE_BLOB(); + } + + public static void initScriptModules() + { + ScriptModule pAccountModule = new ScriptModule("Account"); + EntityDef.moduledefs["Account"] = pAccountModule; + EntityDef.idmoduledefs[1] = pAccountModule; + + Property pAccount_position = new Property(); + pAccount_position.name = "position"; + pAccount_position.properUtype = 40000; + pAccount_position.properFlags = 4; + pAccount_position.aliasID = 1; + Vector3 Account_position_defval = new Vector3(); + pAccount_position.defaultVal = Account_position_defval; + pAccountModule.propertys["position"] = pAccount_position; + + pAccountModule.usePropertyDescrAlias = true; + pAccountModule.idpropertys[(UInt16)pAccount_position.aliasID] = pAccount_position; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), property(position / 40000)."); + + Property pAccount_direction = new Property(); + pAccount_direction.name = "direction"; + pAccount_direction.properUtype = 40001; + pAccount_direction.properFlags = 4; + pAccount_direction.aliasID = 2; + Vector3 Account_direction_defval = new Vector3(); + pAccount_direction.defaultVal = Account_direction_defval; + pAccountModule.propertys["direction"] = pAccount_direction; + + pAccountModule.usePropertyDescrAlias = true; + pAccountModule.idpropertys[(UInt16)pAccount_direction.aliasID] = pAccount_direction; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), property(direction / 40001)."); + + Property pAccount_spaceID = new Property(); + pAccount_spaceID.name = "spaceID"; + pAccount_spaceID.properUtype = 40002; + pAccount_spaceID.properFlags = 16; + pAccount_spaceID.aliasID = 3; + UInt32 Account_spaceID_defval; + UInt32.TryParse("", out Account_spaceID_defval); + pAccount_spaceID.defaultVal = Account_spaceID_defval; + pAccountModule.propertys["spaceID"] = pAccount_spaceID; + + pAccountModule.usePropertyDescrAlias = true; + pAccountModule.idpropertys[(UInt16)pAccount_spaceID.aliasID] = pAccount_spaceID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), property(spaceID / 40002)."); + + Property pAccount_lastSelCharacter = new Property(); + pAccount_lastSelCharacter.name = "lastSelCharacter"; + pAccount_lastSelCharacter.properUtype = 2; + pAccount_lastSelCharacter.properFlags = 32; + pAccount_lastSelCharacter.aliasID = 4; + UInt64 Account_lastSelCharacter_defval; + UInt64.TryParse("0", out Account_lastSelCharacter_defval); + pAccount_lastSelCharacter.defaultVal = Account_lastSelCharacter_defval; + pAccountModule.propertys["lastSelCharacter"] = pAccount_lastSelCharacter; + + pAccountModule.usePropertyDescrAlias = true; + pAccountModule.idpropertys[(UInt16)pAccount_lastSelCharacter.aliasID] = pAccount_lastSelCharacter; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), property(lastSelCharacter / 2)."); + + List pAccount_onCreateAvatarResult_args = new List(); + pAccount_onCreateAvatarResult_args.Add(EntityDef.id2datatypes[2]); + pAccount_onCreateAvatarResult_args.Add(EntityDef.id2datatypes[25]); + + Method pAccount_onCreateAvatarResult = new Method(); + pAccount_onCreateAvatarResult.name = "onCreateAvatarResult"; + pAccount_onCreateAvatarResult.methodUtype = 10005; + pAccount_onCreateAvatarResult.aliasID = 1; + pAccount_onCreateAvatarResult.args = pAccount_onCreateAvatarResult_args; + + pAccountModule.methods["onCreateAvatarResult"] = pAccount_onCreateAvatarResult; + pAccountModule.useMethodDescrAlias = true; + pAccountModule.idmethods[(UInt16)pAccount_onCreateAvatarResult.aliasID] = pAccount_onCreateAvatarResult; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(onCreateAvatarResult / 10005)."); + + List pAccount_onRemoveAvatar_args = new List(); + pAccount_onRemoveAvatar_args.Add(EntityDef.id2datatypes[5]); + + Method pAccount_onRemoveAvatar = new Method(); + pAccount_onRemoveAvatar.name = "onRemoveAvatar"; + pAccount_onRemoveAvatar.methodUtype = 3; + pAccount_onRemoveAvatar.aliasID = 2; + pAccount_onRemoveAvatar.args = pAccount_onRemoveAvatar_args; + + pAccountModule.methods["onRemoveAvatar"] = pAccount_onRemoveAvatar; + pAccountModule.useMethodDescrAlias = true; + pAccountModule.idmethods[(UInt16)pAccount_onRemoveAvatar.aliasID] = pAccount_onRemoveAvatar; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(onRemoveAvatar / 3)."); + + List pAccount_onReqAvatarList_args = new List(); + pAccount_onReqAvatarList_args.Add(EntityDef.id2datatypes[26]); + + Method pAccount_onReqAvatarList = new Method(); + pAccount_onReqAvatarList.name = "onReqAvatarList"; + pAccount_onReqAvatarList.methodUtype = 10003; + pAccount_onReqAvatarList.aliasID = 3; + pAccount_onReqAvatarList.args = pAccount_onReqAvatarList_args; + + pAccountModule.methods["onReqAvatarList"] = pAccount_onReqAvatarList; + pAccountModule.useMethodDescrAlias = true; + pAccountModule.idmethods[(UInt16)pAccount_onReqAvatarList.aliasID] = pAccount_onReqAvatarList; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(onReqAvatarList / 10003)."); + + List pAccount_reqAvatarList_args = new List(); + + Method pAccount_reqAvatarList = new Method(); + pAccount_reqAvatarList.name = "reqAvatarList"; + pAccount_reqAvatarList.methodUtype = 10001; + pAccount_reqAvatarList.aliasID = -1; + pAccount_reqAvatarList.args = pAccount_reqAvatarList_args; + + pAccountModule.methods["reqAvatarList"] = pAccount_reqAvatarList; + pAccountModule.base_methods["reqAvatarList"] = pAccount_reqAvatarList; + + pAccountModule.idbase_methods[pAccount_reqAvatarList.methodUtype] = pAccount_reqAvatarList; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(reqAvatarList / 10001)."); + + List pAccount_reqCreateAvatar_args = new List(); + pAccount_reqCreateAvatar_args.Add(EntityDef.id2datatypes[2]); + pAccount_reqCreateAvatar_args.Add(EntityDef.id2datatypes[12]); + + Method pAccount_reqCreateAvatar = new Method(); + pAccount_reqCreateAvatar.name = "reqCreateAvatar"; + pAccount_reqCreateAvatar.methodUtype = 10002; + pAccount_reqCreateAvatar.aliasID = -1; + pAccount_reqCreateAvatar.args = pAccount_reqCreateAvatar_args; + + pAccountModule.methods["reqCreateAvatar"] = pAccount_reqCreateAvatar; + pAccountModule.base_methods["reqCreateAvatar"] = pAccount_reqCreateAvatar; + + pAccountModule.idbase_methods[pAccount_reqCreateAvatar.methodUtype] = pAccount_reqCreateAvatar; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(reqCreateAvatar / 10002)."); + + List pAccount_reqRemoveAvatar_args = new List(); + pAccount_reqRemoveAvatar_args.Add(EntityDef.id2datatypes[12]); + + Method pAccount_reqRemoveAvatar = new Method(); + pAccount_reqRemoveAvatar.name = "reqRemoveAvatar"; + pAccount_reqRemoveAvatar.methodUtype = 1; + pAccount_reqRemoveAvatar.aliasID = -1; + pAccount_reqRemoveAvatar.args = pAccount_reqRemoveAvatar_args; + + pAccountModule.methods["reqRemoveAvatar"] = pAccount_reqRemoveAvatar; + pAccountModule.base_methods["reqRemoveAvatar"] = pAccount_reqRemoveAvatar; + + pAccountModule.idbase_methods[pAccount_reqRemoveAvatar.methodUtype] = pAccount_reqRemoveAvatar; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(reqRemoveAvatar / 1)."); + + List pAccount_reqRemoveAvatarDBID_args = new List(); + pAccount_reqRemoveAvatarDBID_args.Add(EntityDef.id2datatypes[5]); + + Method pAccount_reqRemoveAvatarDBID = new Method(); + pAccount_reqRemoveAvatarDBID.name = "reqRemoveAvatarDBID"; + pAccount_reqRemoveAvatarDBID.methodUtype = 2; + pAccount_reqRemoveAvatarDBID.aliasID = -1; + pAccount_reqRemoveAvatarDBID.args = pAccount_reqRemoveAvatarDBID_args; + + pAccountModule.methods["reqRemoveAvatarDBID"] = pAccount_reqRemoveAvatarDBID; + pAccountModule.base_methods["reqRemoveAvatarDBID"] = pAccount_reqRemoveAvatarDBID; + + pAccountModule.idbase_methods[pAccount_reqRemoveAvatarDBID.methodUtype] = pAccount_reqRemoveAvatarDBID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(reqRemoveAvatarDBID / 2)."); + + List pAccount_selectAvatarGame_args = new List(); + pAccount_selectAvatarGame_args.Add(EntityDef.id2datatypes[5]); + + Method pAccount_selectAvatarGame = new Method(); + pAccount_selectAvatarGame.name = "selectAvatarGame"; + pAccount_selectAvatarGame.methodUtype = 10004; + pAccount_selectAvatarGame.aliasID = -1; + pAccount_selectAvatarGame.args = pAccount_selectAvatarGame_args; + + pAccountModule.methods["selectAvatarGame"] = pAccount_selectAvatarGame; + pAccountModule.base_methods["selectAvatarGame"] = pAccount_selectAvatarGame; + + pAccountModule.idbase_methods[pAccount_selectAvatarGame.methodUtype] = pAccount_selectAvatarGame; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Account), method(selectAvatarGame / 10004)."); + + ScriptModule pAvatarModule = new ScriptModule("Avatar"); + EntityDef.moduledefs["Avatar"] = pAvatarModule; + EntityDef.idmoduledefs[2] = pAvatarModule; + + Property pAvatar_position = new Property(); + pAvatar_position.name = "position"; + pAvatar_position.properUtype = 40000; + pAvatar_position.properFlags = 4; + pAvatar_position.aliasID = 1; + Vector3 Avatar_position_defval = new Vector3(); + pAvatar_position.defaultVal = Avatar_position_defval; + pAvatarModule.propertys["position"] = pAvatar_position; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_position.aliasID] = pAvatar_position; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(position / 40000)."); + + Property pAvatar_direction = new Property(); + pAvatar_direction.name = "direction"; + pAvatar_direction.properUtype = 40001; + pAvatar_direction.properFlags = 4; + pAvatar_direction.aliasID = 2; + Vector3 Avatar_direction_defval = new Vector3(); + pAvatar_direction.defaultVal = Avatar_direction_defval; + pAvatarModule.propertys["direction"] = pAvatar_direction; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_direction.aliasID] = pAvatar_direction; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(direction / 40001)."); + + Property pAvatar_spaceID = new Property(); + pAvatar_spaceID.name = "spaceID"; + pAvatar_spaceID.properUtype = 40002; + pAvatar_spaceID.properFlags = 16; + pAvatar_spaceID.aliasID = 3; + UInt32 Avatar_spaceID_defval; + UInt32.TryParse("", out Avatar_spaceID_defval); + pAvatar_spaceID.defaultVal = Avatar_spaceID_defval; + pAvatarModule.propertys["spaceID"] = pAvatar_spaceID; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_spaceID.aliasID] = pAvatar_spaceID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(spaceID / 40002)."); + + Property pAvatar_HP = new Property(); + pAvatar_HP.name = "HP"; + pAvatar_HP.properUtype = 47001; + pAvatar_HP.properFlags = 4; + pAvatar_HP.aliasID = 4; + Int32 Avatar_HP_defval; + Int32.TryParse("0", out Avatar_HP_defval); + pAvatar_HP.defaultVal = Avatar_HP_defval; + pAvatarModule.propertys["HP"] = pAvatar_HP; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_HP.aliasID] = pAvatar_HP; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(HP / 47001)."); + + Property pAvatar_HP_Max = new Property(); + pAvatar_HP_Max.name = "HP_Max"; + pAvatar_HP_Max.properUtype = 47002; + pAvatar_HP_Max.properFlags = 4; + pAvatar_HP_Max.aliasID = 5; + Int32 Avatar_HP_Max_defval; + Int32.TryParse("0", out Avatar_HP_Max_defval); + pAvatar_HP_Max.defaultVal = Avatar_HP_Max_defval; + pAvatarModule.propertys["HP_Max"] = pAvatar_HP_Max; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_HP_Max.aliasID] = pAvatar_HP_Max; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(HP_Max / 47002)."); + + Property pAvatar_MP = new Property(); + pAvatar_MP.name = "MP"; + pAvatar_MP.properUtype = 47003; + pAvatar_MP.properFlags = 4; + pAvatar_MP.aliasID = 6; + Int32 Avatar_MP_defval; + Int32.TryParse("0", out Avatar_MP_defval); + pAvatar_MP.defaultVal = Avatar_MP_defval; + pAvatarModule.propertys["MP"] = pAvatar_MP; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_MP.aliasID] = pAvatar_MP; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(MP / 47003)."); + + Property pAvatar_MP_Max = new Property(); + pAvatar_MP_Max.name = "MP_Max"; + pAvatar_MP_Max.properUtype = 47004; + pAvatar_MP_Max.properFlags = 4; + pAvatar_MP_Max.aliasID = 7; + Int32 Avatar_MP_Max_defval; + Int32.TryParse("0", out Avatar_MP_Max_defval); + pAvatar_MP_Max.defaultVal = Avatar_MP_Max_defval; + pAvatarModule.propertys["MP_Max"] = pAvatar_MP_Max; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_MP_Max.aliasID] = pAvatar_MP_Max; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(MP_Max / 47004)."); + + Property pAvatar_component1 = new Property(); + pAvatar_component1.name = "component1"; + pAvatar_component1.properUtype = 16; + pAvatar_component1.properFlags = 253; + pAvatar_component1.aliasID = 8; + pAvatarModule.propertys["component1"] = pAvatar_component1; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_component1.aliasID] = pAvatar_component1; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(component1 / 16)."); + + Property pAvatar_component2 = new Property(); + pAvatar_component2.name = "component2"; + pAvatar_component2.properUtype = 21; + pAvatar_component2.properFlags = 97; + pAvatar_component2.aliasID = 9; + pAvatarModule.propertys["component2"] = pAvatar_component2; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_component2.aliasID] = pAvatar_component2; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(component2 / 21)."); + + Property pAvatar_component3 = new Property(); + pAvatar_component3.name = "component3"; + pAvatar_component3.properUtype = 22; + pAvatar_component3.properFlags = 157; + pAvatar_component3.aliasID = 10; + pAvatarModule.propertys["component3"] = pAvatar_component3; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_component3.aliasID] = pAvatar_component3; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(component3 / 22)."); + + Property pAvatar_forbids = new Property(); + pAvatar_forbids.name = "forbids"; + pAvatar_forbids.properUtype = 47005; + pAvatar_forbids.properFlags = 4; + pAvatar_forbids.aliasID = 11; + Int32 Avatar_forbids_defval; + Int32.TryParse("0", out Avatar_forbids_defval); + pAvatar_forbids.defaultVal = Avatar_forbids_defval; + pAvatarModule.propertys["forbids"] = pAvatar_forbids; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_forbids.aliasID] = pAvatar_forbids; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(forbids / 47005)."); + + Property pAvatar_level = new Property(); + pAvatar_level.name = "level"; + pAvatar_level.properUtype = 41002; + pAvatar_level.properFlags = 8; + pAvatar_level.aliasID = 12; + UInt16 Avatar_level_defval; + UInt16.TryParse("", out Avatar_level_defval); + pAvatar_level.defaultVal = Avatar_level_defval; + pAvatarModule.propertys["level"] = pAvatar_level; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_level.aliasID] = pAvatar_level; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(level / 41002)."); + + Property pAvatar_modelID = new Property(); + pAvatar_modelID.name = "modelID"; + pAvatar_modelID.properUtype = 41006; + pAvatar_modelID.properFlags = 4; + pAvatar_modelID.aliasID = 13; + UInt32 Avatar_modelID_defval; + UInt32.TryParse("0", out Avatar_modelID_defval); + pAvatar_modelID.defaultVal = Avatar_modelID_defval; + pAvatarModule.propertys["modelID"] = pAvatar_modelID; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_modelID.aliasID] = pAvatar_modelID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(modelID / 41006)."); + + Property pAvatar_modelScale = new Property(); + pAvatar_modelScale.name = "modelScale"; + pAvatar_modelScale.properUtype = 41007; + pAvatar_modelScale.properFlags = 4; + pAvatar_modelScale.aliasID = 14; + Byte Avatar_modelScale_defval; + Byte.TryParse("30", out Avatar_modelScale_defval); + pAvatar_modelScale.defaultVal = Avatar_modelScale_defval; + pAvatarModule.propertys["modelScale"] = pAvatar_modelScale; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_modelScale.aliasID] = pAvatar_modelScale; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(modelScale / 41007)."); + + Property pAvatar_moveSpeed = new Property(); + pAvatar_moveSpeed.name = "moveSpeed"; + pAvatar_moveSpeed.properUtype = 11; + pAvatar_moveSpeed.properFlags = 4; + pAvatar_moveSpeed.aliasID = 15; + Byte Avatar_moveSpeed_defval; + Byte.TryParse("50", out Avatar_moveSpeed_defval); + pAvatar_moveSpeed.defaultVal = Avatar_moveSpeed_defval; + pAvatarModule.propertys["moveSpeed"] = pAvatar_moveSpeed; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_moveSpeed.aliasID] = pAvatar_moveSpeed; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(moveSpeed / 11)."); + + Property pAvatar_name = new Property(); + pAvatar_name.name = "name"; + pAvatar_name.properUtype = 41003; + pAvatar_name.properFlags = 4; + pAvatar_name.aliasID = 16; + string Avatar_name_defval = ""; + pAvatar_name.defaultVal = Avatar_name_defval; + pAvatarModule.propertys["name"] = pAvatar_name; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_name.aliasID] = pAvatar_name; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(name / 41003)."); + + Property pAvatar_own_val = new Property(); + pAvatar_own_val.name = "own_val"; + pAvatar_own_val.properUtype = 6; + pAvatar_own_val.properFlags = 16; + pAvatar_own_val.aliasID = 17; + UInt16 Avatar_own_val_defval; + UInt16.TryParse("", out Avatar_own_val_defval); + pAvatar_own_val.defaultVal = Avatar_own_val_defval; + pAvatarModule.propertys["own_val"] = pAvatar_own_val; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_own_val.aliasID] = pAvatar_own_val; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(own_val / 6)."); + + Property pAvatar_spaceUType = new Property(); + pAvatar_spaceUType.name = "spaceUType"; + pAvatar_spaceUType.properUtype = 41001; + pAvatar_spaceUType.properFlags = 8; + pAvatar_spaceUType.aliasID = 18; + UInt32 Avatar_spaceUType_defval; + UInt32.TryParse("", out Avatar_spaceUType_defval); + pAvatar_spaceUType.defaultVal = Avatar_spaceUType_defval; + pAvatarModule.propertys["spaceUType"] = pAvatar_spaceUType; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_spaceUType.aliasID] = pAvatar_spaceUType; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(spaceUType / 41001)."); + + Property pAvatar_state = new Property(); + pAvatar_state.name = "state"; + pAvatar_state.properUtype = 47006; + pAvatar_state.properFlags = 4; + pAvatar_state.aliasID = 19; + SByte Avatar_state_defval; + SByte.TryParse("0", out Avatar_state_defval); + pAvatar_state.defaultVal = Avatar_state_defval; + pAvatarModule.propertys["state"] = pAvatar_state; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_state.aliasID] = pAvatar_state; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(state / 47006)."); + + Property pAvatar_subState = new Property(); + pAvatar_subState.name = "subState"; + pAvatar_subState.properUtype = 47007; + pAvatar_subState.properFlags = 4; + pAvatar_subState.aliasID = 20; + Byte Avatar_subState_defval; + Byte.TryParse("", out Avatar_subState_defval); + pAvatar_subState.defaultVal = Avatar_subState_defval; + pAvatarModule.propertys["subState"] = pAvatar_subState; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_subState.aliasID] = pAvatar_subState; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(subState / 47007)."); + + Property pAvatar_uid = new Property(); + pAvatar_uid.name = "uid"; + pAvatar_uid.properUtype = 41004; + pAvatar_uid.properFlags = 4; + pAvatar_uid.aliasID = 21; + UInt32 Avatar_uid_defval; + UInt32.TryParse("0", out Avatar_uid_defval); + pAvatar_uid.defaultVal = Avatar_uid_defval; + pAvatarModule.propertys["uid"] = pAvatar_uid; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_uid.aliasID] = pAvatar_uid; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(uid / 41004)."); + + Property pAvatar_utype = new Property(); + pAvatar_utype.name = "utype"; + pAvatar_utype.properUtype = 41005; + pAvatar_utype.properFlags = 4; + pAvatar_utype.aliasID = 22; + UInt32 Avatar_utype_defval; + UInt32.TryParse("0", out Avatar_utype_defval); + pAvatar_utype.defaultVal = Avatar_utype_defval; + pAvatarModule.propertys["utype"] = pAvatar_utype; + + pAvatarModule.usePropertyDescrAlias = true; + pAvatarModule.idpropertys[(UInt16)pAvatar_utype.aliasID] = pAvatar_utype; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), property(utype / 41005)."); + + List pAvatar_dialog_addOption_args = new List(); + pAvatar_dialog_addOption_args.Add(EntityDef.id2datatypes[2]); + pAvatar_dialog_addOption_args.Add(EntityDef.id2datatypes[4]); + pAvatar_dialog_addOption_args.Add(EntityDef.id2datatypes[12]); + pAvatar_dialog_addOption_args.Add(EntityDef.id2datatypes[8]); + + Method pAvatar_dialog_addOption = new Method(); + pAvatar_dialog_addOption.name = "dialog_addOption"; + pAvatar_dialog_addOption.methodUtype = 10101; + pAvatar_dialog_addOption.aliasID = 1; + pAvatar_dialog_addOption.args = pAvatar_dialog_addOption_args; + + pAvatarModule.methods["dialog_addOption"] = pAvatar_dialog_addOption; + pAvatarModule.useMethodDescrAlias = true; + pAvatarModule.idmethods[(UInt16)pAvatar_dialog_addOption.aliasID] = pAvatar_dialog_addOption; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(dialog_addOption / 10101)."); + + List pAvatar_dialog_close_args = new List(); + + Method pAvatar_dialog_close = new Method(); + pAvatar_dialog_close.name = "dialog_close"; + pAvatar_dialog_close.methodUtype = 10104; + pAvatar_dialog_close.aliasID = 2; + pAvatar_dialog_close.args = pAvatar_dialog_close_args; + + pAvatarModule.methods["dialog_close"] = pAvatar_dialog_close; + pAvatarModule.useMethodDescrAlias = true; + pAvatarModule.idmethods[(UInt16)pAvatar_dialog_close.aliasID] = pAvatar_dialog_close; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(dialog_close / 10104)."); + + List pAvatar_dialog_setText_args = new List(); + pAvatar_dialog_setText_args.Add(EntityDef.id2datatypes[12]); + pAvatar_dialog_setText_args.Add(EntityDef.id2datatypes[2]); + pAvatar_dialog_setText_args.Add(EntityDef.id2datatypes[4]); + pAvatar_dialog_setText_args.Add(EntityDef.id2datatypes[12]); + + Method pAvatar_dialog_setText = new Method(); + pAvatar_dialog_setText.name = "dialog_setText"; + pAvatar_dialog_setText.methodUtype = 10102; + pAvatar_dialog_setText.aliasID = 3; + pAvatar_dialog_setText.args = pAvatar_dialog_setText_args; + + pAvatarModule.methods["dialog_setText"] = pAvatar_dialog_setText; + pAvatarModule.useMethodDescrAlias = true; + pAvatarModule.idmethods[(UInt16)pAvatar_dialog_setText.aliasID] = pAvatar_dialog_setText; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(dialog_setText / 10102)."); + + List pAvatar_onAddSkill_args = new List(); + pAvatar_onAddSkill_args.Add(EntityDef.id2datatypes[8]); + + Method pAvatar_onAddSkill = new Method(); + pAvatar_onAddSkill.name = "onAddSkill"; + pAvatar_onAddSkill.methodUtype = 12; + pAvatar_onAddSkill.aliasID = 4; + pAvatar_onAddSkill.args = pAvatar_onAddSkill_args; + + pAvatarModule.methods["onAddSkill"] = pAvatar_onAddSkill; + pAvatarModule.useMethodDescrAlias = true; + pAvatarModule.idmethods[(UInt16)pAvatar_onAddSkill.aliasID] = pAvatar_onAddSkill; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(onAddSkill / 12)."); + + List pAvatar_onJump_args = new List(); + + Method pAvatar_onJump = new Method(); + pAvatar_onJump.name = "onJump"; + pAvatar_onJump.methodUtype = 7; + pAvatar_onJump.aliasID = 5; + pAvatar_onJump.args = pAvatar_onJump_args; + + pAvatarModule.methods["onJump"] = pAvatar_onJump; + pAvatarModule.useMethodDescrAlias = true; + pAvatarModule.idmethods[(UInt16)pAvatar_onJump.aliasID] = pAvatar_onJump; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(onJump / 7)."); + + List pAvatar_onRemoveSkill_args = new List(); + pAvatar_onRemoveSkill_args.Add(EntityDef.id2datatypes[8]); + + Method pAvatar_onRemoveSkill = new Method(); + pAvatar_onRemoveSkill.name = "onRemoveSkill"; + pAvatar_onRemoveSkill.methodUtype = 13; + pAvatar_onRemoveSkill.aliasID = 6; + pAvatar_onRemoveSkill.args = pAvatar_onRemoveSkill_args; + + pAvatarModule.methods["onRemoveSkill"] = pAvatar_onRemoveSkill; + pAvatarModule.useMethodDescrAlias = true; + pAvatarModule.idmethods[(UInt16)pAvatar_onRemoveSkill.aliasID] = pAvatar_onRemoveSkill; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(onRemoveSkill / 13)."); + + List pAvatar_recvDamage_args = new List(); + pAvatar_recvDamage_args.Add(EntityDef.id2datatypes[8]); + pAvatar_recvDamage_args.Add(EntityDef.id2datatypes[8]); + pAvatar_recvDamage_args.Add(EntityDef.id2datatypes[8]); + pAvatar_recvDamage_args.Add(EntityDef.id2datatypes[8]); + + Method pAvatar_recvDamage = new Method(); + pAvatar_recvDamage.name = "recvDamage"; + pAvatar_recvDamage.methodUtype = 16; + pAvatar_recvDamage.aliasID = 7; + pAvatar_recvDamage.args = pAvatar_recvDamage_args; + + pAvatarModule.methods["recvDamage"] = pAvatar_recvDamage; + pAvatarModule.useMethodDescrAlias = true; + pAvatarModule.idmethods[(UInt16)pAvatar_recvDamage.aliasID] = pAvatar_recvDamage; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(recvDamage / 16)."); + + List pAvatar_dialog_args = new List(); + pAvatar_dialog_args.Add(EntityDef.id2datatypes[8]); + pAvatar_dialog_args.Add(EntityDef.id2datatypes[4]); + + Method pAvatar_dialog = new Method(); + pAvatar_dialog.name = "dialog"; + pAvatar_dialog.methodUtype = 11003; + pAvatar_dialog.aliasID = -1; + pAvatar_dialog.args = pAvatar_dialog_args; + + pAvatarModule.methods["dialog"] = pAvatar_dialog; + pAvatarModule.cell_methods["dialog"] = pAvatar_dialog; + + pAvatarModule.idcell_methods[pAvatar_dialog.methodUtype] = pAvatar_dialog; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(dialog / 11003)."); + + List pAvatar_jump_args = new List(); + + Method pAvatar_jump = new Method(); + pAvatar_jump.name = "jump"; + pAvatar_jump.methodUtype = 5; + pAvatar_jump.aliasID = -1; + pAvatar_jump.args = pAvatar_jump_args; + + pAvatarModule.methods["jump"] = pAvatar_jump; + pAvatarModule.cell_methods["jump"] = pAvatar_jump; + + pAvatarModule.idcell_methods[pAvatar_jump.methodUtype] = pAvatar_jump; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(jump / 5)."); + + List pAvatar_relive_args = new List(); + pAvatar_relive_args.Add(EntityDef.id2datatypes[2]); + + Method pAvatar_relive = new Method(); + pAvatar_relive.name = "relive"; + pAvatar_relive.methodUtype = 4; + pAvatar_relive.aliasID = -1; + pAvatar_relive.args = pAvatar_relive_args; + + pAvatarModule.methods["relive"] = pAvatar_relive; + pAvatarModule.cell_methods["relive"] = pAvatar_relive; + + pAvatarModule.idcell_methods[pAvatar_relive.methodUtype] = pAvatar_relive; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(relive / 4)."); + + List pAvatar_requestPull_args = new List(); + + Method pAvatar_requestPull = new Method(); + pAvatar_requestPull.name = "requestPull"; + pAvatar_requestPull.methodUtype = 11; + pAvatar_requestPull.aliasID = -1; + pAvatar_requestPull.args = pAvatar_requestPull_args; + + pAvatarModule.methods["requestPull"] = pAvatar_requestPull; + pAvatarModule.cell_methods["requestPull"] = pAvatar_requestPull; + + pAvatarModule.idcell_methods[pAvatar_requestPull.methodUtype] = pAvatar_requestPull; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(requestPull / 11)."); + + List pAvatar_useTargetSkill_args = new List(); + pAvatar_useTargetSkill_args.Add(EntityDef.id2datatypes[8]); + pAvatar_useTargetSkill_args.Add(EntityDef.id2datatypes[8]); + + Method pAvatar_useTargetSkill = new Method(); + pAvatar_useTargetSkill.name = "useTargetSkill"; + pAvatar_useTargetSkill.methodUtype = 11001; + pAvatar_useTargetSkill.aliasID = -1; + pAvatar_useTargetSkill.args = pAvatar_useTargetSkill_args; + + pAvatarModule.methods["useTargetSkill"] = pAvatar_useTargetSkill; + pAvatarModule.cell_methods["useTargetSkill"] = pAvatar_useTargetSkill; + + pAvatarModule.idcell_methods[pAvatar_useTargetSkill.methodUtype] = pAvatar_useTargetSkill; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Avatar), method(useTargetSkill / 11001)."); + + ScriptModule pTestModule = new ScriptModule("Test"); + EntityDef.moduledefs["Test"] = pTestModule; + EntityDef.idmoduledefs[3] = pTestModule; + + Property pTest_position = new Property(); + pTest_position.name = "position"; + pTest_position.properUtype = 40000; + pTest_position.properFlags = 4; + pTest_position.aliasID = 1; + Vector3 Test_position_defval = new Vector3(); + pTest_position.defaultVal = Test_position_defval; + pTestModule.propertys["position"] = pTest_position; + + pTestModule.usePropertyDescrAlias = true; + pTestModule.idpropertys[(UInt16)pTest_position.aliasID] = pTest_position; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), property(position / 40000)."); + + Property pTest_direction = new Property(); + pTest_direction.name = "direction"; + pTest_direction.properUtype = 40001; + pTest_direction.properFlags = 4; + pTest_direction.aliasID = 2; + Vector3 Test_direction_defval = new Vector3(); + pTest_direction.defaultVal = Test_direction_defval; + pTestModule.propertys["direction"] = pTest_direction; + + pTestModule.usePropertyDescrAlias = true; + pTestModule.idpropertys[(UInt16)pTest_direction.aliasID] = pTest_direction; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), property(direction / 40001)."); + + Property pTest_spaceID = new Property(); + pTest_spaceID.name = "spaceID"; + pTest_spaceID.properUtype = 40002; + pTest_spaceID.properFlags = 16; + pTest_spaceID.aliasID = 3; + UInt32 Test_spaceID_defval; + UInt32.TryParse("", out Test_spaceID_defval); + pTest_spaceID.defaultVal = Test_spaceID_defval; + pTestModule.propertys["spaceID"] = pTest_spaceID; + + pTestModule.usePropertyDescrAlias = true; + pTestModule.idpropertys[(UInt16)pTest_spaceID.aliasID] = pTest_spaceID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), property(spaceID / 40002)."); + + Property pTest_own = new Property(); + pTest_own.name = "own"; + pTest_own.properUtype = 18; + pTest_own.properFlags = 8; + pTest_own.aliasID = 4; + Int32 Test_own_defval; + Int32.TryParse("1001", out Test_own_defval); + pTest_own.defaultVal = Test_own_defval; + pTestModule.propertys["own"] = pTest_own; + + pTestModule.usePropertyDescrAlias = true; + pTestModule.idpropertys[(UInt16)pTest_own.aliasID] = pTest_own; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), property(own / 18)."); + + Property pTest_state = new Property(); + pTest_state.name = "state"; + pTest_state.properUtype = 17; + pTest_state.properFlags = 4; + pTest_state.aliasID = 5; + Int32 Test_state_defval; + Int32.TryParse("100", out Test_state_defval); + pTest_state.defaultVal = Test_state_defval; + pTestModule.propertys["state"] = pTest_state; + + pTestModule.usePropertyDescrAlias = true; + pTestModule.idpropertys[(UInt16)pTest_state.aliasID] = pTest_state; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), property(state / 17)."); + + List pTest_helloCB_args = new List(); + pTest_helloCB_args.Add(EntityDef.id2datatypes[8]); + + Method pTest_helloCB = new Method(); + pTest_helloCB.name = "helloCB"; + pTest_helloCB.methodUtype = 28; + pTest_helloCB.aliasID = 1; + pTest_helloCB.args = pTest_helloCB_args; + + pTestModule.methods["helloCB"] = pTest_helloCB; + pTestModule.useMethodDescrAlias = true; + pTestModule.idmethods[(UInt16)pTest_helloCB.aliasID] = pTest_helloCB; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), method(helloCB / 28)."); + + List pTest_say_args = new List(); + pTest_say_args.Add(EntityDef.id2datatypes[8]); + + Method pTest_say = new Method(); + pTest_say.name = "say"; + pTest_say.methodUtype = 27; + pTest_say.aliasID = -1; + pTest_say.args = pTest_say_args; + + pTestModule.methods["say"] = pTest_say; + pTestModule.base_methods["say"] = pTest_say; + + pTestModule.idbase_methods[pTest_say.methodUtype] = pTest_say; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), method(say / 27)."); + + List pTest_hello_args = new List(); + pTest_hello_args.Add(EntityDef.id2datatypes[8]); + + Method pTest_hello = new Method(); + pTest_hello.name = "hello"; + pTest_hello.methodUtype = 26; + pTest_hello.aliasID = -1; + pTest_hello.args = pTest_hello_args; + + pTestModule.methods["hello"] = pTest_hello; + pTestModule.cell_methods["hello"] = pTest_hello; + + pTestModule.idcell_methods[pTest_hello.methodUtype] = pTest_hello; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Test), method(hello / 26)."); + + ScriptModule pTestNoBaseModule = new ScriptModule("TestNoBase"); + EntityDef.moduledefs["TestNoBase"] = pTestNoBaseModule; + EntityDef.idmoduledefs[4] = pTestNoBaseModule; + + Property pTestNoBase_position = new Property(); + pTestNoBase_position.name = "position"; + pTestNoBase_position.properUtype = 40000; + pTestNoBase_position.properFlags = 4; + pTestNoBase_position.aliasID = 1; + Vector3 TestNoBase_position_defval = new Vector3(); + pTestNoBase_position.defaultVal = TestNoBase_position_defval; + pTestNoBaseModule.propertys["position"] = pTestNoBase_position; + + pTestNoBaseModule.usePropertyDescrAlias = true; + pTestNoBaseModule.idpropertys[(UInt16)pTestNoBase_position.aliasID] = pTestNoBase_position; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(TestNoBase), property(position / 40000)."); + + Property pTestNoBase_direction = new Property(); + pTestNoBase_direction.name = "direction"; + pTestNoBase_direction.properUtype = 40001; + pTestNoBase_direction.properFlags = 4; + pTestNoBase_direction.aliasID = 2; + Vector3 TestNoBase_direction_defval = new Vector3(); + pTestNoBase_direction.defaultVal = TestNoBase_direction_defval; + pTestNoBaseModule.propertys["direction"] = pTestNoBase_direction; + + pTestNoBaseModule.usePropertyDescrAlias = true; + pTestNoBaseModule.idpropertys[(UInt16)pTestNoBase_direction.aliasID] = pTestNoBase_direction; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(TestNoBase), property(direction / 40001)."); + + Property pTestNoBase_spaceID = new Property(); + pTestNoBase_spaceID.name = "spaceID"; + pTestNoBase_spaceID.properUtype = 40002; + pTestNoBase_spaceID.properFlags = 16; + pTestNoBase_spaceID.aliasID = 3; + UInt32 TestNoBase_spaceID_defval; + UInt32.TryParse("", out TestNoBase_spaceID_defval); + pTestNoBase_spaceID.defaultVal = TestNoBase_spaceID_defval; + pTestNoBaseModule.propertys["spaceID"] = pTestNoBase_spaceID; + + pTestNoBaseModule.usePropertyDescrAlias = true; + pTestNoBaseModule.idpropertys[(UInt16)pTestNoBase_spaceID.aliasID] = pTestNoBase_spaceID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(TestNoBase), property(spaceID / 40002)."); + + Property pTestNoBase_own = new Property(); + pTestNoBase_own.name = "own"; + pTestNoBase_own.properUtype = 24; + pTestNoBase_own.properFlags = 8; + pTestNoBase_own.aliasID = 4; + Int32 TestNoBase_own_defval; + Int32.TryParse("1001", out TestNoBase_own_defval); + pTestNoBase_own.defaultVal = TestNoBase_own_defval; + pTestNoBaseModule.propertys["own"] = pTestNoBase_own; + + pTestNoBaseModule.usePropertyDescrAlias = true; + pTestNoBaseModule.idpropertys[(UInt16)pTestNoBase_own.aliasID] = pTestNoBase_own; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(TestNoBase), property(own / 24)."); + + Property pTestNoBase_state = new Property(); + pTestNoBase_state.name = "state"; + pTestNoBase_state.properUtype = 23; + pTestNoBase_state.properFlags = 4; + pTestNoBase_state.aliasID = 5; + Int32 TestNoBase_state_defval; + Int32.TryParse("100", out TestNoBase_state_defval); + pTestNoBase_state.defaultVal = TestNoBase_state_defval; + pTestNoBaseModule.propertys["state"] = pTestNoBase_state; + + pTestNoBaseModule.usePropertyDescrAlias = true; + pTestNoBaseModule.idpropertys[(UInt16)pTestNoBase_state.aliasID] = pTestNoBase_state; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(TestNoBase), property(state / 23)."); + + List pTestNoBase_helloCB_args = new List(); + pTestNoBase_helloCB_args.Add(EntityDef.id2datatypes[8]); + + Method pTestNoBase_helloCB = new Method(); + pTestNoBase_helloCB.name = "helloCB"; + pTestNoBase_helloCB.methodUtype = 30; + pTestNoBase_helloCB.aliasID = 1; + pTestNoBase_helloCB.args = pTestNoBase_helloCB_args; + + pTestNoBaseModule.methods["helloCB"] = pTestNoBase_helloCB; + pTestNoBaseModule.useMethodDescrAlias = true; + pTestNoBaseModule.idmethods[(UInt16)pTestNoBase_helloCB.aliasID] = pTestNoBase_helloCB; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(TestNoBase), method(helloCB / 30)."); + + List pTestNoBase_hello_args = new List(); + pTestNoBase_hello_args.Add(EntityDef.id2datatypes[8]); + + Method pTestNoBase_hello = new Method(); + pTestNoBase_hello.name = "hello"; + pTestNoBase_hello.methodUtype = 29; + pTestNoBase_hello.aliasID = -1; + pTestNoBase_hello.args = pTestNoBase_hello_args; + + pTestNoBaseModule.methods["hello"] = pTestNoBase_hello; + pTestNoBaseModule.cell_methods["hello"] = pTestNoBase_hello; + + pTestNoBaseModule.idcell_methods[pTestNoBase_hello.methodUtype] = pTestNoBase_hello; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(TestNoBase), method(hello / 29)."); + + ScriptModule pMonsterModule = new ScriptModule("Monster"); + EntityDef.moduledefs["Monster"] = pMonsterModule; + EntityDef.idmoduledefs[5] = pMonsterModule; + + Property pMonster_position = new Property(); + pMonster_position.name = "position"; + pMonster_position.properUtype = 40000; + pMonster_position.properFlags = 4; + pMonster_position.aliasID = 1; + Vector3 Monster_position_defval = new Vector3(); + pMonster_position.defaultVal = Monster_position_defval; + pMonsterModule.propertys["position"] = pMonster_position; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_position.aliasID] = pMonster_position; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(position / 40000)."); + + Property pMonster_direction = new Property(); + pMonster_direction.name = "direction"; + pMonster_direction.properUtype = 40001; + pMonster_direction.properFlags = 4; + pMonster_direction.aliasID = 2; + Vector3 Monster_direction_defval = new Vector3(); + pMonster_direction.defaultVal = Monster_direction_defval; + pMonsterModule.propertys["direction"] = pMonster_direction; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_direction.aliasID] = pMonster_direction; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(direction / 40001)."); + + Property pMonster_spaceID = new Property(); + pMonster_spaceID.name = "spaceID"; + pMonster_spaceID.properUtype = 40002; + pMonster_spaceID.properFlags = 16; + pMonster_spaceID.aliasID = 3; + UInt32 Monster_spaceID_defval; + UInt32.TryParse("", out Monster_spaceID_defval); + pMonster_spaceID.defaultVal = Monster_spaceID_defval; + pMonsterModule.propertys["spaceID"] = pMonster_spaceID; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_spaceID.aliasID] = pMonster_spaceID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(spaceID / 40002)."); + + Property pMonster_HP = new Property(); + pMonster_HP.name = "HP"; + pMonster_HP.properUtype = 47001; + pMonster_HP.properFlags = 4; + pMonster_HP.aliasID = 4; + Int32 Monster_HP_defval; + Int32.TryParse("0", out Monster_HP_defval); + pMonster_HP.defaultVal = Monster_HP_defval; + pMonsterModule.propertys["HP"] = pMonster_HP; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_HP.aliasID] = pMonster_HP; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(HP / 47001)."); + + Property pMonster_HP_Max = new Property(); + pMonster_HP_Max.name = "HP_Max"; + pMonster_HP_Max.properUtype = 47002; + pMonster_HP_Max.properFlags = 4; + pMonster_HP_Max.aliasID = 5; + Int32 Monster_HP_Max_defval; + Int32.TryParse("0", out Monster_HP_Max_defval); + pMonster_HP_Max.defaultVal = Monster_HP_Max_defval; + pMonsterModule.propertys["HP_Max"] = pMonster_HP_Max; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_HP_Max.aliasID] = pMonster_HP_Max; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(HP_Max / 47002)."); + + Property pMonster_MP = new Property(); + pMonster_MP.name = "MP"; + pMonster_MP.properUtype = 47003; + pMonster_MP.properFlags = 4; + pMonster_MP.aliasID = 6; + Int32 Monster_MP_defval; + Int32.TryParse("0", out Monster_MP_defval); + pMonster_MP.defaultVal = Monster_MP_defval; + pMonsterModule.propertys["MP"] = pMonster_MP; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_MP.aliasID] = pMonster_MP; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(MP / 47003)."); + + Property pMonster_MP_Max = new Property(); + pMonster_MP_Max.name = "MP_Max"; + pMonster_MP_Max.properUtype = 47004; + pMonster_MP_Max.properFlags = 4; + pMonster_MP_Max.aliasID = 7; + Int32 Monster_MP_Max_defval; + Int32.TryParse("0", out Monster_MP_Max_defval); + pMonster_MP_Max.defaultVal = Monster_MP_Max_defval; + pMonsterModule.propertys["MP_Max"] = pMonster_MP_Max; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_MP_Max.aliasID] = pMonster_MP_Max; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(MP_Max / 47004)."); + + Property pMonster_entityNO = new Property(); + pMonster_entityNO.name = "entityNO"; + pMonster_entityNO.properUtype = 51007; + pMonster_entityNO.properFlags = 4; + pMonster_entityNO.aliasID = 8; + UInt32 Monster_entityNO_defval; + UInt32.TryParse("0", out Monster_entityNO_defval); + pMonster_entityNO.defaultVal = Monster_entityNO_defval; + pMonsterModule.propertys["entityNO"] = pMonster_entityNO; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_entityNO.aliasID] = pMonster_entityNO; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(entityNO / 51007)."); + + Property pMonster_forbids = new Property(); + pMonster_forbids.name = "forbids"; + pMonster_forbids.properUtype = 47005; + pMonster_forbids.properFlags = 4; + pMonster_forbids.aliasID = 9; + Int32 Monster_forbids_defval; + Int32.TryParse("0", out Monster_forbids_defval); + pMonster_forbids.defaultVal = Monster_forbids_defval; + pMonsterModule.propertys["forbids"] = pMonster_forbids; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_forbids.aliasID] = pMonster_forbids; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(forbids / 47005)."); + + Property pMonster_modelID = new Property(); + pMonster_modelID.name = "modelID"; + pMonster_modelID.properUtype = 41006; + pMonster_modelID.properFlags = 4; + pMonster_modelID.aliasID = 10; + UInt32 Monster_modelID_defval; + UInt32.TryParse("0", out Monster_modelID_defval); + pMonster_modelID.defaultVal = Monster_modelID_defval; + pMonsterModule.propertys["modelID"] = pMonster_modelID; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_modelID.aliasID] = pMonster_modelID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(modelID / 41006)."); + + Property pMonster_modelScale = new Property(); + pMonster_modelScale.name = "modelScale"; + pMonster_modelScale.properUtype = 41007; + pMonster_modelScale.properFlags = 4; + pMonster_modelScale.aliasID = 11; + Byte Monster_modelScale_defval; + Byte.TryParse("30", out Monster_modelScale_defval); + pMonster_modelScale.defaultVal = Monster_modelScale_defval; + pMonsterModule.propertys["modelScale"] = pMonster_modelScale; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_modelScale.aliasID] = pMonster_modelScale; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(modelScale / 41007)."); + + Property pMonster_moveSpeed = new Property(); + pMonster_moveSpeed.name = "moveSpeed"; + pMonster_moveSpeed.properUtype = 32; + pMonster_moveSpeed.properFlags = 4; + pMonster_moveSpeed.aliasID = 12; + Byte Monster_moveSpeed_defval; + Byte.TryParse("50", out Monster_moveSpeed_defval); + pMonster_moveSpeed.defaultVal = Monster_moveSpeed_defval; + pMonsterModule.propertys["moveSpeed"] = pMonster_moveSpeed; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_moveSpeed.aliasID] = pMonster_moveSpeed; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(moveSpeed / 32)."); + + Property pMonster_name = new Property(); + pMonster_name.name = "name"; + pMonster_name.properUtype = 41003; + pMonster_name.properFlags = 4; + pMonster_name.aliasID = 13; + string Monster_name_defval = ""; + pMonster_name.defaultVal = Monster_name_defval; + pMonsterModule.propertys["name"] = pMonster_name; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_name.aliasID] = pMonster_name; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(name / 41003)."); + + Property pMonster_state = new Property(); + pMonster_state.name = "state"; + pMonster_state.properUtype = 47006; + pMonster_state.properFlags = 4; + pMonster_state.aliasID = 14; + SByte Monster_state_defval; + SByte.TryParse("0", out Monster_state_defval); + pMonster_state.defaultVal = Monster_state_defval; + pMonsterModule.propertys["state"] = pMonster_state; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_state.aliasID] = pMonster_state; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(state / 47006)."); + + Property pMonster_subState = new Property(); + pMonster_subState.name = "subState"; + pMonster_subState.properUtype = 47007; + pMonster_subState.properFlags = 4; + pMonster_subState.aliasID = 15; + Byte Monster_subState_defval; + Byte.TryParse("", out Monster_subState_defval); + pMonster_subState.defaultVal = Monster_subState_defval; + pMonsterModule.propertys["subState"] = pMonster_subState; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_subState.aliasID] = pMonster_subState; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(subState / 47007)."); + + Property pMonster_uid = new Property(); + pMonster_uid.name = "uid"; + pMonster_uid.properUtype = 41004; + pMonster_uid.properFlags = 4; + pMonster_uid.aliasID = 16; + UInt32 Monster_uid_defval; + UInt32.TryParse("0", out Monster_uid_defval); + pMonster_uid.defaultVal = Monster_uid_defval; + pMonsterModule.propertys["uid"] = pMonster_uid; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_uid.aliasID] = pMonster_uid; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(uid / 41004)."); + + Property pMonster_utype = new Property(); + pMonster_utype.name = "utype"; + pMonster_utype.properUtype = 41005; + pMonster_utype.properFlags = 4; + pMonster_utype.aliasID = 17; + UInt32 Monster_utype_defval; + UInt32.TryParse("0", out Monster_utype_defval); + pMonster_utype.defaultVal = Monster_utype_defval; + pMonsterModule.propertys["utype"] = pMonster_utype; + + pMonsterModule.usePropertyDescrAlias = true; + pMonsterModule.idpropertys[(UInt16)pMonster_utype.aliasID] = pMonster_utype; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), property(utype / 41005)."); + + List pMonster_recvDamage_args = new List(); + pMonster_recvDamage_args.Add(EntityDef.id2datatypes[8]); + pMonster_recvDamage_args.Add(EntityDef.id2datatypes[8]); + pMonster_recvDamage_args.Add(EntityDef.id2datatypes[8]); + pMonster_recvDamage_args.Add(EntityDef.id2datatypes[8]); + + Method pMonster_recvDamage = new Method(); + pMonster_recvDamage.name = "recvDamage"; + pMonster_recvDamage.methodUtype = 34; + pMonster_recvDamage.aliasID = 1; + pMonster_recvDamage.args = pMonster_recvDamage_args; + + pMonsterModule.methods["recvDamage"] = pMonster_recvDamage; + pMonsterModule.useMethodDescrAlias = true; + pMonsterModule.idmethods[(UInt16)pMonster_recvDamage.aliasID] = pMonster_recvDamage; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Monster), method(recvDamage / 34)."); + + ScriptModule pNPCModule = new ScriptModule("NPC"); + EntityDef.moduledefs["NPC"] = pNPCModule; + EntityDef.idmoduledefs[6] = pNPCModule; + + Property pNPC_position = new Property(); + pNPC_position.name = "position"; + pNPC_position.properUtype = 40000; + pNPC_position.properFlags = 4; + pNPC_position.aliasID = 1; + Vector3 NPC_position_defval = new Vector3(); + pNPC_position.defaultVal = NPC_position_defval; + pNPCModule.propertys["position"] = pNPC_position; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_position.aliasID] = pNPC_position; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(position / 40000)."); + + Property pNPC_direction = new Property(); + pNPC_direction.name = "direction"; + pNPC_direction.properUtype = 40001; + pNPC_direction.properFlags = 4; + pNPC_direction.aliasID = 2; + Vector3 NPC_direction_defval = new Vector3(); + pNPC_direction.defaultVal = NPC_direction_defval; + pNPCModule.propertys["direction"] = pNPC_direction; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_direction.aliasID] = pNPC_direction; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(direction / 40001)."); + + Property pNPC_spaceID = new Property(); + pNPC_spaceID.name = "spaceID"; + pNPC_spaceID.properUtype = 40002; + pNPC_spaceID.properFlags = 16; + pNPC_spaceID.aliasID = 3; + UInt32 NPC_spaceID_defval; + UInt32.TryParse("", out NPC_spaceID_defval); + pNPC_spaceID.defaultVal = NPC_spaceID_defval; + pNPCModule.propertys["spaceID"] = pNPC_spaceID; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_spaceID.aliasID] = pNPC_spaceID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(spaceID / 40002)."); + + Property pNPC_entityNO = new Property(); + pNPC_entityNO.name = "entityNO"; + pNPC_entityNO.properUtype = 51007; + pNPC_entityNO.properFlags = 4; + pNPC_entityNO.aliasID = 4; + UInt32 NPC_entityNO_defval; + UInt32.TryParse("0", out NPC_entityNO_defval); + pNPC_entityNO.defaultVal = NPC_entityNO_defval; + pNPCModule.propertys["entityNO"] = pNPC_entityNO; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_entityNO.aliasID] = pNPC_entityNO; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(entityNO / 51007)."); + + Property pNPC_modelID = new Property(); + pNPC_modelID.name = "modelID"; + pNPC_modelID.properUtype = 41006; + pNPC_modelID.properFlags = 4; + pNPC_modelID.aliasID = 5; + UInt32 NPC_modelID_defval; + UInt32.TryParse("0", out NPC_modelID_defval); + pNPC_modelID.defaultVal = NPC_modelID_defval; + pNPCModule.propertys["modelID"] = pNPC_modelID; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_modelID.aliasID] = pNPC_modelID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(modelID / 41006)."); + + Property pNPC_modelScale = new Property(); + pNPC_modelScale.name = "modelScale"; + pNPC_modelScale.properUtype = 41007; + pNPC_modelScale.properFlags = 4; + pNPC_modelScale.aliasID = 6; + Byte NPC_modelScale_defval; + Byte.TryParse("30", out NPC_modelScale_defval); + pNPC_modelScale.defaultVal = NPC_modelScale_defval; + pNPCModule.propertys["modelScale"] = pNPC_modelScale; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_modelScale.aliasID] = pNPC_modelScale; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(modelScale / 41007)."); + + Property pNPC_moveSpeed = new Property(); + pNPC_moveSpeed.name = "moveSpeed"; + pNPC_moveSpeed.properUtype = 43; + pNPC_moveSpeed.properFlags = 4; + pNPC_moveSpeed.aliasID = 7; + Byte NPC_moveSpeed_defval; + Byte.TryParse("50", out NPC_moveSpeed_defval); + pNPC_moveSpeed.defaultVal = NPC_moveSpeed_defval; + pNPCModule.propertys["moveSpeed"] = pNPC_moveSpeed; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_moveSpeed.aliasID] = pNPC_moveSpeed; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(moveSpeed / 43)."); + + Property pNPC_name = new Property(); + pNPC_name.name = "name"; + pNPC_name.properUtype = 41003; + pNPC_name.properFlags = 4; + pNPC_name.aliasID = 8; + string NPC_name_defval = ""; + pNPC_name.defaultVal = NPC_name_defval; + pNPCModule.propertys["name"] = pNPC_name; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_name.aliasID] = pNPC_name; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(name / 41003)."); + + Property pNPC_uid = new Property(); + pNPC_uid.name = "uid"; + pNPC_uid.properUtype = 41004; + pNPC_uid.properFlags = 4; + pNPC_uid.aliasID = 9; + UInt32 NPC_uid_defval; + UInt32.TryParse("0", out NPC_uid_defval); + pNPC_uid.defaultVal = NPC_uid_defval; + pNPCModule.propertys["uid"] = pNPC_uid; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_uid.aliasID] = pNPC_uid; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(uid / 41004)."); + + Property pNPC_utype = new Property(); + pNPC_utype.name = "utype"; + pNPC_utype.properUtype = 41005; + pNPC_utype.properFlags = 4; + pNPC_utype.aliasID = 10; + UInt32 NPC_utype_defval; + UInt32.TryParse("0", out NPC_utype_defval); + pNPC_utype.defaultVal = NPC_utype_defval; + pNPCModule.propertys["utype"] = pNPC_utype; + + pNPCModule.usePropertyDescrAlias = true; + pNPCModule.idpropertys[(UInt16)pNPC_utype.aliasID] = pNPC_utype; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(NPC), property(utype / 41005)."); + + pNPCModule.useMethodDescrAlias = true; + ScriptModule pGateModule = new ScriptModule("Gate"); + EntityDef.moduledefs["Gate"] = pGateModule; + EntityDef.idmoduledefs[7] = pGateModule; + + Property pGate_position = new Property(); + pGate_position.name = "position"; + pGate_position.properUtype = 40000; + pGate_position.properFlags = 4; + pGate_position.aliasID = 1; + Vector3 Gate_position_defval = new Vector3(); + pGate_position.defaultVal = Gate_position_defval; + pGateModule.propertys["position"] = pGate_position; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_position.aliasID] = pGate_position; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(position / 40000)."); + + Property pGate_direction = new Property(); + pGate_direction.name = "direction"; + pGate_direction.properUtype = 40001; + pGate_direction.properFlags = 4; + pGate_direction.aliasID = 2; + Vector3 Gate_direction_defval = new Vector3(); + pGate_direction.defaultVal = Gate_direction_defval; + pGateModule.propertys["direction"] = pGate_direction; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_direction.aliasID] = pGate_direction; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(direction / 40001)."); + + Property pGate_spaceID = new Property(); + pGate_spaceID.name = "spaceID"; + pGate_spaceID.properUtype = 40002; + pGate_spaceID.properFlags = 16; + pGate_spaceID.aliasID = 3; + UInt32 Gate_spaceID_defval; + UInt32.TryParse("", out Gate_spaceID_defval); + pGate_spaceID.defaultVal = Gate_spaceID_defval; + pGateModule.propertys["spaceID"] = pGate_spaceID; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_spaceID.aliasID] = pGate_spaceID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(spaceID / 40002)."); + + Property pGate_entityNO = new Property(); + pGate_entityNO.name = "entityNO"; + pGate_entityNO.properUtype = 51007; + pGate_entityNO.properFlags = 4; + pGate_entityNO.aliasID = 4; + UInt32 Gate_entityNO_defval; + UInt32.TryParse("0", out Gate_entityNO_defval); + pGate_entityNO.defaultVal = Gate_entityNO_defval; + pGateModule.propertys["entityNO"] = pGate_entityNO; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_entityNO.aliasID] = pGate_entityNO; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(entityNO / 51007)."); + + Property pGate_modelID = new Property(); + pGate_modelID.name = "modelID"; + pGate_modelID.properUtype = 41006; + pGate_modelID.properFlags = 4; + pGate_modelID.aliasID = 5; + UInt32 Gate_modelID_defval; + UInt32.TryParse("0", out Gate_modelID_defval); + pGate_modelID.defaultVal = Gate_modelID_defval; + pGateModule.propertys["modelID"] = pGate_modelID; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_modelID.aliasID] = pGate_modelID; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(modelID / 41006)."); + + Property pGate_modelScale = new Property(); + pGate_modelScale.name = "modelScale"; + pGate_modelScale.properUtype = 41007; + pGate_modelScale.properFlags = 4; + pGate_modelScale.aliasID = 6; + Byte Gate_modelScale_defval; + Byte.TryParse("30", out Gate_modelScale_defval); + pGate_modelScale.defaultVal = Gate_modelScale_defval; + pGateModule.propertys["modelScale"] = pGate_modelScale; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_modelScale.aliasID] = pGate_modelScale; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(modelScale / 41007)."); + + Property pGate_name = new Property(); + pGate_name.name = "name"; + pGate_name.properUtype = 41003; + pGate_name.properFlags = 4; + pGate_name.aliasID = 7; + string Gate_name_defval = ""; + pGate_name.defaultVal = Gate_name_defval; + pGateModule.propertys["name"] = pGate_name; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_name.aliasID] = pGate_name; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(name / 41003)."); + + Property pGate_uid = new Property(); + pGate_uid.name = "uid"; + pGate_uid.properUtype = 41004; + pGate_uid.properFlags = 4; + pGate_uid.aliasID = 8; + UInt32 Gate_uid_defval; + UInt32.TryParse("0", out Gate_uid_defval); + pGate_uid.defaultVal = Gate_uid_defval; + pGateModule.propertys["uid"] = pGate_uid; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_uid.aliasID] = pGate_uid; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(uid / 41004)."); + + Property pGate_utype = new Property(); + pGate_utype.name = "utype"; + pGate_utype.properUtype = 41005; + pGate_utype.properFlags = 4; + pGate_utype.aliasID = 9; + UInt32 Gate_utype_defval; + UInt32.TryParse("0", out Gate_utype_defval); + pGate_utype.defaultVal = Gate_utype_defval; + pGateModule.propertys["utype"] = pGate_utype; + + pGateModule.usePropertyDescrAlias = true; + pGateModule.idpropertys[(UInt16)pGate_utype.aliasID] = pGate_utype; + + //Dbg.DEBUG_MSG("EntityDef::initScriptModules: add(Gate), property(utype / 41005)."); + + pGateModule.useMethodDescrAlias = true; + } + + public static void initDefTypes() + { + { + UInt16 utype = 2; + string typeName = "ENTITY_SUBSTATE"; + string name = "UINT8"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 3; + string typeName = "UINT16"; + string name = "UINT16"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 5; + string typeName = "UID"; + string name = "UINT64"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 4; + string typeName = "ENTITY_UTYPE"; + string name = "UINT32"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 6; + string typeName = "ENTITY_STATE"; + string name = "INT8"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 7; + string typeName = "INT16"; + string name = "INT16"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 8; + string typeName = "ENTITY_FORBIDS"; + string name = "INT32"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 9; + string typeName = "INT64"; + string name = "INT64"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 1; + string typeName = "STRING"; + string name = "STRING"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 12; + string typeName = "UNICODE"; + string name = "UNICODE"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 13; + string typeName = "FLOAT"; + string name = "FLOAT"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 14; + string typeName = "DOUBLE"; + string name = "DOUBLE"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 10; + string typeName = "UID1"; + string name = "PYTHON"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 10; + string typeName = "PY_DICT"; + string name = "PY_DICT"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 10; + string typeName = "PY_TUPLE"; + string name = "PY_TUPLE"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 10; + string typeName = "PY_LIST"; + string name = "PY_LIST"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 20; + string typeName = "ENTITYCALL"; + string name = "ENTITYCALL"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 11; + string typeName = "BLOB"; + string name = "BLOB"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 15; + string typeName = "VECTOR2"; + string name = "VECTOR2"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 16; + string typeName = "DIRECTION3D"; + string name = "VECTOR3"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 17; + string typeName = "VECTOR4"; + string name = "VECTOR4"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 22; + string typeName = "ENTITY_FORBID_COUNTER"; + DATATYPE_ENTITY_FORBID_COUNTER datatype = new DATATYPE_ENTITY_FORBID_COUNTER(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 23; + string typeName = "ENTITYID_LIST"; + DATATYPE_ENTITYID_LIST datatype = new DATATYPE_ENTITYID_LIST(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 24; + string typeName = "AVATAR_DATA"; + DATATYPE_AVATAR_DATA datatype = new DATATYPE_AVATAR_DATA(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 25; + string typeName = "AVATAR_INFOS"; + DATATYPE_AVATAR_INFOS datatype = new DATATYPE_AVATAR_INFOS(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 26; + string typeName = "AVATAR_INFOS_LIST"; + DATATYPE_AVATAR_INFOS_LIST datatype = new DATATYPE_AVATAR_INFOS_LIST(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 28; + string typeName = "BAG"; + DATATYPE_BAG datatype = new DATATYPE_BAG(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 31; + string typeName = "EXAMPLES"; + DATATYPE_EXAMPLES datatype = new DATATYPE_EXAMPLES(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 32; + string typeName = "AnonymousArray_32"; + DATATYPE_AnonymousArray_32 datatype = new DATATYPE_AnonymousArray_32(); + EntityDef.datatypes[typeName] = datatype; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 33; + string typeName = "AnonymousArray_33"; + string name = "ENTITY_COMPONENT"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 34; + string typeName = "AnonymousArray_34"; + string name = "ENTITY_COMPONENT"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + { + UInt16 utype = 35; + string typeName = "AnonymousArray_35"; + string name = "ENTITY_COMPONENT"; + DATATYPE_BASE val = null; + EntityDef.datatypes.TryGetValue(name, out val); + EntityDef.datatypes[typeName] = val; + EntityDef.id2datatypes[utype] = EntityDef.datatypes[typeName]; + EntityDef.datatype2id[typeName] = utype; + } + + foreach(string datatypeStr in EntityDef.datatypes.Keys) + { + DATATYPE_BASE dataType = EntityDef.datatypes[datatypeStr]; + if(dataType != null) + { + dataType.bind(); + } + } + } + + } + + +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityDef.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityDef.cs.meta new file mode 100644 index 00000000..f48da9fc --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/EntityDef.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: df581ee7bf4eb144f93c2c8378493832 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Event.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Event.cs new file mode 100644 index 00000000..9214b188 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Event.cs @@ -0,0 +1,807 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + using System.Threading; + + /// + /// KBE-Plugin fire-out events(KBE => Unity): + /// + public class EventOutTypes + { + // ------------------------------------账号相关------------------------------------ + + /// + /// Create account feedback results. + /// param1(uint16): retcode. // server_errors + /// param2(bytes): datas. // If you use third-party account system, the system may fill some of the third-party additional datas. + /// + public const string onCreateAccountResult = "onCreateAccountResult"; + + /// + // Response from binding account Email request. + // param1(uint16): retcode. // server_errors + /// + public const string onBindAccountEmail = "onBindAccountEmail"; + + /// + // Response from a new password request. + // param1(uint16): retcode. // server_errors + /// + public const string onNewPassword = "onNewPassword"; + + /// + // Response from a reset password request. + // param1(uint16): retcode. // server_errors + /// + public const string onResetPassword = "onResetPassword"; + + // ------------------------------------连接相关------------------------------------ + /// + /// Kicked of the current server. + /// param1(uint16): retcode. // server_errors + /// + public const string onKicked = "onKicked"; + + /// + /// Disconnected from the server. + /// + public const string onDisconnected = "onDisconnected"; + + /// + /// Status of connection server. + /// param1(bool): success or fail + /// + public const string onConnectionState = "onConnectionState"; + + // ------------------------------------logon相关------------------------------------ + /// + /// Engine version mismatch. + /// param1(string): clientVersion + /// param2(string): serverVersion + /// + public const string onVersionNotMatch = "onVersionNotMatch"; + + /// + /// script version mismatch. + /// param1(string): clientScriptVersion + /// param2(string): serverScriptVersion + /// + public const string onScriptVersionNotMatch = "onScriptVersionNotMatch"; + + /// + /// Login failed. + /// param1(uint16): retcode. // server_errors + /// + public const string onLoginFailed = "onLoginFailed"; + + /// + /// Login to baseapp. + /// + public const string onLoginBaseapp = "onLoginBaseapp"; + + /// + /// Login baseapp failed. + /// param1(uint16): retcode. // server_errors + /// + public const string onLoginBaseappFailed = "onLoginBaseappFailed"; + + /// + /// Relogin to baseapp. + /// + public const string onReloginBaseapp = "onReloginBaseapp"; + + /// + /// Relogin baseapp success. + /// + public const string onReloginBaseappSuccessfully = "onReloginBaseappSuccessfully"; + + /// + /// Relogin baseapp failed. + /// param1(uint16): retcode. // server_errors + /// + public const string onReloginBaseappFailed = "onReloginBaseappFailed"; + + // ------------------------------------实体cell相关事件------------------------------------ + + /// + /// Entity enter the client-world. + /// param1: Entity + /// + public const string onEnterWorld = "onEnterWorld"; + + /// + /// Entity leave the client-world. + /// param1: Entity + /// + public const string onLeaveWorld = "onLeaveWorld"; + + /// + /// Player enter the new space. + /// param1: Entity + /// + public const string onEnterSpace = "onEnterSpace"; + + /// + /// Player leave the space. + /// param1: Entity + /// + public const string onLeaveSpace = "onLeaveSpace"; + + /// + /// Sets the current position of the entity. + /// param1: Entity + /// + public const string set_position = "set_position"; + + /// + /// Sets the current direction of the entity. + /// param1: Entity + /// + public const string set_direction = "set_direction"; + + /// + /// The entity position is updated, you can smooth the moving entity to new location. + /// param1: Entity + /// + public const string updatePosition = "updatePosition"; + + /// + /// The current space is specified by the geometry mapping. + /// Popular said is to load the specified Map Resources. + /// param1(string): resPath + /// + public const string addSpaceGeometryMapping = "addSpaceGeometryMapping"; + + /// + /// Server spaceData set data. + /// param1(int32): spaceID + /// param2(string): key + /// param3(string): value + /// + public const string onSetSpaceData = "onSetSpaceData"; + + /// + /// Start downloading data. + /// param1(int32): rspaceID + /// param2(string): key + /// + public const string onDelSpaceData = "onDelSpaceData"; + + /// + /// Triggered when the entity is controlled or out of control. + /// param1: Entity + /// param2(bool): isControlled + /// + public const string onControlled = "onControlled"; + + /// + /// Lose controlled entity. + /// param1: Entity + /// + public const string onLoseControlledEntity = "onLoseControlledEntity"; + + // ------------------------------------数据下载相关------------------------------------ + /// + /// Start downloading data. + /// param1(uint16): resouce id + /// param2(uint32): data size + /// param3(string): description + /// + public const string onStreamDataStarted = "onStreamDataStarted"; + + /// + /// Receive data. + /// param1(uint16): resouce id + /// param2(bytes): datas + /// + public const string onStreamDataRecv = "onStreamDataRecv"; + + /// + /// The downloaded data is completed. + /// param1(uint16): resouce id + /// + public const string onStreamDataCompleted = "onStreamDataCompleted"; + }; + + /// + /// KBE-Plugin fire-in events(Unity => KBE): + /// + public class EventInTypes + { + /// + /// Create new account. + /// param1(string): accountName + /// param2(string): password + /// param3(bytes): datas // Datas by user defined. Data will be recorded into the KBE account database, you can access the datas through the script layer. If you use third-party account system, datas will be submitted to the third-party system. + /// + public const string createAccount = "createAccount"; + + /// + /// Login to server. + /// param1(string): accountName + /// param2(string): password + /// param3(bytes): datas // Datas by user defined. Data will be recorded into the KBE account database, you can access the datas through the script layer. If you use third-party account system, datas will be submitted to the third-party system. + /// + public const string login = "login"; + + /// + /// Logout to baseapp, called when exiting the client. + /// + public const string logout = "logout"; + + /// + /// Relogin to baseapp. + /// + public const string reloginBaseapp = "reloginBaseapp"; + + /// + /// Reset password. + /// param1(string): accountName + /// + public const string resetPassword = "resetPassword"; + + /// + /// Request to set up a new password for the account. Note: account must be online. + /// param1(string): old_password + /// param2(string): new_password + /// + public const string newPassword = "newPassword"; + + /// + /// Request server binding account Email. + /// param1(string): emailAddress + /// + public const string bindAccountEmail = "bindAccountEmail"; + }; + + /// + /// 事件模块: KBEngine插件层与Unity3D表现层通过事件来交互,特别是在多线程模式下较方便 + /// + public class Event + { + public struct Pair + { + public object obj; + public string funcname; + public System.Reflection.MethodInfo method; + }; + + public struct EventObj + { + public Pair info; + public string eventname; + public object[] args; + }; + + static Dictionary> events_out = new Dictionary>(); + + public static bool outEventsImmediately = true; + + static LinkedList firedEvents_out = new LinkedList(); + static LinkedList doingEvents_out = new LinkedList(); + + static Dictionary> events_in = new Dictionary>(); + + static LinkedList firedEvents_in = new LinkedList(); + static LinkedList doingEvents_in = new LinkedList(); + + static bool _isPauseOut = false; + + public Event() + { + } + + public static void clear() + { + events_out.Clear(); + events_in.Clear(); + clearFiredEvents(); + } + + public static void clearFiredEvents() + { + monitor_Enter(events_out); + firedEvents_out.Clear(); + monitor_Exit(events_out); + + doingEvents_out.Clear(); + + monitor_Enter(events_in); + firedEvents_in.Clear(); + monitor_Exit(events_in); + + doingEvents_in.Clear(); + + _isPauseOut = false; + } + + public static void pause() + { + _isPauseOut = true; + } + + public static void resume() + { + _isPauseOut = false; + processOutEvents(); + } + + public static bool isPause() + { + return _isPauseOut; + } + + public static void monitor_Enter(object obj) + { + if(KBEngineApp.app == null) + return; + + Monitor.Enter(obj); + } + + public static void monitor_Exit(object obj) + { + if(KBEngineApp.app == null) + return; + + Monitor.Exit(obj); + } + + public static bool hasRegisterOut(string eventname) + { + return _hasRegister(events_out, eventname); + } + + public static bool hasRegisterIn(string eventname) + { + return _hasRegister(events_in, eventname); + } + + private static bool _hasRegister(Dictionary> events, string eventname) + { + bool has = false; + + monitor_Enter(events); + has = events.ContainsKey(eventname); + monitor_Exit(events); + + return has; + } + + /// + /// 注册监听由kbe插件抛出的事件。(out = kbe->render) + /// 通常由渲染表现层来注册, 例如:监听角色血量属性的变化, 如果UI层注册这个事件, + /// 事件触发后就可以根据事件所附带的当前血量值来改变角色头顶的血条值。 + /// + public static bool registerOut(string eventname, object obj, string funcname) + { + return register(events_out, eventname, obj, funcname); + } + + /// + /// 注册监听由kbe插件抛出的事件。(out = kbe->render) + /// 通常由渲染表现层来注册, 例如:监听角色血量属性的变化, 如果UI层注册这个事件, + /// 事件触发后就可以根据事件所附带的当前血量值来改变角色头顶的血条值。 + /// + public static bool registerOut(string eventname, Action handler) + { + return registerOut(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由kbe插件抛出的事件。(out = kbe->render) + /// 通常由渲染表现层来注册, 例如:监听角色血量属性的变化, 如果UI层注册这个事件, + /// 事件触发后就可以根据事件所附带的当前血量值来改变角色头顶的血条值。 + /// + public static bool registerOut(string eventname, Action handler) + { + return registerOut(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由kbe插件抛出的事件。(out = kbe->render) + /// 通常由渲染表现层来注册, 例如:监听角色血量属性的变化, 如果UI层注册这个事件, + /// 事件触发后就可以根据事件所附带的当前血量值来改变角色头顶的血条值。 + /// + public static bool registerOut(string eventname, Action handler) + { + return registerOut(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由kbe插件抛出的事件。(out = kbe->render) + /// 通常由渲染表现层来注册, 例如:监听角色血量属性的变化, 如果UI层注册这个事件, + /// 事件触发后就可以根据事件所附带的当前血量值来改变角色头顶的血条值。 + /// + public static bool registerOut(string eventname, Action handler) + { + return registerOut(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由kbe插件抛出的事件。(out = kbe->render) + /// 通常由渲染表现层来注册, 例如:监听角色血量属性的变化, 如果UI层注册这个事件, + /// 事件触发后就可以根据事件所附带的当前血量值来改变角色头顶的血条值。 + /// + public static bool registerOut(string eventname, Action handler) + { + return registerOut(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由渲染表现层抛出的事件(in = render->kbe) + /// 通常由kbe插件层来注册, 例如:UI层点击登录, 此时需要触发一个事件给kbe插件层进行与服务端交互的处理。 + /// + public static bool registerIn(string eventname, object obj, string funcname) + { + return register(events_in, eventname, obj, funcname); + } + + /// + /// 注册监听由渲染表现层抛出的事件(in = render->kbe) + /// 通常由kbe插件层来注册, 例如:UI层点击登录, 此时需要触发一个事件给kbe插件层进行与服务端交互的处理。 + /// + public static bool registerIn(string eventname, Action handler) + { + return registerIn(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由渲染表现层抛出的事件(in = render->kbe) + /// 通常由kbe插件层来注册, 例如:UI层点击登录, 此时需要触发一个事件给kbe插件层进行与服务端交互的处理。 + /// + public static bool registerIn(string eventname, Action handler) + { + return registerIn(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由渲染表现层抛出的事件(in = render->kbe) + /// 通常由kbe插件层来注册, 例如:UI层点击登录, 此时需要触发一个事件给kbe插件层进行与服务端交互的处理。 + /// + public static bool registerIn(string eventname, Action handler) + { + return registerIn(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由渲染表现层抛出的事件(in = render->kbe) + /// 通常由kbe插件层来注册, 例如:UI层点击登录, 此时需要触发一个事件给kbe插件层进行与服务端交互的处理。 + /// + public static bool registerIn(string eventname, Action handler) + { + return registerIn(eventname, handler.Target, handler.Method.Name); + } + + /// + /// 注册监听由渲染表现层抛出的事件(in = render->kbe) + /// 通常由kbe插件层来注册, 例如:UI层点击登录, 此时需要触发一个事件给kbe插件层进行与服务端交互的处理。 + /// + public static bool registerIn(string eventname, Action handler) + { + return registerIn(eventname, handler.Target, handler.Method.Name); + } + + private static bool register(Dictionary> events, string eventname, object obj, string funcname) + { + deregister(events, eventname, obj, funcname); + List lst = null; + + Pair pair = new Pair(); + pair.obj = obj; + pair.funcname = funcname; + pair.method = obj.GetType().GetMethod(funcname); + + if(pair.method == null) + { + Dbg.ERROR_MSG("Event::register: " + obj + "not found method[" + funcname + "]"); + return false; + } + + monitor_Enter(events); + if(!events.TryGetValue(eventname, out lst)) + { + lst = new List(); + lst.Add(pair); + //Dbg.DEBUG_MSG("Event::register: event(" + eventname + ")!"); + events.Add(eventname, lst); + monitor_Exit(events); + return true; + } + + //Dbg.DEBUG_MSG("Event::register: event(" + eventname + ")!"); + lst.Add(pair); + monitor_Exit(events); + return true; + } + + public static bool deregisterOut(string eventname, object obj, string funcname) + { + removeFiredEventOut(obj, eventname, funcname); + return deregister(events_out, eventname, obj, funcname); + } + + public static bool deregisterOut(string eventname, Action handler) + { + return deregisterOut(eventname, handler.Target, handler.Method.Name); + } + + public static bool deregisterIn(string eventname, object obj, string funcname) + { + removeFiredEventIn(obj, eventname, funcname); + return deregister(events_in, eventname, obj, funcname); + } + + public static bool deregisterIn(string eventname, Action handler) + { + return deregisterIn(eventname, handler.Target, handler.Method.Name); + } + + private static bool deregister(Dictionary> events, string eventname, object obj, string funcname) + { + monitor_Enter(events); + List lst = null; + + if(!events.TryGetValue(eventname, out lst)) + { + monitor_Exit(events); + return false; + } + + for(int i=0; i> events, object obj) + { + monitor_Enter(events); + + var iter = events.GetEnumerator(); + while (iter.MoveNext()) + { + List lst = iter.Current.Value; + // 从后往前遍历,以避免中途删除的问题 + for (int i = lst.Count - 1; i >= 0; i--) + { + if (obj == lst[i].obj) + { + //Dbg.DEBUG_MSG("Event::deregister: event(" + e.Key + ":" + lst[i].funcname + ")!"); + lst.RemoveAt(i); + } + } + } + + monitor_Exit(events); + return true; + } + + /// + /// kbe插件触发事件(out = kbe->render) + /// 通常由渲染表现层来注册, 例如:监听角色血量属性的变化, 如果UI层注册这个事件, + /// 事件触发后就可以根据事件所附带的当前血量值来改变角色头顶的血条值。 + /// + public static void fireOut(string eventname, params object[] args) + { + fire_(events_out, firedEvents_out, eventname, args, outEventsImmediately); + } + + /// + /// 渲染表现层抛出事件(in = render->kbe) + /// 通常由kbe插件层来注册, 例如:UI层点击登录, 此时需要触发一个事件给kbe插件层进行与服务端交互的处理。 + /// + public static void fireIn(string eventname, params object[] args) + { + fire_(events_in, firedEvents_in, eventname, args, false); + } + + /// + /// 触发kbe插件和渲染表现层都能够收到的事件 + /// + public static void fireAll(string eventname, params object[] args) + { + fire_(events_in, firedEvents_in, eventname, args, false); + fire_(events_out, firedEvents_out, eventname, args, false); + } + + private static void fire_(Dictionary> events, LinkedList firedEvents, string eventname, object[] args, bool eventsImmediately) + { + monitor_Enter(events); + List lst = null; + + if(!events.TryGetValue(eventname, out lst)) + { + //if(events == events_in) + // Dbg.WARNING_MSG("Event::fireIn: event(" + eventname + ") not found!"); + //else + // Dbg.WARNING_MSG("Event::fireOut: event(" + eventname + ") not found!"); + + monitor_Exit(events); + return; + } + + if(eventsImmediately && !_isPauseOut) + { + for(int i=0; i 0) + { + var iter = firedEvents_out.GetEnumerator(); + while (iter.MoveNext()) + { + doingEvents_out.AddLast(iter.Current); + } + + firedEvents_out.Clear(); + } + + monitor_Exit(events_out); + + while (doingEvents_out.Count > 0 && !_isPauseOut) + { + + EventObj eobj = doingEvents_out.First.Value; + + //Debug.Log("processOutEvents:" + eobj.info.funcname + "(" + eobj.info + ")"); + //foreach(object v in eobj.args) + //{ + // Debug.Log("processOutEvents:args=" + v); + //} + try + { + eobj.info.method.Invoke (eobj.info.obj, eobj.args); + } + catch (Exception e) + { + Dbg.ERROR_MSG("Event::processOutEvents: event=" + eobj.info.method.DeclaringType.FullName + "::" + eobj.info.funcname + "\n" + e.ToString()); + } + + if(doingEvents_out.Count > 0) + doingEvents_out.RemoveFirst(); + } + } + + public static void processInEvents() + { + monitor_Enter(events_in); + + if(firedEvents_in.Count > 0) + { + var iter = firedEvents_in.GetEnumerator(); + while (iter.MoveNext()) + { + doingEvents_in.AddLast(iter.Current); + } + + firedEvents_in.Clear(); + } + + monitor_Exit(events_in); + + while (doingEvents_in.Count > 0) + { + + EventObj eobj = doingEvents_in.First.Value; + + //Debug.Log("processInEvents:" + eobj.info.funcname + "(" + eobj.info + ")"); + //foreach(object v in eobj.args) + //{ + // Debug.Log("processInEvents:args=" + v); + //} + try + { + eobj.info.method.Invoke (eobj.info.obj, eobj.args); + } + catch (Exception e) + { + Dbg.ERROR_MSG("Event::processInEvents: event=" + eobj.info.method.DeclaringType.FullName + "::" + eobj.info.funcname + "\n" + e.ToString()); + } + + if(doingEvents_in.Count > 0) + doingEvents_in.RemoveFirst(); + } + } + + public static void removeAllFiredEventIn(object obj) + { + removeFiredEvent(firedEvents_in, obj); + } + + public static void removeAllFiredEventOut(object obj) + { + removeFiredEvent(firedEvents_out, obj); + } + + public static void removeFiredEventIn(object obj, string eventname, string funcname) + { + removeFiredEvent(firedEvents_in, obj, eventname, funcname); + } + + public static void removeFiredEventOut(object obj, string eventname, string funcname) + { + removeFiredEvent(firedEvents_out, obj, eventname, funcname); + } + + public static void removeFiredEvent(LinkedList firedEvents, object obj, string eventname="", string funcname="") + { + monitor_Enter(firedEvents); + + while(true) + { + bool found = false; + foreach(EventObj eobj in firedEvents) + { + if( ((eventname == "" && funcname == "") || (eventname == eobj.eventname && funcname == eobj.info.funcname)) + && eobj.info.obj == obj) + { + firedEvents.Remove(eobj); + found = true; + break; + } + } + + if (!found) + break; + } + + monitor_Exit(firedEvents); + } + + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Event.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Event.cs.meta new file mode 100644 index 00000000..f5193113 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Event.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8a53438d582f483408f4bade85969039 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/GateBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/GateBase.cs new file mode 100644 index 00000000..cbce7580 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/GateBase.cs @@ -0,0 +1,486 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class Gate : GateBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Gate.def + // Please inherit and implement "class Gate : GateBase" + public abstract class GateBase : Entity + { + public EntityBaseEntityCall_GateBase baseEntityCall = null; + public EntityCellEntityCall_GateBase cellEntityCall = null; + + public UInt32 entityNO = 0; + public virtual void onEntityNOChanged(UInt32 oldValue) {} + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + + public GateBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_GateBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_GateBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Gate"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Gate"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 51007: + UInt32 oldval_entityNO = entityNO; + entityNO = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onEntityNOChanged(oldval_entityNO); + } + else + { + if(inWorld) + onEntityNOChanged(oldval_entityNO); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["Gate"]; + Dictionary pdatas = sm.idpropertys; + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt32 oldval_entityNO = entityNO; + Property prop_entityNO = pdatas[4]; + if(prop_entityNO.isBase()) + { + if(inited && !inWorld) + onEntityNOChanged(oldval_entityNO); + } + else + { + if(inWorld) + { + if(prop_entityNO.isOwnerOnly() && !isPlayer()) + { + } + else + { + onEntityNOChanged(oldval_entityNO); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[5]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[6]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[7]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[8]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[9]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/GateBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/GateBase.cs.meta new file mode 100644 index 00000000..8d7720b7 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/GateBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 60121f9afc82ba246a14ef5b44d28956 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEMain.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEMain.cs new file mode 100644 index 00000000..94370503 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEMain.cs @@ -0,0 +1,128 @@ +using UnityEngine; +using System; +using System.Collections; +using KBEngine; + +/* + 可以理解为插件的入口模块 + 在这个入口中安装了需要监听的事件(installEvents),同时初始化KBEngine(initKBEngine) +*/ + +public class KBEMain : MonoBehaviour +{ + public KBEngineApp gameapp = null; + + // 在unity3d界面中可见选项 + public DEBUGLEVEL debugLevel = DEBUGLEVEL.DEBUG; + public bool isMultiThreads = false; + public string ip = "127.0.0.1"; + public int port = 20013; + public KBEngineApp.CLIENT_TYPE clientType = KBEngineApp.CLIENT_TYPE.CLIENT_TYPE_MINI; + public KBEngineApp.NETWORK_ENCRYPT_TYPE networkEncryptType = KBEngineApp.NETWORK_ENCRYPT_TYPE.ENCRYPT_TYPE_NONE; + public int syncPlayerMS = 1000 / 10; + + public int threadUpdateHZ = 10 * 2; + public int serverHeartbeatTick = 60; + public int TCP_SEND_BUFFER_MAX = (int)KBEngine.NetworkInterfaceBase.TCP_PACKET_MAX; + public int TCP_RECV_BUFFER_MAX = (int)KBEngine.NetworkInterfaceBase.TCP_PACKET_MAX; + public int UDP_SEND_BUFFER_MAX = (int)KBEngine.NetworkInterfaceBase.UDP_PACKET_MAX; + public int UDP_RECV_BUFFER_MAX = (int)KBEngine.NetworkInterfaceBase.UDP_PACKET_MAX; + public bool useAliasEntityID = true; + public bool isOnInitCallPropertysSetMethods = true; + public bool forceDisableUDP = false; + + public bool automaticallyUpdateSDK = true; + + protected virtual void Awake() + { + DontDestroyOnLoad(transform.gameObject); + } + + // Use this for initialization + protected virtual void Start () + { + MonoBehaviour.print("clientapp::start()"); + installEvents(); + initKBEngine(); + } + + public virtual void installEvents() + { + KBEngine.Event.registerOut(EventOutTypes.onVersionNotMatch, this, "onVersionNotMatch"); + KBEngine.Event.registerOut(EventOutTypes.onScriptVersionNotMatch, this, "onScriptVersionNotMatch"); + } + + public void onVersionNotMatch(string verInfo, string serVerInfo) + { +#if UNITY_EDITOR + if(automaticallyUpdateSDK) + gameObject.AddComponent(); +#endif + } + + public void onScriptVersionNotMatch(string verInfo, string serVerInfo) + { +#if UNITY_EDITOR + if(automaticallyUpdateSDK) + gameObject.AddComponent(); +#endif + } + + public virtual void initKBEngine() + { + // 如果此处发生错误,请查看 Assets\Scripts\kbe_scripts\if_Entity_error_use______git_submodule_update_____kbengine_plugins_______open_this_file_and_I_will_tell_you.cs + + Dbg.debugLevel = debugLevel; + + KBEngineArgs args = new KBEngineArgs(); + + args.ip = ip; + args.port = port; + args.clientType = clientType; + args.networkEncryptType = networkEncryptType; + args.syncPlayerMS = syncPlayerMS; + args.threadUpdateHZ = threadUpdateHZ; + args.serverHeartbeatTick = serverHeartbeatTick / 2; + args.useAliasEntityID = useAliasEntityID; + args.isOnInitCallPropertysSetMethods = isOnInitCallPropertysSetMethods; + args.forceDisableUDP = forceDisableUDP; + + args.TCP_SEND_BUFFER_MAX = (UInt32)TCP_SEND_BUFFER_MAX; + args.TCP_RECV_BUFFER_MAX = (UInt32)TCP_RECV_BUFFER_MAX; + args.UDP_SEND_BUFFER_MAX = (UInt32)UDP_SEND_BUFFER_MAX; + args.UDP_RECV_BUFFER_MAX = (UInt32)UDP_RECV_BUFFER_MAX; + + args.isMultiThreads = isMultiThreads; + + if(isMultiThreads) + gameapp = new KBEngineAppThread(args); + else + gameapp = new KBEngineApp(args); + } + + protected virtual void OnDestroy() + { + MonoBehaviour.print("clientapp::OnDestroy(): begin"); + if (KBEngineApp.app != null) + { + KBEngineApp.app.destroy(); + KBEngineApp.app = null; + } + KBEngine.Event.clear(); + MonoBehaviour.print("clientapp::OnDestroy(): end"); + } + + protected virtual void FixedUpdate () + { + KBEUpdate(); + } + + public virtual void KBEUpdate() + { + // 单线程模式必须自己调用 + if(!isMultiThreads) + gameapp.process(); + + KBEngine.Event.processOutEvents(); + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEMain.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEMain.cs.meta new file mode 100644 index 00000000..72452fdc --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEMain.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ad6b5538ac439864b90304b81f7c0a9b +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBETypes.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBETypes.cs new file mode 100644 index 00000000..a3bca7c8 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBETypes.cs @@ -0,0 +1,1605 @@ +/* + Generated by KBEngine! + Please do not modify this file! + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + + + // defined in */scripts/entity_defs/types.xml + + public struct UINT8 + { + Byte value; + + UINT8(Byte value) + { + this.value = value; + } + + public static implicit operator Byte(UINT8 value) + { + return value.value; + } + + public static implicit operator UINT8(Byte value) + { + Byte tvalue = (Byte)value; + return new UINT8(tvalue); + } + + public static Byte MaxValue + { + get + { + return Byte.MaxValue; + } + } + + public static Byte MinValue + { + get + { + return Byte.MinValue; + } + } + } + + public struct UINT16 + { + UInt16 value; + + UINT16(UInt16 value) + { + this.value = value; + } + + public static implicit operator UInt16(UINT16 value) + { + return value.value; + } + + public static implicit operator UINT16(UInt16 value) + { + UInt16 tvalue = (UInt16)value; + return new UINT16(tvalue); + } + + public static UInt16 MaxValue + { + get + { + return UInt16.MaxValue; + } + } + + public static UInt16 MinValue + { + get + { + return UInt16.MinValue; + } + } + } + + public struct UINT64 + { + UInt64 value; + + UINT64(UInt64 value) + { + this.value = value; + } + + public static implicit operator UInt64(UINT64 value) + { + return value.value; + } + + public static implicit operator UINT64(UInt64 value) + { + UInt64 tvalue = (UInt64)value; + return new UINT64(tvalue); + } + + public static UInt64 MaxValue + { + get + { + return UInt64.MaxValue; + } + } + + public static UInt64 MinValue + { + get + { + return UInt64.MinValue; + } + } + } + + public struct UINT32 + { + UInt32 value; + + UINT32(UInt32 value) + { + this.value = value; + } + + public static implicit operator UInt32(UINT32 value) + { + return value.value; + } + + public static implicit operator UINT32(UInt32 value) + { + UInt32 tvalue = (UInt32)value; + return new UINT32(tvalue); + } + + public static UInt32 MaxValue + { + get + { + return UInt32.MaxValue; + } + } + + public static UInt32 MinValue + { + get + { + return UInt32.MinValue; + } + } + } + + public struct INT8 + { + SByte value; + + INT8(SByte value) + { + this.value = value; + } + + public static implicit operator SByte(INT8 value) + { + return value.value; + } + + public static implicit operator INT8(SByte value) + { + SByte tvalue = (SByte)value; + return new INT8(tvalue); + } + + public static SByte MaxValue + { + get + { + return SByte.MaxValue; + } + } + + public static SByte MinValue + { + get + { + return SByte.MinValue; + } + } + } + + public struct INT16 + { + Int16 value; + + INT16(Int16 value) + { + this.value = value; + } + + public static implicit operator Int16(INT16 value) + { + return value.value; + } + + public static implicit operator INT16(Int16 value) + { + Int16 tvalue = (Int16)value; + return new INT16(tvalue); + } + + public static Int16 MaxValue + { + get + { + return Int16.MaxValue; + } + } + + public static Int16 MinValue + { + get + { + return Int16.MinValue; + } + } + } + + public struct INT32 + { + Int32 value; + + INT32(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(INT32 value) + { + return value.value; + } + + public static implicit operator INT32(Int32 value) + { + Int32 tvalue = (Int32)value; + return new INT32(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct INT64 + { + Int64 value; + + INT64(Int64 value) + { + this.value = value; + } + + public static implicit operator Int64(INT64 value) + { + return value.value; + } + + public static implicit operator INT64(Int64 value) + { + Int64 tvalue = (Int64)value; + return new INT64(tvalue); + } + + public static Int64 MaxValue + { + get + { + return Int64.MaxValue; + } + } + + public static Int64 MinValue + { + get + { + return Int64.MinValue; + } + } + } + + public struct STRING + { + string value; + + STRING(string value) + { + this.value = value; + } + + public static implicit operator string(STRING value) + { + return value.value; + } + + public static implicit operator STRING(string value) + { + string tvalue = (string)value; + return new STRING(tvalue); + } + } + + public struct UNICODE + { + string value; + + UNICODE(string value) + { + this.value = value; + } + + public static implicit operator string(UNICODE value) + { + return value.value; + } + + public static implicit operator UNICODE(string value) + { + string tvalue = (string)value; + return new UNICODE(tvalue); + } + } + + public struct FLOAT + { + float value; + + FLOAT(float value) + { + this.value = value; + } + + public static implicit operator float(FLOAT value) + { + return value.value; + } + + public static implicit operator FLOAT(float value) + { + float tvalue = (float)value; + return new FLOAT(tvalue); + } + + public static float MaxValue + { + get + { + return float.MaxValue; + } + } + + public static float MinValue + { + get + { + return float.MinValue; + } + } + } + + public struct DOUBLE + { + double value; + + DOUBLE(double value) + { + this.value = value; + } + + public static implicit operator double(DOUBLE value) + { + return value.value; + } + + public static implicit operator DOUBLE(double value) + { + double tvalue = (double)value; + return new DOUBLE(tvalue); + } + + public static double MaxValue + { + get + { + return double.MaxValue; + } + } + + public static double MinValue + { + get + { + return double.MinValue; + } + } + } + + public struct PYTHON + { + byte[] value; + + PYTHON(byte[] value) + { + this.value = value; + } + + public static implicit operator byte[](PYTHON value) + { + return value.value; + } + + public static implicit operator PYTHON(byte[] value) + { + byte[] tvalue = (byte[])value; + return new PYTHON(tvalue); + } + + public Byte this[int ID] + { + get { return value[ID]; } + set { this.value[ID] = value; } + } + } + + public struct PY_DICT + { + byte[] value; + + PY_DICT(byte[] value) + { + this.value = value; + } + + public static implicit operator byte[](PY_DICT value) + { + return value.value; + } + + public static implicit operator PY_DICT(byte[] value) + { + byte[] tvalue = (byte[])value; + return new PY_DICT(tvalue); + } + + public Byte this[int ID] + { + get { return value[ID]; } + set { this.value[ID] = value; } + } + } + + public struct PY_TUPLE + { + byte[] value; + + PY_TUPLE(byte[] value) + { + this.value = value; + } + + public static implicit operator byte[](PY_TUPLE value) + { + return value.value; + } + + public static implicit operator PY_TUPLE(byte[] value) + { + byte[] tvalue = (byte[])value; + return new PY_TUPLE(tvalue); + } + + public Byte this[int ID] + { + get { return value[ID]; } + set { this.value[ID] = value; } + } + } + + public struct PY_LIST + { + byte[] value; + + PY_LIST(byte[] value) + { + this.value = value; + } + + public static implicit operator byte[](PY_LIST value) + { + return value.value; + } + + public static implicit operator PY_LIST(byte[] value) + { + byte[] tvalue = (byte[])value; + return new PY_LIST(tvalue); + } + + public Byte this[int ID] + { + get { return value[ID]; } + set { this.value[ID] = value; } + } + } + + public struct ENTITYCALL + { + byte[] value; + + ENTITYCALL(byte[] value) + { + this.value = value; + } + + public static implicit operator byte[](ENTITYCALL value) + { + return value.value; + } + + public static implicit operator ENTITYCALL(byte[] value) + { + byte[] tvalue = (byte[])value; + return new ENTITYCALL(tvalue); + } + + public Byte this[int ID] + { + get { return value[ID]; } + set { this.value[ID] = value; } + } + } + + public struct BLOB + { + byte[] value; + + BLOB(byte[] value) + { + this.value = value; + } + + public static implicit operator byte[](BLOB value) + { + return value.value; + } + + public static implicit operator BLOB(byte[] value) + { + byte[] tvalue = (byte[])value; + return new BLOB(tvalue); + } + + public Byte this[int ID] + { + get { return value[ID]; } + set { this.value[ID] = value; } + } + } + + public struct VECTOR2 + { + Vector2 value; + + VECTOR2(Vector2 value) + { + this.value = value; + } + + public static implicit operator Vector2(VECTOR2 value) + { + return value.value; + } + + public static implicit operator VECTOR2(Vector2 value) + { + Vector2 tvalue = (Vector2)value; + return new VECTOR2(tvalue); + } + + public float x + { + get { return value.x; } + set { this.value.x = value; } + } + + public float y + { + get { return value.y; } + set { this.value.y = value; } + } + + } + + public struct VECTOR3 + { + Vector3 value; + + VECTOR3(Vector3 value) + { + this.value = value; + } + + public static implicit operator Vector3(VECTOR3 value) + { + return value.value; + } + + public static implicit operator VECTOR3(Vector3 value) + { + Vector3 tvalue = (Vector3)value; + return new VECTOR3(tvalue); + } + + public float x + { + get { return value.x; } + set { this.value.x = value; } + } + + public float y + { + get { return value.y; } + set { this.value.y = value; } + } + + public float z + { + get { return value.z; } + set { this.value.z = value; } + } + + } + + public struct VECTOR4 + { + Vector4 value; + + VECTOR4(Vector4 value) + { + this.value = value; + } + + public static implicit operator Vector4(VECTOR4 value) + { + return value.value; + } + + public static implicit operator VECTOR4(Vector4 value) + { + Vector4 tvalue = (Vector4)value; + return new VECTOR4(tvalue); + } + + public float x + { + get { return value.x; } + set { this.value.x = value; } + } + + public float y + { + get { return value.y; } + set { this.value.y = value; } + } + + public float z + { + get { return value.z; } + set { this.value.z = value; } + } + + public float w + { + get { return value.w; } + set { this.value.w = value; } + } + } + + public struct OBJECT_ID + { + Int32 value; + + OBJECT_ID(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(OBJECT_ID value) + { + return value.value; + } + + public static implicit operator OBJECT_ID(Int32 value) + { + Int32 tvalue = (Int32)value; + return new OBJECT_ID(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct BOOL + { + Byte value; + + BOOL(Byte value) + { + this.value = value; + } + + public static implicit operator Byte(BOOL value) + { + return value.value; + } + + public static implicit operator BOOL(Byte value) + { + Byte tvalue = (Byte)value; + return new BOOL(tvalue); + } + + public static Byte MaxValue + { + get + { + return Byte.MaxValue; + } + } + + public static Byte MinValue + { + get + { + return Byte.MinValue; + } + } + } + + public struct CONTROLLER_ID + { + Int32 value; + + CONTROLLER_ID(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(CONTROLLER_ID value) + { + return value.value; + } + + public static implicit operator CONTROLLER_ID(Int32 value) + { + Int32 tvalue = (Int32)value; + return new CONTROLLER_ID(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct EXPERIENCE + { + Int32 value; + + EXPERIENCE(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(EXPERIENCE value) + { + return value.value; + } + + public static implicit operator EXPERIENCE(Int32 value) + { + Int32 tvalue = (Int32)value; + return new EXPERIENCE(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct ITEM_ID + { + Int32 value; + + ITEM_ID(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(ITEM_ID value) + { + return value.value; + } + + public static implicit operator ITEM_ID(Int32 value) + { + Int32 tvalue = (Int32)value; + return new ITEM_ID(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct SKILLID + { + Int32 value; + + SKILLID(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(SKILLID value) + { + return value.value; + } + + public static implicit operator SKILLID(Int32 value) + { + Int32 tvalue = (Int32)value; + return new SKILLID(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct QUESTID + { + Int32 value; + + QUESTID(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(QUESTID value) + { + return value.value; + } + + public static implicit operator QUESTID(Int32 value) + { + Int32 tvalue = (Int32)value; + return new QUESTID(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct DBID + { + UInt64 value; + + DBID(UInt64 value) + { + this.value = value; + } + + public static implicit operator UInt64(DBID value) + { + return value.value; + } + + public static implicit operator DBID(UInt64 value) + { + UInt64 tvalue = (UInt64)value; + return new DBID(tvalue); + } + + public static UInt64 MaxValue + { + get + { + return UInt64.MaxValue; + } + } + + public static UInt64 MinValue + { + get + { + return UInt64.MinValue; + } + } + } + + public struct UID + { + UInt64 value; + + UID(UInt64 value) + { + this.value = value; + } + + public static implicit operator UInt64(UID value) + { + return value.value; + } + + public static implicit operator UID(UInt64 value) + { + UInt64 tvalue = (UInt64)value; + return new UID(tvalue); + } + + public static UInt64 MaxValue + { + get + { + return UInt64.MaxValue; + } + } + + public static UInt64 MinValue + { + get + { + return UInt64.MinValue; + } + } + } + + public struct UID1 + { + byte[] value; + + UID1(byte[] value) + { + this.value = value; + } + + public static implicit operator byte[](UID1 value) + { + return value.value; + } + + public static implicit operator UID1(byte[] value) + { + byte[] tvalue = (byte[])value; + return new UID1(tvalue); + } + + public Byte this[int ID] + { + get { return value[ID]; } + set { this.value[ID] = value; } + } + } + + public struct ENTITY_ID + { + Int32 value; + + ENTITY_ID(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(ENTITY_ID value) + { + return value.value; + } + + public static implicit operator ENTITY_ID(Int32 value) + { + Int32 tvalue = (Int32)value; + return new ENTITY_ID(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct ENTITY_NO + { + UInt32 value; + + ENTITY_NO(UInt32 value) + { + this.value = value; + } + + public static implicit operator UInt32(ENTITY_NO value) + { + return value.value; + } + + public static implicit operator ENTITY_NO(UInt32 value) + { + UInt32 tvalue = (UInt32)value; + return new ENTITY_NO(tvalue); + } + + public static UInt32 MaxValue + { + get + { + return UInt32.MaxValue; + } + } + + public static UInt32 MinValue + { + get + { + return UInt32.MinValue; + } + } + } + + public struct SPACE_ID + { + UInt32 value; + + SPACE_ID(UInt32 value) + { + this.value = value; + } + + public static implicit operator UInt32(SPACE_ID value) + { + return value.value; + } + + public static implicit operator SPACE_ID(UInt32 value) + { + UInt32 tvalue = (UInt32)value; + return new SPACE_ID(tvalue); + } + + public static UInt32 MaxValue + { + get + { + return UInt32.MaxValue; + } + } + + public static UInt32 MinValue + { + get + { + return UInt32.MinValue; + } + } + } + + public struct POSITION3D + { + Vector3 value; + + POSITION3D(Vector3 value) + { + this.value = value; + } + + public static implicit operator Vector3(POSITION3D value) + { + return value.value; + } + + public static implicit operator POSITION3D(Vector3 value) + { + Vector3 tvalue = (Vector3)value; + return new POSITION3D(tvalue); + } + + public float x + { + get { return value.x; } + set { this.value.x = value; } + } + + public float y + { + get { return value.y; } + set { this.value.y = value; } + } + + public float z + { + get { return value.z; } + set { this.value.z = value; } + } + + } + + public struct DIRECTION3D + { + Vector3 value; + + DIRECTION3D(Vector3 value) + { + this.value = value; + } + + public static implicit operator Vector3(DIRECTION3D value) + { + return value.value; + } + + public static implicit operator DIRECTION3D(Vector3 value) + { + Vector3 tvalue = (Vector3)value; + return new DIRECTION3D(tvalue); + } + + public float x + { + get { return value.x; } + set { this.value.x = value; } + } + + public float y + { + get { return value.y; } + set { this.value.y = value; } + } + + public float z + { + get { return value.z; } + set { this.value.z = value; } + } + + } + + public struct ENTITY_UTYPE + { + UInt32 value; + + ENTITY_UTYPE(UInt32 value) + { + this.value = value; + } + + public static implicit operator UInt32(ENTITY_UTYPE value) + { + return value.value; + } + + public static implicit operator ENTITY_UTYPE(UInt32 value) + { + UInt32 tvalue = (UInt32)value; + return new ENTITY_UTYPE(tvalue); + } + + public static UInt32 MaxValue + { + get + { + return UInt32.MaxValue; + } + } + + public static UInt32 MinValue + { + get + { + return UInt32.MinValue; + } + } + } + + public struct DAMAGE_TYPE + { + Int32 value; + + DAMAGE_TYPE(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(DAMAGE_TYPE value) + { + return value.value; + } + + public static implicit operator DAMAGE_TYPE(Int32 value) + { + Int32 tvalue = (Int32)value; + return new DAMAGE_TYPE(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct ENMITY + { + Int32 value; + + ENMITY(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(ENMITY value) + { + return value.value; + } + + public static implicit operator ENMITY(Int32 value) + { + Int32 tvalue = (Int32)value; + return new ENMITY(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct HP + { + Int32 value; + + HP(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(HP value) + { + return value.value; + } + + public static implicit operator HP(Int32 value) + { + Int32 tvalue = (Int32)value; + return new HP(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct MP + { + Int32 value; + + MP(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(MP value) + { + return value.value; + } + + public static implicit operator MP(Int32 value) + { + Int32 tvalue = (Int32)value; + return new MP(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public struct ENTITY_STATE + { + SByte value; + + ENTITY_STATE(SByte value) + { + this.value = value; + } + + public static implicit operator SByte(ENTITY_STATE value) + { + return value.value; + } + + public static implicit operator ENTITY_STATE(SByte value) + { + SByte tvalue = (SByte)value; + return new ENTITY_STATE(tvalue); + } + + public static SByte MaxValue + { + get + { + return SByte.MaxValue; + } + } + + public static SByte MinValue + { + get + { + return SByte.MinValue; + } + } + } + + public struct ENTITY_SUBSTATE + { + Byte value; + + ENTITY_SUBSTATE(Byte value) + { + this.value = value; + } + + public static implicit operator Byte(ENTITY_SUBSTATE value) + { + return value.value; + } + + public static implicit operator ENTITY_SUBSTATE(Byte value) + { + Byte tvalue = (Byte)value; + return new ENTITY_SUBSTATE(tvalue); + } + + public static Byte MaxValue + { + get + { + return Byte.MaxValue; + } + } + + public static Byte MinValue + { + get + { + return Byte.MinValue; + } + } + } + + public struct ENTITY_FORBIDS + { + Int32 value; + + ENTITY_FORBIDS(Int32 value) + { + this.value = value; + } + + public static implicit operator Int32(ENTITY_FORBIDS value) + { + return value.value; + } + + public static implicit operator ENTITY_FORBIDS(Int32 value) + { + Int32 tvalue = (Int32)value; + return new ENTITY_FORBIDS(tvalue); + } + + public static Int32 MaxValue + { + get + { + return Int32.MaxValue; + } + } + + public static Int32 MinValue + { + get + { + return Int32.MinValue; + } + } + } + + public class ENTITY_FORBID_COUNTER : List + { + + } + + public class ENTITYID_LIST : List + { + + } + + public class AVATAR_DATA + { + public SByte param1 = 0; + public byte[] param2 = new byte[0]; + + } + + public class AVATAR_INFOS + { + public UInt64 dbid = 0; + public string name = ""; + public Byte roleType = 0; + public UInt16 level = 0; + public AVATAR_DATA data = new AVATAR_DATA(); + + } + + public class AVATAR_INFOS_LIST + { + public List values = new List(); + + } + + public class BAG + { + public List> values22 = new List>(); + + } + + public class EXAMPLES + { + public Int64 k1 = 0; + public Int64 k2 = 0; + + } + + +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBETypes.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBETypes.cs.meta new file mode 100644 index 00000000..baec15d9 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBETypes.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0da90f7dba4d20049b98494402cb9506 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngine.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngine.cs new file mode 100644 index 00000000..b937a5ac --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngine.cs @@ -0,0 +1,2463 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Threading; + using System.Text.RegularExpressions; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /* + 这是KBEngine插件的核心模块 + 包括网络创建、持久化协议、entities的管理、以及引起对外可调用接口。 + + 一些可以参考的地方: + http://www.kbengine.org/docs/programming/clientsdkprogramming.html + http://www.kbengine.org/docs/programming/kbe_message_format.html + + http://www.kbengine.org/cn/docs/programming/clientsdkprogramming.html + http://www.kbengine.org/cn/docs/programming/kbe_message_format.html + */ + public class KBEngineApp + { + public static KBEngineApp app = null; + private NetworkInterfaceBase _networkInterface = null; + + KBEngineArgs _args = null; + + // 客户端的类别 + // http://www.kbengine.org/docs/programming/clientsdkprogramming.html + // http://www.kbengine.org/cn/docs/programming/clientsdkprogramming.html + public enum CLIENT_TYPE + { + // Mobile(Phone, Pad) + CLIENT_TYPE_MOBILE = 1, + + // Windows Application program + CLIENT_TYPE_WIN = 2, + + // Linux Application program + CLIENT_TYPE_LINUX = 3, + + // Mac Application program + CLIENT_TYPE_MAC = 4, + + // Web,HTML5,Flash + CLIENT_TYPE_BROWSER = 5, + + // bots + CLIENT_TYPE_BOTS = 6, + + // Mini-Client + CLIENT_TYPE_MINI = 7, + }; + + //加密通信类型 + public enum NETWORK_ENCRYPT_TYPE + { + //无加密 + ENCRYPT_TYPE_NONE = 0, + + //Blowfish + ENCRYPT_TYPE_BLOWFISH = 1, + }; + + public string username = "kbengine"; + public string password = "123456"; + + // 服务端分配的baseapp地址 + public string baseappIP = ""; + public UInt16 baseappTcpPort = 0; + public UInt16 baseappUdpPort = 0; + + // 当前状态 + public string currserver = ""; + public string currstate = ""; + + // 服务端下行以及客户端上行用于登录时处理的账号绑定的二进制信息 + // 该信息由用户自己进行扩展 + private byte[] _serverdatas = new byte[0]; + private byte[] _clientdatas = new byte[0]; + + // 通信协议加密,blowfish协议 + private byte[] _encryptedKey = new byte[0]; + + // 服务端与客户端的版本号以及协议MD5 + public string serverVersion = ""; + public string clientVersion = "2.5.8"; + public string serverScriptVersion = ""; + public string clientScriptVersion = "0.1.0"; + public string serverProtocolMD5 = "ACE55A2934030C0DA3446BA0E5FAB5DD"; + public string serverEntitydefMD5 = "46596D3750651E9F679C7775CD577E35"; + + // 当前玩家的实体id与实体类别 + public UInt64 entity_uuid = 0; + public Int32 entity_id = 0; + public string entity_type = ""; + + private List _controlledEntities = new List(); + + // 当前服务端最后一次同步过来的玩家位置 + private Vector3 _entityServerPos = new Vector3(0f, 0f, 0f); + + // space的数据,具体看API手册关于spaceData + // https://github.com/kbengine/kbengine/tree/master/docs/api + private Dictionary _spacedatas = new Dictionary(); + + // 所有实体都保存于这里, 请参看API手册关于entities部分 + // https://github.com/kbengine/kbengine/tree/master/docs/api + public Dictionary entities = new Dictionary(); + + // 在玩家View范围小于256个实体时我们可以通过一字节索引来找到entity + private List _entityIDAliasIDList = new List(); + private Dictionary _bufferedCreateEntityMessages = new Dictionary(); + + // 所有服务端错误码对应的错误描述 + private ServerErrorDescrs _serverErrs = new ServerErrorDescrs(); + + private System.DateTime _lastTickTime = System.DateTime.Now; + private System.DateTime _lastTickCBTime = System.DateTime.Now; + private System.DateTime _lastUpdateToServerTime = System.DateTime.Now; + + //上传玩家信息到服务器间隔,单位毫秒 + private float _updatePlayerToServerPeroid = 100.0f; + private const int _1MS_TO_100NS = 10000; + + //加密过滤器 + private EncryptionFilter _filter = null; + + // 玩家当前所在空间的id, 以及空间对应的资源 + public UInt32 spaceID = 0; + public string spaceResPath = ""; + public bool isLoadedGeometry = false; + + // 按照标准,每个客户端部分都应该包含这个属性 + public const string component = "client"; + + public KBEngineApp(KBEngineArgs args) + { + if (app != null) + throw new Exception("Only one instance of KBEngineApp!"); + + app = this; + Event.outEventsImmediately = !args.isMultiThreads; + + initialize(args); + } + + public static KBEngineApp getSingleton() + { + if(KBEngineApp.app == null) + { + throw new Exception("Please create KBEngineApp!"); + } + + return KBEngineApp.app; + } + + public virtual bool initialize(KBEngineArgs args) + { + _args = args; + _updatePlayerToServerPeroid = (float)_args.syncPlayerMS; + + EntityDef.init(); + + initNetwork(); + + // 注册事件 + installEvents(); + + return true; + } + + void initNetwork() + { + _filter = null; + Messages.init(); + _networkInterface = new NetworkInterfaceTCP(); + } + + void installEvents() + { + Event.registerIn(EventInTypes.createAccount, this, "createAccount"); + Event.registerIn(EventInTypes.login, this, "login"); + Event.registerIn(EventInTypes.logout, this, "logout"); + Event.registerIn(EventInTypes.reloginBaseapp, this, "reloginBaseapp"); + Event.registerIn(EventInTypes.resetPassword, this, "resetPassword"); + Event.registerIn(EventInTypes.bindAccountEmail, this, "bindAccountEmail"); + Event.registerIn(EventInTypes.newPassword, this, "newPassword"); + + // 内部事件 + Event.registerIn("_closeNetwork", this, "_closeNetwork"); + } + + public KBEngineArgs getInitArgs() + { + return _args; + } + + public virtual void destroy() + { + Dbg.WARNING_MSG("KBEngine::destroy()"); + + if(currserver == "baseapp") + logout(); + + reset(); + KBEngine.Event.deregisterIn(this); + resetMessages(); + + KBEngineApp.app = null; + } + + public NetworkInterfaceBase networkInterface() + { + return _networkInterface; + } + + public byte[] serverdatas() + { + return _serverdatas; + } + + public void entityServerPos(Vector3 pos) + { + _entityServerPos = pos; + } + + public void resetMessages() + { + _serverErrs.Clear(); + Messages.clear(); + EntityDef.reset(); + + Entity.clear(); + Dbg.DEBUG_MSG("KBEngine::resetMessages()"); + } + + public virtual void reset() + { + KBEngine.Event.clearFiredEvents(); + + clearEntities(true); + + currserver = ""; + currstate = ""; + _serverdatas = new byte[0]; + serverVersion = ""; + serverScriptVersion = ""; + + entity_uuid = 0; + entity_id = 0; + entity_type = ""; + + _entityIDAliasIDList.Clear(); + _bufferedCreateEntityMessages.Clear(); + + _lastTickTime = System.DateTime.Now; + _lastTickCBTime = System.DateTime.Now; + _lastUpdateToServerTime = System.DateTime.Now; + + spaceID = 0; + spaceResPath = ""; + isLoadedGeometry = false; + + if (_networkInterface != null) + _networkInterface.reset(); + + _filter = null; + _networkInterface = new NetworkInterfaceTCP(); + + _spacedatas.Clear(); + } + + public static bool validEmail(string strEmail) + { + return Regex.IsMatch(strEmail, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.) + |(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"); + } + + /* + 插件的主循环处理函数 + */ + public virtual void process() + { + // 处理网络 + if (_networkInterface != null) + _networkInterface.process(); + + // 处理外层抛入的事件 + Event.processInEvents(); + + // 向服务端发送心跳以及同步角色信息到服务端 + sendTick(); + } + + /* + 当前玩家entity + */ + public Entity player() + { + Entity e; + if(entities.TryGetValue(entity_id, out e)) + return e; + + return null; + } + + public void _closeNetwork(NetworkInterfaceBase networkInterface) + { + networkInterface.close(); + } + + /* + 向服务端发送心跳以及同步角色信息到服务端 + */ + public void sendTick() + { + if(_networkInterface == null || _networkInterface.connected == false) + return; + + TimeSpan span = DateTime.Now - _lastTickTime; + + // 更新玩家的位置与朝向到服务端 + updatePlayerToServer(); + + if(_args.serverHeartbeatTick > 0 && span.Seconds > _args.serverHeartbeatTick) + { + span = _lastTickCBTime - _lastTickTime; + + // 如果心跳回调接收时间小于心跳发送时间,说明没有收到回调 + // 此时应该通知客户端掉线了 + if(span.Seconds < 0) + { + Dbg.ERROR_MSG("sendTick: Receive appTick timeout!"); + _networkInterface.close(); + return; + } + + Message Loginapp_onClientActiveTickMsg = null; + Message Baseapp_onClientActiveTickMsg = null; + + Messages.messages.TryGetValue("Loginapp_onClientActiveTick", out Loginapp_onClientActiveTickMsg); + Messages.messages.TryGetValue("Baseapp_onClientActiveTick", out Baseapp_onClientActiveTickMsg); + + if(currserver == "loginapp") + { + if(Loginapp_onClientActiveTickMsg != null) + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Loginapp_onClientActiveTick"]); + bundle.send(_networkInterface); + } + } + else + { + if(Baseapp_onClientActiveTickMsg != null) + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_onClientActiveTick"]); + bundle.send(_networkInterface); + } + } + + _lastTickTime = System.DateTime.Now; + } + } + + /* + 服务器心跳回调 + */ + public void Client_onAppActiveTickCB() + { + _lastTickCBTime = System.DateTime.Now; + } + + /* + 与服务端握手,与任何一个进程连接之后应该第一时间进行握手 + */ + public void hello() + { + Bundle bundle = Bundle.createObject(); + if(currserver == "loginapp") + bundle.newMessage(Messages.messages["Loginapp_hello"]); + else + bundle.newMessage(Messages.messages["Baseapp_hello"]); + + _filter = null; + + if (_args.networkEncryptType == NETWORK_ENCRYPT_TYPE.ENCRYPT_TYPE_BLOWFISH) + { + _filter = new BlowfishFilter(); + _encryptedKey = ((BlowfishFilter)_filter).key(); + _networkInterface.setFilter(null); + } + + bundle.writeString(clientVersion); + bundle.writeString(clientScriptVersion); + bundle.writeBlob(_encryptedKey); + bundle.send(_networkInterface); + } + + /* + 握手之后服务端的回调 + */ + public void Client_onHelloCB(MemoryStream stream) + { + string str_serverVersion = stream.readString(); + serverScriptVersion = stream.readString(); + string currentServerProtocolMD5 = stream.readString(); + string currentServerEntitydefMD5 = stream.readString(); + Int32 ctype = stream.readInt32(); + + Dbg.DEBUG_MSG("KBEngine::Client_onHelloCB: verInfo(" + str_serverVersion + + "), scriptVersion("+ serverScriptVersion + "), srvProtocolMD5("+ serverProtocolMD5 + + "), srvEntitydefMD5("+ serverEntitydefMD5 + "), + ctype(" + ctype + ")!"); + + if(str_serverVersion != "Getting") + { + serverVersion = str_serverVersion; + + /* + if(serverProtocolMD5 != currentServerProtocolMD5) + { + Dbg.ERROR_MSG("Client_onHelloCB: digest not match! serverProtocolMD5=" + serverProtocolMD5 + "(server: " + currentServerProtocolMD5 + ")"); + Event.fireAll(EventOutTypes.onVersionNotMatch, clientVersion, serverVersion); + return; + } + */ + + if (serverEntitydefMD5 != currentServerEntitydefMD5) + { + Dbg.ERROR_MSG("Client_onHelloCB: digest not match! serverEntitydefMD5=" + serverEntitydefMD5 + "(server: " + currentServerEntitydefMD5 + ")"); + Event.fireAll(EventOutTypes.onVersionNotMatch, clientVersion, serverVersion); + return; + } + } + + if (_args.networkEncryptType == NETWORK_ENCRYPT_TYPE.ENCRYPT_TYPE_BLOWFISH) + { + _networkInterface.setFilter(_filter); + _filter = null; + } + + onServerDigest(); + + if(currserver == "baseapp") + { + onLogin_baseapp(); + } + else + { + onLogin_loginapp(); + } + } + + /* + 服务端错误描述导入了 + */ + public void Client_onImportServerErrorsDescr(MemoryStream stream) + { + // 无需实现,已由插件生成静态代码 + } + + /* + 从服务端返回的二进制流导入客户端消息协议 + */ + public void Client_onImportClientMessages(MemoryStream stream) + { + // 无需实现,已由插件生成静态代码 + } + + /* + 从服务端返回的二进制流导入客户端消息协议 + */ + public void Client_onImportClientEntityDef(MemoryStream stream) + { + // 无需实现,已由插件生成静态代码 + } + + public void Client_onImportClientSDK(MemoryStream stream) + { + int remainingFiles = 0; + remainingFiles = stream.readInt32(); + + string fileName; + fileName = stream.readString(); + + int fileSize = 0; + fileSize = stream.readInt32(); + + byte[] fileDatas = new byte[0]; + fileDatas = stream.readBlob(); + + Event.fireIn("onImportClientSDK", remainingFiles, fileName, fileSize, fileDatas); + } + + /* + 引擎版本不匹配 + */ + public void Client_onVersionNotMatch(MemoryStream stream) + { + serverVersion = stream.readString(); + + Dbg.ERROR_MSG("Client_onVersionNotMatch: verInfo=" + clientVersion + "(server: " + serverVersion + ")"); + Event.fireAll(EventOutTypes.onVersionNotMatch, clientVersion, serverVersion); + } + + /* + 脚本版本不匹配 + */ + public void Client_onScriptVersionNotMatch(MemoryStream stream) + { + serverScriptVersion = stream.readString(); + + Dbg.ERROR_MSG("Client_onScriptVersionNotMatch: verInfo=" + clientScriptVersion + "(server: " + serverScriptVersion + ")"); + Event.fireAll(EventOutTypes.onScriptVersionNotMatch, clientScriptVersion, serverScriptVersion); + } + + /* + 被服务端踢出 + */ + public void Client_onKicked(UInt16 failedcode) + { + Dbg.DEBUG_MSG("Client_onKicked: failedcode=" + failedcode + "(" + serverErr(failedcode) + ")"); + Event.fireAll(EventOutTypes.onKicked, failedcode); + } + + /* + 登录到服务端,必须登录完成loginapp与网关(baseapp),登录流程才算完毕 + */ + public void login(string username, string password, byte[] datas) + { + KBEngineApp.app.username = username; + KBEngineApp.app.password = password; + KBEngineApp.app._clientdatas = datas; + + KBEngineApp.app.login_loginapp(true); + } + + /* + 登录到服务端(loginapp), 登录成功后还必须登录到网关(baseapp)登录流程才算完毕 + */ + public void login_loginapp(bool noconnect) + { + if(noconnect) + { + reset(); + _networkInterface.connectTo(_args.ip, _args.port, onConnectTo_loginapp_callback, null); + } + else + { + Dbg.DEBUG_MSG("KBEngine::login_loginapp(): send login! username=" + username); + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Loginapp_login"]); + bundle.writeInt8((sbyte)_args.clientType); + bundle.writeBlob(KBEngineApp.app._clientdatas); + bundle.writeString(username); + bundle.writeString(password); + bundle.send(_networkInterface); + } + } + + private void onConnectTo_loginapp_callback(string ip, int port, bool success, object userData) + { + _lastTickCBTime = System.DateTime.Now; + + if(!success) + { + Dbg.ERROR_MSG(string.Format("KBEngine::login_loginapp(): connect {0}:{1} error!", ip, port)); + return; + } + + currserver = "loginapp"; + currstate = "login"; + + Dbg.DEBUG_MSG(string.Format("KBEngine::login_loginapp(): connect {0}:{1} success!", ip, port)); + + hello(); + } + + private void onLogin_loginapp() + { + _lastTickCBTime = System.DateTime.Now; + login_loginapp(false); + } + + /* + 登录到服务端,登录到网关(baseapp) + */ + public void login_baseapp(bool noconnect) + { + if(noconnect) + { + Event.fireOut(EventOutTypes.onLoginBaseapp); + + _networkInterface.reset(); + + if(_args.forceDisableUDP || baseappUdpPort == 0) + { + _networkInterface = new NetworkInterfaceTCP(); + _networkInterface.connectTo(baseappIP, baseappTcpPort, onConnectTo_baseapp_callback, null); + } + else + { + _networkInterface = new NetworkInterfaceKCP(); + _networkInterface.connectTo(baseappIP, baseappUdpPort, onConnectTo_baseapp_callback, null); + } + } + else + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_loginBaseapp"]); + bundle.writeString(username); + bundle.writeString(password); + bundle.send(_networkInterface); + } + } + + private void onConnectTo_baseapp_callback(string ip, int port, bool success, object userData) + { + _lastTickCBTime = System.DateTime.Now; + + if(!success) + { + Dbg.ERROR_MSG(string.Format("KBEngine::login_baseapp(): connect {0}:{1} error!", ip, port)); + return; + } + + currserver = "baseapp"; + currstate = ""; + + Dbg.DEBUG_MSG(string.Format("KBEngine::login_baseapp(): connect {0}:{1} success!", ip, port)); + + hello(); + } + + private void onLogin_baseapp() + { + _lastTickCBTime = System.DateTime.Now; + login_baseapp(false); + } + + /* + 重登录到网关(baseapp) + 一些移动类应用容易掉线,可以使用该功能快速的重新与服务端建立通信 + */ + public void reloginBaseapp() + { + _lastTickTime = System.DateTime.Now; + _lastTickCBTime = System.DateTime.Now; + + if(_networkInterface.valid()) + return; + + Event.fireAll(EventOutTypes.onReloginBaseapp); + + _networkInterface.reset(); + + if(_args.forceDisableUDP || baseappUdpPort == 0) + { + _networkInterface = new NetworkInterfaceTCP(); + _networkInterface.connectTo(baseappIP, baseappTcpPort, onReConnectTo_baseapp_callback, null); + } + else + { + _networkInterface = new NetworkInterfaceKCP(); + _networkInterface.connectTo(baseappIP, baseappUdpPort, onReConnectTo_baseapp_callback, null); + } + } + + private void onReConnectTo_baseapp_callback(string ip, int port, bool success, object userData) + { + if(!success) + { + Dbg.ERROR_MSG(string.Format("KBEngine::reloginBaseapp(): connect {0}:{1} error!", ip, port)); + return; + } + + Dbg.DEBUG_MSG(string.Format("KBEngine::relogin_baseapp(): connect {0}:{1} success!", ip, port)); + + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_reloginBaseapp"]); + bundle.writeString(username); + bundle.writeString(password); + bundle.writeUint64(entity_uuid); + bundle.writeInt32(entity_id); + bundle.send(_networkInterface); + + _lastTickCBTime = System.DateTime.Now; + } + + /* + 登出baseapp + */ + public void logout() + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_logoutBaseapp"]); + bundle.writeUint64(entity_uuid); + bundle.writeInt32(entity_id); + bundle.send(_networkInterface); + } + + /* + 通过错误id得到错误描述 + */ + public string serverErr(UInt16 id) + { + return _serverErrs.serverErrStr(id); + } + + public void onOpenLoginapp_resetpassword() + { + Dbg.DEBUG_MSG("KBEngine::onOpenLoginapp_resetpassword: successfully!"); + currserver = "loginapp"; + currstate = "resetpassword"; + _lastTickCBTime = System.DateTime.Now; + + resetpassword_loginapp(false); + } + + /* + 重置密码, 通过loginapp + */ + public void resetPassword(string username) + { + KBEngineApp.app.username = username; + resetpassword_loginapp(true); + } + + /* + 重置密码, 通过loginapp + */ + public void resetpassword_loginapp(bool noconnect) + { + if(noconnect) + { + reset(); + _networkInterface.connectTo(_args.ip, _args.port, onConnectTo_resetpassword_callback, null); + } + else + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Loginapp_reqAccountResetPassword"]); + bundle.writeString(username); + bundle.send(_networkInterface); + } + } + + private void onConnectTo_resetpassword_callback(string ip, int port, bool success, object userData) + { + _lastTickCBTime = System.DateTime.Now; + + if(!success) + { + Dbg.ERROR_MSG(string.Format("KBEngine::resetpassword_loginapp(): connect {0}:{1} error!", ip, port)); + return; + } + + Dbg.DEBUG_MSG(string.Format("KBEngine::resetpassword_loginapp(): connect {0}:{1} success!", ip, port)); + onOpenLoginapp_resetpassword(); + } + + public void Client_onReqAccountResetPasswordCB(UInt16 failcode) + { + Event.fireOut(EventOutTypes.onResetPassword, failcode); + + if(failcode != 0) + { + Dbg.ERROR_MSG("KBEngine::Client_onReqAccountResetPasswordCB: " + username + " failed! code=" + failcode + "(" + serverErr(failcode) + ")!"); + return; + } + + Dbg.DEBUG_MSG("KBEngine::Client_onReqAccountResetPasswordCB: " + username + " success!"); + } + + /* + 绑定Email,通过baseapp + */ + public void bindAccountEmail(string emailAddress) + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_reqAccountBindEmail"]); + bundle.writeInt32(entity_id); + bundle.writeString(password); + bundle.writeString(emailAddress); + bundle.send(_networkInterface); + } + + public void Client_onReqAccountBindEmailCB(UInt16 failcode) + { + Event.fireOut(EventOutTypes.onBindAccountEmail, failcode); + + if(failcode != 0) + { + Dbg.ERROR_MSG("KBEngine::Client_onReqAccountBindEmailCB: " + username + " failed! code=" + failcode + "(" + serverErr(failcode) + ")!"); + return; + } + + Dbg.DEBUG_MSG("KBEngine::Client_onReqAccountBindEmailCB: " + username + " success!"); + } + + /* + 设置新密码,通过baseapp, 必须玩家登录在线操作所以是baseapp。 + */ + public void newPassword(string old_password, string new_password) + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_reqAccountNewPassword"]); + bundle.writeInt32(entity_id); + bundle.writeString(old_password); + bundle.writeString(new_password); + bundle.send(_networkInterface); + } + + public void Client_onReqAccountNewPasswordCB(UInt16 failcode) + { + Event.fireOut(EventOutTypes.onNewPassword, failcode); + + if(failcode != 0) + { + Dbg.ERROR_MSG("KBEngine::Client_onReqAccountNewPasswordCB: " + username + " failed! code=" + failcode + "(" + serverErr(failcode) + ")!"); + return; + } + + Dbg.DEBUG_MSG("KBEngine::Client_onReqAccountNewPasswordCB: " + username + " success!"); + } + + public void createAccount(string username, string password, byte[] datas) + { + KBEngineApp.app.username = username; + KBEngineApp.app.password = password; + KBEngineApp.app._clientdatas = datas; + + KBEngineApp.app.createAccount_loginapp(true); + } + + /* + 创建账号,通过loginapp + */ + public void createAccount_loginapp(bool noconnect) + { + if(noconnect) + { + reset(); + _networkInterface.connectTo(_args.ip, _args.port, onConnectTo_createAccount_callback, null); + } + else + { + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Loginapp_reqCreateAccount"]); + bundle.writeString(username); + bundle.writeString(password); + bundle.writeBlob(KBEngineApp.app._clientdatas); + bundle.send(_networkInterface); + } + } + + public void onOpenLoginapp_createAccount() + { + Dbg.DEBUG_MSG("KBEngine::onOpenLoginapp_createAccount: successfully!"); + currserver = "loginapp"; + currstate = "createAccount"; + _lastTickCBTime = System.DateTime.Now; + + createAccount_loginapp(false); + } + + private void onConnectTo_createAccount_callback(string ip, int port, bool success, object userData) + { + _lastTickCBTime = System.DateTime.Now; + + if(!success) + { + Dbg.ERROR_MSG(string.Format("KBEngine::createAccount_loginapp(): connect {0}:{1} error!", ip, port)); + return; + } + + Dbg.DEBUG_MSG(string.Format("KBEngine::createAccount_loginapp(): connect {0}:{1} success!", ip, port)); + onOpenLoginapp_createAccount(); + } + + /* + 获得了服务端摘要信息, 摘要包括协议MD5, entitydefMD5 + */ + public void onServerDigest() + { + } + + /* + 登录loginapp失败了 + */ + public void Client_onLoginFailed(MemoryStream stream) + { + UInt16 failedcode = stream.readUint16(); + _serverdatas = stream.readBlob(); + Dbg.ERROR_MSG("KBEngine::Client_onLoginFailed: failedcode(" + failedcode + ":" + serverErr(failedcode) + "), datas(" + _serverdatas.Length + ")!"); + Event.fireAll(EventOutTypes.onLoginFailed, failedcode, _serverdatas); + } + + /* + 登录loginapp成功了 + */ + public void Client_onLoginSuccessfully(MemoryStream stream) + { + var accountName = stream.readString(); + username = accountName; + baseappIP = stream.readString(); + baseappTcpPort = stream.readUint16(); + baseappUdpPort = stream.readUint16(); + _serverdatas = stream.readBlob(); + + Dbg.DEBUG_MSG("KBEngine::Client_onLoginSuccessfully: accountName(" + accountName + "), addr(" + + baseappIP + ":" + baseappTcpPort + "|" + baseappUdpPort + "), datas(" + _serverdatas.Length + ")!"); + + login_baseapp(true); + } + + /* + 登录baseapp失败了 + */ + public void Client_onLoginBaseappFailed(UInt16 failedcode) + { + Dbg.ERROR_MSG("KBEngine::Client_onLoginBaseappFailed: failedcode=" + failedcode + "("+ serverErr(failedcode) + ")!"); + Event.fireAll(EventOutTypes.onLoginBaseappFailed, failedcode); + } + + /* + 重登录baseapp失败了 + */ + public void Client_onReloginBaseappFailed(UInt16 failedcode) + { + Dbg.ERROR_MSG("KBEngine::Client_onReloginBaseappFailed: failedcode=" + failedcode + "(" + serverErr(failedcode) + ")!"); + Event.fireAll(EventOutTypes.onReloginBaseappFailed, failedcode); + } + + /* + 登录baseapp成功了 + */ + public void Client_onReloginBaseappSuccessfully(MemoryStream stream) + { + entity_uuid = stream.readUint64(); + Dbg.DEBUG_MSG("KBEngine::Client_onReloginBaseappSuccessfully: name(" + username + ")!"); + Event.fireAll(EventOutTypes.onReloginBaseappSuccessfully); + } + + /* + 服务端通知创建一个角色 + */ + public void Client_onCreatedProxies(UInt64 rndUUID, Int32 eid, string entityType) + { + Dbg.DEBUG_MSG("KBEngine::Client_onCreatedProxies: eid(" + eid + "), entityType(" + entityType + ")!"); + + entity_uuid = rndUUID; + entity_id = eid; + entity_type = entityType; + + if(!this.entities.ContainsKey(eid)) + { + ScriptModule module = null; + if(!EntityDef.moduledefs.TryGetValue(entityType, out module)) + { + Dbg.ERROR_MSG("KBEngine::Client_onCreatedProxies: not found module(" + entityType + ")!"); + return; + } + + Type runclass = module.entityScript; + if(runclass == null) + return; + + Entity entity = (Entity)Activator.CreateInstance(runclass); + entity.id = eid; + entity.className = entityType; + entity.onGetBase(); + + entities[eid] = entity; + + MemoryStream entityMessage = null; + _bufferedCreateEntityMessages.TryGetValue(eid, out entityMessage); + + if(entityMessage != null) + { + Client_onUpdatePropertys(entityMessage); + _bufferedCreateEntityMessages.Remove(eid); + entityMessage.reclaimObject(); + } + + entity.__init__(); + entity.attachComponents(); + entity.inited = true; + + if(_args.isOnInitCallPropertysSetMethods) + entity.callPropertysSetMethods(); + } + else + { + MemoryStream entityMessage = null; + _bufferedCreateEntityMessages.TryGetValue(eid, out entityMessage); + + if(entityMessage != null) + { + Client_onUpdatePropertys(entityMessage); + _bufferedCreateEntityMessages.Remove(eid); + entityMessage.reclaimObject(); + } + } + } + + public Entity findEntity(Int32 entityID) + { + Entity entity = null; + + if(!entities.TryGetValue(entityID, out entity)) + { + return null; + } + + return entity; + } + + /* + 通过流数据获得View实体的ID + */ + public Int32 getViewEntityIDFromStream(MemoryStream stream) + { + if (!_args.useAliasEntityID) + return stream.readInt32(); + + Int32 id = 0; + if(_entityIDAliasIDList.Count > 255) + { + id = stream.readInt32(); + } + else + { + byte aliasID = stream.readUint8(); + + // 如果为0且客户端上一步是重登陆或者重连操作并且服务端entity在断线期间一直处于在线状态 + // 则可以忽略这个错误, 因为cellapp可能一直在向baseapp发送同步消息, 当客户端重连上时未等 + // 服务端初始化步骤开始则收到同步信息, 此时这里就会出错。 + if(_entityIDAliasIDList.Count <= aliasID) + return 0; + + id = _entityIDAliasIDList[aliasID]; + } + + return id; + } + + /* + 服务端使用优化的方式更新实体属性数据 + */ + public void Client_onUpdatePropertysOptimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + onUpdatePropertys_(eid, stream); + } + + /* + 服务端更新实体属性数据 + */ + public void Client_onUpdatePropertys(MemoryStream stream) + { + Int32 eid = stream.readInt32(); + onUpdatePropertys_(eid, stream); + } + + public void onUpdatePropertys_(Int32 eid, MemoryStream stream) + { + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + MemoryStream entityMessage = null; + if(_bufferedCreateEntityMessages.TryGetValue(eid, out entityMessage)) + { + Dbg.ERROR_MSG("KBEngine::Client_onUpdatePropertys: entity(" + eid + ") not found!"); + return; + } + + MemoryStream stream1 = MemoryStream.createObject(); + stream1.wpos = stream.wpos; + stream1.rpos = stream.rpos - 4; + Array.Copy(stream.data(), stream1.data(), stream.wpos); + _bufferedCreateEntityMessages[eid] = stream1; + return; + } + + entity.onUpdatePropertys(stream); + } + + /* + 服务端使用优化的方式调用实体方法 + */ + public void Client_onRemoteMethodCallOptimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + onRemoteMethodCall_(eid, stream); + } + + /* + 服务端调用实体方法 + */ + public void Client_onRemoteMethodCall(MemoryStream stream) + { + Int32 eid = stream.readInt32(); + onRemoteMethodCall_(eid, stream); + } + + public void onRemoteMethodCall_(Int32 eid, MemoryStream stream) + { + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onRemoteMethodCall: entity(" + eid + ") not found!"); + return; + } + + entity.onRemoteMethodCall(stream); + } + + /* + 服务端通知一个实体进入了世界(如果实体是当前玩家则玩家第一次在一个space中创建了, 如果是其他实体则是其他实体进入了玩家的View) + */ + public void Client_onEntityEnterWorld(MemoryStream stream) + { + Int32 eid = stream.readInt32(); + if(entity_id > 0 && entity_id != eid) + _entityIDAliasIDList.Add(eid); + + UInt16 uentityType; + if(EntityDef.idmoduledefs.Count > 255) + uentityType = stream.readUint16(); + else + uentityType = stream.readUint8(); + + sbyte isOnGround = 1; + + if(stream.length() > 0) + isOnGround = stream.readInt8(); + + string entityType = EntityDef.idmoduledefs[uentityType].name; + // Dbg.DEBUG_MSG("KBEngine::Client_onEntityEnterWorld: " + entityType + "(" + eid + "), spaceID(" + KBEngineApp.app.spaceID + ")!"); + + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + MemoryStream entityMessage = null; + if(!_bufferedCreateEntityMessages.TryGetValue(eid, out entityMessage)) + { + Dbg.ERROR_MSG("KBEngine::Client_onEntityEnterWorld: entity(" + eid + ") not found!"); + return; + } + + ScriptModule module = null; + if(!EntityDef.moduledefs.TryGetValue(entityType, out module)) + { + Dbg.ERROR_MSG("KBEngine::Client_onEntityEnterWorld: not found module(" + entityType + ")!"); + } + + Type runclass = module.entityScript; + if(runclass == null) + return; + + entity = (Entity)Activator.CreateInstance(runclass); + entity.id = eid; + entity.className = entityType; + entity.onGetCell(); + + entities[eid] = entity; + + Client_onUpdatePropertys(entityMessage); + _bufferedCreateEntityMessages.Remove(eid); + entityMessage.reclaimObject(); + + entity.isOnGround = isOnGround > 0; + entity.onDirectionChanged(entity.direction); + entity.onPositionChanged(entity.position); + + entity.__init__(); + entity.attachComponents(); + entity.inited = true; + entity.inWorld = true; + entity.enterWorld(); + + if(_args.isOnInitCallPropertysSetMethods) + entity.callPropertysSetMethods(); + } + else + { + if(!entity.inWorld) + { + // 安全起见, 这里清空一下 + // 如果服务端上使用giveClientTo切换控制权 + // 之前的实体已经进入世界, 切换后的实体也进入世界, 这里可能会残留之前那个实体进入世界的信息 + _entityIDAliasIDList.Clear(); + clearEntities(false); + entities[entity.id] = entity; + + entity.onGetCell(); + + entity.onDirectionChanged(entity.direction); + entity.onPositionChanged(entity.position); + + _entityServerPos = entity.position; + entity.isOnGround = isOnGround > 0; + entity.inWorld = true; + entity.enterWorld(); + + if(_args.isOnInitCallPropertysSetMethods) + entity.callPropertysSetMethods(); + } + } + } + + /* + 服务端使用优化的方式通知一个实体离开了世界(如果实体是当前玩家则玩家离开了space, 如果是其他实体则是其他实体离开了玩家的View) + */ + public void Client_onEntityLeaveWorldOptimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + KBEngineApp.app.Client_onEntityLeaveWorld(eid); + } + + /* + 服务端通知一个实体离开了世界(如果实体是当前玩家则玩家离开了space, 如果是其他实体则是其他实体离开了玩家的View) + */ + public void Client_onEntityLeaveWorld(Int32 eid) + { + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onEntityLeaveWorld: entity(" + eid + ") not found!"); + return; + } + + if(entity.inWorld) + entity.leaveWorld(); + + if(entity_id == eid) + { + clearSpace(false); + entity.onLoseCell(); + } + else + { + if(_controlledEntities.Remove(entity)) + Event.fireOut(EventOutTypes.onLoseControlledEntity, entity); + + entities.Remove(eid); + entity.destroy(); + _entityIDAliasIDList.Remove(eid); + } + } + + /* + 服务端通知当前玩家进入了一个新的space + */ + public void Client_onEntityEnterSpace(MemoryStream stream) + { + Int32 eid = stream.readInt32(); + spaceID = stream.readUint32(); + + sbyte isOnGround = 1; + + if(stream.length() > 0) + isOnGround = stream.readInt8(); + + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onEntityEnterSpace: entity(" + eid + ") not found!"); + return; + } + + entity.isOnGround = isOnGround > 0; + _entityServerPos = entity.position; + entity.enterSpace(); + } + + /* + 服务端通知当前玩家离开了space + */ + public void Client_onEntityLeaveSpace(Int32 eid) + { + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onEntityLeaveSpace: entity(" + eid + ") not found!"); + return; + } + + entity.leaveSpace(); + clearSpace(false); + } + + /* + 账号创建返回结果 + */ + public void Client_onCreateAccountResult(MemoryStream stream) + { + UInt16 retcode = stream.readUint16(); + byte[] datas = stream.readBlob(); + + Event.fireOut(EventOutTypes.onCreateAccountResult, retcode, datas); + + if(retcode != 0) + { + Dbg.WARNING_MSG("KBEngine::Client_onCreateAccountResult: " + username + " create is failed! code=" + retcode + "(" + serverErr(retcode)+ ")!"); + return; + } + + Dbg.DEBUG_MSG("KBEngine::Client_onCreateAccountResult: " + username + " create is successfully!"); + } + + /* + 告诉客户端:你当前负责(或取消)控制谁的位移同步 + */ + public void Client_onControlEntity(Int32 eid, sbyte isControlled) + { + Entity entity = null; + + if (!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onControlEntity: entity(" + eid + ") not found!"); + return; + } + + var isCont = isControlled != 0; + if (isCont) + { + // 如果被控制者是玩家自己,那表示玩家自己被其它人控制了 + // 所以玩家自己不应该进入这个被控制列表 + if (player().id != entity.id) + { + _controlledEntities.Add(entity); + } + } + else + { + _controlledEntities.Remove(entity); + } + + entity.isControlled = isCont; + + try + { + entity.onControlled(isCont); + Event.fireOut(EventOutTypes.onControlled, entity, isCont); + } + catch (Exception e) + { + Dbg.ERROR_MSG(string.Format("KBEngine::Client_onControlEntity: entity id = '{0}', is controlled = '{1}', error = '{1}'", eid, isCont, e)); + } + } + + /* + 更新当前玩家的位置与朝向到服务端, 可以通过开关_syncPlayerMS关闭这个机制 + */ + public void updatePlayerToServer() + { + if(_updatePlayerToServerPeroid <= 0.01f || spaceID == 0) + { + return; + } + + var now = DateTime.Now; + TimeSpan span = now - _lastUpdateToServerTime; + + if (span.Ticks < _updatePlayerToServerPeroid * _1MS_TO_100NS) + return; + + Entity playerEntity = player(); + if (playerEntity == null || playerEntity.inWorld == false || playerEntity.isControlled) + return; + + _lastUpdateToServerTime = now - (span - TimeSpan.FromTicks(Convert.ToInt64(_updatePlayerToServerPeroid * _1MS_TO_100NS))); + + Vector3 position = playerEntity.position; + Vector3 direction = playerEntity.direction; + + bool posHasChanged = Vector3.Distance(playerEntity._entityLastLocalPos, position) > 0.001f; + bool dirHasChanged = Vector3.Distance(playerEntity._entityLastLocalDir, direction) > 0.001f; + + if(posHasChanged || dirHasChanged) + { + playerEntity._entityLastLocalPos = position; + playerEntity._entityLastLocalDir = direction; + + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_onUpdateDataFromClient"]); + bundle.writeFloat(position.x); + bundle.writeFloat(position.y); + bundle.writeFloat(position.z); + + double x = ((double)direction.x / 360 * (System.Math.PI * 2)); + double y = ((double)direction.y / 360 * (System.Math.PI * 2)); + double z = ((double)direction.z / 360 * (System.Math.PI * 2)); + + // 根据弧度转角度公式会出现负数 + // unity会自动转化到0~360度之间,这里需要做一个还原 + if(x - System.Math.PI > 0.0) + x -= System.Math.PI * 2; + + if(y - System.Math.PI > 0.0) + y -= System.Math.PI * 2; + + if(z - System.Math.PI > 0.0) + z -= System.Math.PI * 2; + + bundle.writeFloat((float)x); + bundle.writeFloat((float)y); + bundle.writeFloat((float)z); + bundle.writeUint8((Byte)(playerEntity.isOnGround == true ? 1 : 0)); + bundle.writeUint32(spaceID); + bundle.send(_networkInterface); + } + + // 开始同步所有被控制了的entity的位置 + for (int i = 0; i < _controlledEntities.Count; ++i) + { + var entity = _controlledEntities[i]; + position = entity.position; + direction = entity.direction; + + posHasChanged = Vector3.Distance(entity._entityLastLocalPos, position) > 0.001f; + dirHasChanged = Vector3.Distance(entity._entityLastLocalDir, direction) > 0.001f; + + if (posHasChanged || dirHasChanged) + { + entity._entityLastLocalPos = position; + entity._entityLastLocalDir = direction; + + Bundle bundle = Bundle.createObject(); + bundle.newMessage(Messages.messages["Baseapp_onUpdateDataFromClientForControlledEntity"]); + bundle.writeInt32(entity.id); + bundle.writeFloat(position.x); + bundle.writeFloat(position.y); + bundle.writeFloat(position.z); + + double x = ((double)direction.x / 360 * (System.Math.PI * 2)); + double y = ((double)direction.y / 360 * (System.Math.PI * 2)); + double z = ((double)direction.z / 360 * (System.Math.PI * 2)); + + // 根据弧度转角度公式会出现负数 + // unity会自动转化到0~360度之间,这里需要做一个还原 + if(x - System.Math.PI > 0.0) + x -= System.Math.PI * 2; + + if(y - System.Math.PI > 0.0) + y -= System.Math.PI * 2; + + if(z - System.Math.PI > 0.0) + z -= System.Math.PI * 2; + + bundle.writeFloat((float)x); + bundle.writeFloat((float)y); + bundle.writeFloat((float)z); + bundle.writeUint8((Byte)(entity.isOnGround == true ? 1 : 0)); + bundle.writeUint32(spaceID); + bundle.send(_networkInterface); + } + } + } + + /* + 当前space添加了关于几何等信息的映射资源 + 客户端可以通过这个资源信息来加载对应的场景 + */ + public void addSpaceGeometryMapping(UInt32 uspaceID, string respath) + { + Dbg.DEBUG_MSG("KBEngine::addSpaceGeometryMapping: spaceID(" + uspaceID + "), respath(" + respath + ")!"); + + isLoadedGeometry = true; + spaceID = uspaceID; + spaceResPath = respath; + Event.fireOut(EventOutTypes.addSpaceGeometryMapping, spaceResPath); + } + + public void clearSpace(bool isall) + { + _entityIDAliasIDList.Clear(); + _spacedatas.Clear(); + clearEntities(isall); + isLoadedGeometry = false; + spaceID = 0; + } + + public void clearEntities(bool isall) + { + _controlledEntities.Clear(); + + if (!isall) + { + Entity entity = player(); + + foreach (KeyValuePair dic in entities) + { + if(dic.Key == entity.id) + continue; + + if(dic.Value.inWorld) + dic.Value.leaveWorld(); + + dic.Value.destroy(); + } + + entities.Clear(); + entities[entity.id] = entity; + } + else + { + foreach (KeyValuePair dic in entities) + { + if(dic.Value.inWorld) + dic.Value.leaveWorld(); + + dic.Value.destroy(); + } + + entities.Clear(); + } + } + + /* + 服务端初始化客户端的spacedata, spacedata请参考API + */ + public void Client_initSpaceData(MemoryStream stream) + { + clearSpace(false); + spaceID = stream.readUint32(); + + while(stream.length() > 0) + { + string key = stream.readString(); + string val = stream.readString(); + Client_setSpaceData(spaceID, key, val); + } + + Dbg.DEBUG_MSG("KBEngine::Client_initSpaceData: spaceID(" + spaceID + "), size(" + _spacedatas.Count + ")!"); + } + + /* + 服务端设置客户端的spacedata, spacedata请参考API + */ + public void Client_setSpaceData(UInt32 spaceID, string key, string value) + { + Dbg.DEBUG_MSG("KBEngine::Client_setSpaceData: spaceID(" + spaceID + "), key(" + key + "), value(" + value + ")!"); + _spacedatas[key] = value; + + if(key == "_mapping") + addSpaceGeometryMapping(spaceID, value); + + Event.fireOut(EventOutTypes.onSetSpaceData, spaceID, key, value); + } + + /* + 服务端删除客户端的spacedata, spacedata请参考API + */ + public void Client_delSpaceData(UInt32 spaceID, string key) + { + Dbg.DEBUG_MSG("KBEngine::Client_delSpaceData: spaceID(" + spaceID + "), key(" + key + ")"); + _spacedatas.Remove(key); + Event.fireOut(EventOutTypes.onDelSpaceData, spaceID, key); + } + + public string getSpaceData(string key) + { + string val = ""; + + if(!_spacedatas.TryGetValue(key, out val)) + { + return ""; + } + + return val; + } + + /* + 服务端通知强制销毁一个实体 + */ + public void Client_onEntityDestroyed(Int32 eid) + { + Dbg.DEBUG_MSG("KBEngine::Client_onEntityDestroyed: entity(" + eid + ")"); + + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onEntityDestroyed: entity(" + eid + ") not found!"); + return; + } + + if(entity.inWorld) + { + if(entity_id == eid) + clearSpace(false); + + entity.leaveWorld(); + } + + if(_controlledEntities.Remove(entity)) + Event.fireOut(EventOutTypes.onLoseControlledEntity, entity); + + entities.Remove(eid); + entity.destroy(); + } + + /* + 服务端更新玩家的基础位置, 客户端以这个基础位置加上便宜值计算出玩家周围实体的坐标 + */ + public void Client_onUpdateBasePos(float x, float y, float z) + { + _entityServerPos.x = x; + _entityServerPos.y = y; + _entityServerPos.z = z; + + var entity = player(); + if (entity != null && entity.isControlled) + { + entity.position.Set(_entityServerPos.x, _entityServerPos.y, _entityServerPos.z); + Event.fireOut(EventOutTypes.updatePosition, entity); + entity.onUpdateVolatileData(); + } + } + + public void Client_onUpdateBasePosXZ(float x, float z) + { + _entityServerPos.x = x; + _entityServerPos.z = z; + + var entity = player(); + if (entity != null && entity.isControlled) + { + entity.position.x = _entityServerPos.x; + entity.position.z = _entityServerPos.z; + Event.fireOut(EventOutTypes.updatePosition, entity); + entity.onUpdateVolatileData(); + } + } + + public void Client_onUpdateBaseDir(MemoryStream stream) + { + float yaw, pitch, roll; + yaw = stream.readFloat() * 360 / ((float)System.Math.PI * 2); + pitch = stream.readFloat() * 360 / ((float)System.Math.PI * 2); + roll = stream.readFloat() * 360 / ((float)System.Math.PI * 2); + + var entity = player(); + if (entity != null && entity.isControlled) + { + entity.direction.Set(roll, pitch, yaw); + Event.fireOut(EventOutTypes.set_direction, entity); + entity.onUpdateVolatileData(); + } + } + + public void Client_onUpdateData(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onUpdateData: entity(" + eid + ") not found!"); + return; + } + } + + /* + 服务端强制设置了玩家的坐标 + 例如:在服务端使用avatar.position=(0,0,0), 或者玩家位置与速度异常时会强制拉回到一个位置 + */ + public void Client_onSetEntityPosAndDir(MemoryStream stream) + { + Int32 eid = stream.readInt32(); + Entity entity = null; + + if(!entities.TryGetValue(eid, out entity)) + { + Dbg.ERROR_MSG("KBEngine::Client_onSetEntityPosAndDir: entity(" + eid + ") not found!"); + return; + } + + Vector3 old_position = new Vector3(entity.position.x, entity.position.y, entity.position.z); + Vector3 old_direction = new Vector3(entity.direction.x, entity.direction.y, entity.direction.z); + + entity.position.x = stream.readFloat(); + entity.position.y = stream.readFloat(); + entity.position.z = stream.readFloat(); + + entity.direction.x = stream.readFloat(); + entity.direction.y = stream.readFloat(); + entity.direction.z = stream.readFloat(); + + entity._entityLastLocalPos = entity.position; + entity._entityLastLocalDir = entity.direction; + + entity.onDirectionChanged(old_direction); + entity.onPositionChanged(old_position); + } + + public void Client_onUpdateData_ypr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float y = stream.readFloat(); + float p = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, p, r, -1, false); + } + + public void Client_onUpdateData_yp(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float y = stream.readFloat(); + float p = stream.readFloat(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, p, KBEMath.KBE_FLT_MAX, -1, false); + } + + public void Client_onUpdateData_yr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float y = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, KBEMath.KBE_FLT_MAX, r, -1, false); + } + + public void Client_onUpdateData_pr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float p = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, p, r, -1, false); + } + + public void Client_onUpdateData_y(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float y = stream.readFloat(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, -1, false); + } + + public void Client_onUpdateData_p(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float p = stream.readFloat(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, p, KBEMath.KBE_FLT_MAX, -1, false); + } + + public void Client_onUpdateData_r(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float r = stream.readFloat(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, r, -1, false); + } + + public void Client_onUpdateData_xz(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 1, false); + } + + public void Client_onUpdateData_xz_ypr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + float y = stream.readFloat(); + float p = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, y, p, r, 1, false); + } + + public void Client_onUpdateData_xz_yp(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + float y = stream.readFloat(); + float p = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, y, p, KBEMath.KBE_FLT_MAX, 1, false); + } + + public void Client_onUpdateData_xz_yr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + float y = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, y, KBEMath.KBE_FLT_MAX, r, 1, false); + } + + public void Client_onUpdateData_xz_pr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + float p = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, KBEMath.KBE_FLT_MAX, p, r, 1, false); + } + + public void Client_onUpdateData_xz_y(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + float yaw = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, yaw, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 1, false); + } + + public void Client_onUpdateData_xz_p(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + float p = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, KBEMath.KBE_FLT_MAX, p, KBEMath.KBE_FLT_MAX, 1, false); + } + + public void Client_onUpdateData_xz_r(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float z = stream.readFloat(); + + float r = stream.readFloat(); + + _updateVolatileData(eid, x, KBEMath.KBE_FLT_MAX, z, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, r, 1, false); + } + + public void Client_onUpdateData_xyz(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 0, false); + } + + public void Client_onUpdateData_xyz_ypr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + float yaw = stream.readFloat(); + float p = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, yaw, p, r, 0, false); + } + + public void Client_onUpdateData_xyz_yp(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + float yaw = stream.readFloat(); + float p = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, yaw, p, KBEMath.KBE_FLT_MAX, 0, false); + } + + public void Client_onUpdateData_xyz_yr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + float yaw = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, yaw, KBEMath.KBE_FLT_MAX, r, 0, false); + } + + public void Client_onUpdateData_xyz_pr(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + float p = stream.readFloat(); + float r = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, KBEMath.KBE_FLT_MAX, p, r, 0, false); + } + + public void Client_onUpdateData_xyz_y(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + float yaw = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, yaw, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 0, false); + } + + public void Client_onUpdateData_xyz_p(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + float p = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, KBEMath.KBE_FLT_MAX, p, KBEMath.KBE_FLT_MAX, 0, false); + } + + public void Client_onUpdateData_xyz_r(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + float x = stream.readFloat(); + float y = stream.readFloat(); + float z = stream.readFloat(); + + float r = stream.readFloat(); + + _updateVolatileData(eid, x, y, z, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, r, 0, false); + } + + public void Client_onUpdateData_ypr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + SByte y = stream.readInt8(); + SByte p = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, p, r, -1, true); + } + + public void Client_onUpdateData_yp_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + SByte y = stream.readInt8(); + SByte p = stream.readInt8(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, p, KBEMath.KBE_FLT_MAX, -1, true); + } + + public void Client_onUpdateData_yr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + SByte y = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, KBEMath.KBE_FLT_MAX, r, -1, true); + } + + public void Client_onUpdateData_pr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + SByte p = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, p, r, -1, true); + } + + public void Client_onUpdateData_y_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + SByte y = stream.readInt8(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, y, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, -1, true); + } + + public void Client_onUpdateData_p_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + SByte p = stream.readInt8(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, p, KBEMath.KBE_FLT_MAX, -1, true); + } + + public void Client_onUpdateData_r_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + SByte r = stream.readInt8(); + + _updateVolatileData(eid, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, r, -1, true); + } + + public void Client_onUpdateData_xz_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 1, true); + } + + public void Client_onUpdateData_xz_ypr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + + SByte y = stream.readInt8(); + SByte p = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], y, p, r, 1, true); + } + + public void Client_onUpdateData_xz_yp_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + + SByte y = stream.readInt8(); + SByte p = stream.readInt8(); + + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], y, p, KBEMath.KBE_FLT_MAX, 1, true); + } + + public void Client_onUpdateData_xz_yr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + + SByte y = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], y, KBEMath.KBE_FLT_MAX, r, 1, true); + } + + public void Client_onUpdateData_xz_pr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + + SByte p = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], KBEMath.KBE_FLT_MAX, p, r, 1, true); + } + + public void Client_onUpdateData_xz_y_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + Vector2 xz = stream.readPackXZ(); + SByte yaw = stream.readInt8(); + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], yaw, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 1, true); + } + + public void Client_onUpdateData_xz_p_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + + SByte p = stream.readInt8(); + + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], KBEMath.KBE_FLT_MAX, p, KBEMath.KBE_FLT_MAX, 1, true); + } + + public void Client_onUpdateData_xz_r_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], KBEMath.KBE_FLT_MAX, xz[1], KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, r, 1, true); + } + + public void Client_onUpdateData_xyz_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + _updateVolatileData(eid, xz[0], y, xz[1], KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 0, true); + } + + public void Client_onUpdateData_xyz_ypr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + SByte yaw = stream.readInt8(); + SByte p = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], y, xz[1], yaw, p, r, 0, true); + } + + public void Client_onUpdateData_xyz_yp_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + SByte yaw = stream.readInt8(); + SByte p = stream.readInt8(); + + _updateVolatileData(eid, xz[0], y, xz[1], yaw, p, KBEMath.KBE_FLT_MAX, 0, true); + } + + public void Client_onUpdateData_xyz_yr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + SByte yaw = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], y, xz[1], yaw, KBEMath.KBE_FLT_MAX, r, 0, true); + } + + public void Client_onUpdateData_xyz_pr_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + SByte p = stream.readInt8(); + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], y, xz[1], KBEMath.KBE_FLT_MAX, p, r, 0, true); + } + + public void Client_onUpdateData_xyz_y_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + SByte yaw = stream.readInt8(); + _updateVolatileData(eid, xz[0], y, xz[1], yaw, KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, 0, true); + } + + public void Client_onUpdateData_xyz_p_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + SByte p = stream.readInt8(); + + _updateVolatileData(eid, xz[0], y, xz[1], KBEMath.KBE_FLT_MAX, p, KBEMath.KBE_FLT_MAX, 0, true); + } + + public void Client_onUpdateData_xyz_r_optimized(MemoryStream stream) + { + Int32 eid = getViewEntityIDFromStream(stream); + + Vector2 xz = stream.readPackXZ(); + float y = stream.readPackY(); + + SByte r = stream.readInt8(); + + _updateVolatileData(eid, xz[0], y, xz[1], KBEMath.KBE_FLT_MAX, KBEMath.KBE_FLT_MAX, r, 0, true); + } + + private void _updateVolatileData(Int32 entityID, float x, float y, float z, float yaw, float pitch, float roll, sbyte isOnGround, bool isOptimized) + { + Entity entity = null; + + if(!entities.TryGetValue(entityID, out entity)) + { + // 如果为0且客户端上一步是重登陆或者重连操作并且服务端entity在断线期间一直处于在线状态 + // 则可以忽略这个错误, 因为cellapp可能一直在向baseapp发送同步消息, 当客户端重连上时未等 + // 服务端初始化步骤开始则收到同步信息, 此时这里就会出错。 + Dbg.ERROR_MSG("KBEngine::_updateVolatileData: entity(" + entityID + ") not found!"); + return; + } + + // 小于0不设置 + if(isOnGround >= 0) + { + entity.isOnGround = (isOnGround > 0); + } + + bool changeDirection = false; + + if(roll != KBEMath.KBE_FLT_MAX) + { + changeDirection = true; + entity.direction.x = (isOptimized ? KBEMath.int82angle((SByte)roll, false) : roll) * 360 / ((float)System.Math.PI * 2); + } + + if(pitch != KBEMath.KBE_FLT_MAX) + { + changeDirection = true; + entity.direction.y = (isOptimized ? KBEMath.int82angle((SByte)pitch, false) : pitch) * 360 / ((float)System.Math.PI * 2); + } + + if(yaw != KBEMath.KBE_FLT_MAX) + { + changeDirection = true; + entity.direction.z = (isOptimized ? KBEMath.int82angle((SByte)yaw, false) : yaw) * 360 / ((float)System.Math.PI * 2); + } + + bool done = false; + if(changeDirection == true) + { + Event.fireOut(EventOutTypes.set_direction, entity); + done = true; + } + + bool positionChanged = x != KBEMath.KBE_FLT_MAX || y != KBEMath.KBE_FLT_MAX || z != KBEMath.KBE_FLT_MAX; + if (x == KBEMath.KBE_FLT_MAX) x = isOptimized ? 0.0f : entity.position.x; + if (y == KBEMath.KBE_FLT_MAX) y = isOptimized ? 0.0f : entity.position.y; + if (z == KBEMath.KBE_FLT_MAX) z = isOptimized ? 0.0f : entity.position.z; + + if(positionChanged) + { + Vector3 pos = isOptimized ? new Vector3(x + _entityServerPos.x, y + _entityServerPos.y, z + _entityServerPos.z) : new Vector3(x, y, z); + + entity.position = pos; + done = true; + Event.fireOut(EventOutTypes.updatePosition, entity); + } + + if(done) + entity.onUpdateVolatileData(); + } + + /* + 服务端通知流数据下载开始 + 请参考API手册关于onStreamDataStarted + */ + public void Client_onStreamDataStarted(Int16 id, UInt32 datasize, string descr) + { + Event.fireOut(EventOutTypes.onStreamDataStarted, id, datasize, descr); + } + + public void Client_onStreamDataRecv(MemoryStream stream) + { + Int16 resID = stream.readInt16(); + byte[] datas = stream.readBlob(); + Event.fireOut(EventOutTypes.onStreamDataRecv, resID, datas); + } + + public void Client_onStreamDataCompleted(Int16 id) + { + Event.fireOut(EventOutTypes.onStreamDataCompleted, id); + } + } + + + public class KBEngineAppThread : KBEngineApp + { + /* + KBEngine处理线程 + */ + public class KBEThread + { + + KBEngineApp app_; + public bool over = false; + + public KBEThread(KBEngineApp app) + { + this.app_ = app; + } + + public void run() + { + Dbg.INFO_MSG("KBEThread::run()"); + over = false; + + try + { + this.app_.process(); + } + catch (Exception e) + { + Dbg.ERROR_MSG(e.ToString()); + } + + over = true; + Dbg.INFO_MSG("KBEThread::end()"); + } + } + + private Thread _t = null; + public KBEThread kbethread = null; + + // 主循环频率 + public static int threadUpdateHZ = 10; + + // 主循环周期ms 优化去掉循环中做除法 + private static float threadUpdatePeriod = 1000f / threadUpdateHZ; + + // 插件是否退出 + private bool _isbreak = false; + + private System.DateTime _lasttime = System.DateTime.Now; + + public KBEngineAppThread(KBEngineArgs args) : + base(args) + { + } + + public override bool initialize(KBEngineArgs args) + { + base.initialize(args); + + KBEngineAppThread.threadUpdateHZ = args.threadUpdateHZ; + threadUpdatePeriod = 1000f / threadUpdateHZ; + + kbethread = new KBEThread(this); + _t = new Thread(new ThreadStart(kbethread.run)); + _t.Start(); + + return true; + } + + public override void reset() + { + _isbreak = false; + _lasttime = System.DateTime.Now; + + base.reset(); + } + + /* + 插件退出处理 + */ + public void breakProcess() + { + _isbreak = true; + } + + public bool isbreak() + { + return _isbreak; + } + + public override void process() + { + while(!isbreak()) + { + base.process(); + _thread_wait(); + } + + Dbg.WARNING_MSG("KBEngineAppThread::process(): break!"); + } + + /* + 防止占满CPU, 需要让线程等待一会 + */ + void _thread_wait() + { + TimeSpan span = DateTime.Now - _lasttime; + + int diff = (int)(threadUpdatePeriod - span.TotalMilliseconds); + + if(diff < 0) + diff = 0; + + System.Threading.Thread.Sleep(diff); + _lasttime = DateTime.Now; + } + + public override void destroy() + { + Dbg.WARNING_MSG("KBEngineAppThread::destroy()"); + breakProcess(); + + int i = 0; + while(!kbethread.over && i < 50) + { + Thread.Sleep(100); + i += 1; + } + + if(_t != null) + _t.Abort(); + + _t = null; + + base.destroy(); + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngine.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngine.cs.meta new file mode 100644 index 00000000..065a4b6a --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngine.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 408d2189a5f3723438f7e9bb9bda0b6b +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngineArgs.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngineArgs.cs new file mode 100644 index 00000000..f1e31fd1 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngineArgs.cs @@ -0,0 +1,77 @@ +namespace KBEngine +{ + using System; + + using MessageLengthEx = System.UInt32; + + /* + 初始化KBEngine的参数类 + */ + public class KBEngineArgs + { + // 登录ip和端口 + public string ip = "127.0.0.1"; + public int port = 20013; + + // 客户端类型 + // Reference: http://www.kbengine.org/docs/programming/clientsdkprogramming.html, client types + public KBEngineApp.CLIENT_TYPE clientType = KBEngineApp.CLIENT_TYPE.CLIENT_TYPE_MINI; + + //加密通信类型 + public KBEngineApp.NETWORK_ENCRYPT_TYPE networkEncryptType = KBEngineApp.NETWORK_ENCRYPT_TYPE.ENCRYPT_TYPE_NONE; + + // Allow synchronization role position information to the server + // 是否开启自动同步玩家信息到服务端,信息包括位置与方向,毫秒 + // 非高实时类游戏不需要开放这个选项 + public int syncPlayerMS = 100; + + // 是否使用别名机制 + // 这个参数的选择必须与kbengine_defs.xml::cellapp/aliasEntityID的参数保持一致 + public bool useAliasEntityID = true; + + // 在Entity初始化时是否触发属性的set_*事件(callPropertysSetMethods) + public bool isOnInitCallPropertysSetMethods = true; + + // 发送缓冲大小 + public MessageLengthEx TCP_SEND_BUFFER_MAX = NetworkInterfaceBase.TCP_PACKET_MAX; + public MessageLengthEx UDP_SEND_BUFFER_MAX = 128; + + // 接收缓冲区大小 + public MessageLengthEx TCP_RECV_BUFFER_MAX = NetworkInterfaceBase.TCP_PACKET_MAX; + public MessageLengthEx UDP_RECV_BUFFER_MAX = 128; + + // 是否多线程启动 + public bool isMultiThreads = false; + + // 只在多线程模式启用 + // 线程主循环处理频率 + public int threadUpdateHZ = 10; + + // 强制禁用UDP通讯 + public bool forceDisableUDP = false; + + // 心跳频率(tick数) + public int serverHeartbeatTick = 15; + + public int getTCPRecvBufferSize() + { + return (int)TCP_RECV_BUFFER_MAX; + } + + public int getTCPSendBufferSize() + { + return (int)TCP_SEND_BUFFER_MAX; + } + + public int getUDPRecvBufferSize() + { + return (int)UDP_RECV_BUFFER_MAX; + } + + public int getUDPSendBufferSize() + { + return (int)UDP_SEND_BUFFER_MAX; + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngineArgs.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngineArgs.cs.meta new file mode 100644 index 00000000..fa59e68f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/KBEngineArgs.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a3b08dd03df3322478018d976df639e2 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Math.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Math.cs new file mode 100644 index 00000000..169fdd28 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Math.cs @@ -0,0 +1,45 @@ +using UnityEngine; +using KBEngine; +using System; +using System.Collections; + +namespace KBEngine +{ + +/* + KBEngine的数学相关模块 +*/ +public class KBEMath +{ + public static float KBE_FLT_MAX = float.MaxValue; + + public static float int82angle(SByte angle, bool half) + { + float halfv = 128f; + if(half == true) + halfv = 254f; + + halfv = ((float)angle) * ((float)System.Math.PI / halfv); + return halfv; + } + + public static bool almostEqual(float f1, float f2, float epsilon) + { + return Math.Abs( f1 - f2 ) < epsilon; + } + + public static bool isNumeric(object v) + { + return v is sbyte || v is byte || + v is short || v is ushort || + v is int || v is uint || + v is long || v is ulong || + v is char || v is decimal || v is float || + v is double || v is Int16 || v is Int64 || + v is UInt16 || v is UInt64 || + v is Boolean || v is bool; + } +} + + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Math.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Math.cs.meta new file mode 100644 index 00000000..3fb61da3 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Math.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8a0c0f6a7aa107d4286c6ab2261d0367 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MemoryStream.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MemoryStream.cs new file mode 100644 index 00000000..8c64b4bc --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MemoryStream.cs @@ -0,0 +1,472 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Threading; + using System.Runtime.InteropServices; + + /* + 二进制数据流模块 + 能够将一些基本类型序列化(writeXXX)成二进制流同时也提供了反序列化(readXXX)等操作 + */ + public class MemoryStream : ObjectPool + { + public const int BUFFER_MAX = 1460 * 4; + + public int rpos = 0; + public int wpos = 0; + private byte[] datas_ = new byte[BUFFER_MAX]; + + private static System.Text.ASCIIEncoding _converter = new System.Text.ASCIIEncoding(); + + [StructLayout(LayoutKind.Explicit, Size = 4)] + struct PackFloatXType + { + [FieldOffset(0)] + public float fv; + + [FieldOffset(0)] + public UInt32 uv; + + [FieldOffset(0)] + public Int32 iv; + } + + + public byte[] setBuffer(byte[] buffer) + { + byte[] outBuf = datas_; + datas_ = buffer; + return outBuf; + } + + public void swap(MemoryStream stream) + { + int t_rpos = rpos; + int t_wpos = wpos; + rpos = stream.rpos; + wpos = stream.wpos; + stream.rpos = t_rpos; + stream.wpos = t_wpos; + + datas_ = stream.setBuffer(datas_); + } + + /// + /// 把自己放回缓冲池 + /// + public void reclaimObject() + { + clear(); + reclaimObject(this); + } + + public byte[] data() + { + return datas_; + } + + public void setData(byte[] data) + { + datas_ = data; + } + + //--------------------------------------------------------------------------------- + public SByte readInt8() + { + return (SByte)datas_[rpos++]; + } + + public Int16 readInt16() + { + rpos += 2; + return BitConverter.ToInt16(datas_, rpos - 2); + } + + public Int32 readInt32() + { + rpos += 4; + return BitConverter.ToInt32(datas_, rpos - 4); + } + + public Int64 readInt64() + { + rpos += 8; + return BitConverter.ToInt64(datas_, rpos - 8); + } + + public Byte readUint8() + { + return datas_[rpos++]; + } + + public UInt16 readUint16() + { + rpos += 2; + return BitConverter.ToUInt16(datas_, rpos - 2); + } + + public UInt32 readUint32() + { + rpos += 4; + return BitConverter.ToUInt32(datas_, rpos - 4); + } + + public UInt64 readUint64() + { + rpos += 8; + return BitConverter.ToUInt64(datas_, rpos - 8); + } + + public float readFloat() + { + rpos += 4; + return BitConverter.ToSingle(datas_, rpos - 4); + } + + public double readDouble() + { + rpos += 8; + return BitConverter.ToDouble(datas_, rpos - 8); + } + + public string readString() + { + int offset = rpos; + while(datas_[rpos++] != 0) + { + } + + return _converter.GetString(datas_, offset, rpos - offset - 1); + } + + public string readUnicode() + { + return System.Text.Encoding.UTF8.GetString(readBlob()); + } + + public byte[] readBlob() + { + UInt32 size = readUint32(); + byte[] buf = new byte[size]; + + Array.Copy(datas_, rpos, buf, 0, size); + rpos += (int)size; + return buf; + } + + public byte[] readEntitycall() + { + readUint64(); + readInt32(); + readUint16(); + readUint16(); + return new byte[0]; + } + + public Vector2 readVector2() + { + float x = readFloat(); + float y = readFloat(); + return new Vector2(x, y); + } + + public Vector3 readVector3() + { + float x = readFloat(); + float y = readFloat(); + float z = readFloat(); + return new Vector3(x, y, z); + } + + public Vector4 readVector4() + { + float x = readFloat(); + float y = readFloat(); + float z = readFloat(); + float w = readFloat(); + return new Vector4(x, y, z, w); + } + + public byte[] readPython() + { + return readBlob(); + } + + public Vector2 readPackXZ() + { + PackFloatXType xPackData; + PackFloatXType zPackData; + + xPackData.fv = 0f; + zPackData.fv = 0f; + + xPackData.uv = 0x40000000; + zPackData.uv = 0x40000000; + + Byte v1 = readUint8(); + Byte v2 = readUint8(); + Byte v3 = readUint8(); + + UInt32 data = 0; + data |= ((UInt32)v1 << 16); + data |= ((UInt32)v2 << 8); + data |= (UInt32)v3; + + xPackData.uv |= (data & 0x7ff000) << 3; + zPackData.uv |= (data & 0x0007ff) << 15; + + xPackData.fv -= 2.0f; + zPackData.fv -= 2.0f; + + xPackData.uv |= (data & 0x800000) << 8; + zPackData.uv |= (data & 0x000800) << 20; + + Vector2 vec = new Vector2(xPackData.fv, zPackData.fv); + return vec; + } + + public float readPackY() + { + PackFloatXType yPackData; + yPackData.fv = 0f; + yPackData.uv = 0x40000000; + + UInt16 data = readUint16(); + + yPackData.uv |= ((UInt32)data & 0x7fff) << 12; + yPackData.fv -= 2f; + yPackData.uv |= ((UInt32)data & 0x8000) << 16; + + return yPackData.fv; + } + + //--------------------------------------------------------------------------------- + public void writeInt8(SByte v) + { + datas_[wpos++] = (Byte)v; + } + + public void writeInt16(Int16 v) + { + writeInt8((SByte)(v & 0xff)); + writeInt8((SByte)(v >> 8 & 0xff)); + } + + public void writeInt32(Int32 v) + { + for(int i=0; i<4; i++) + writeInt8((SByte)(v >> i * 8 & 0xff)); + } + + public void writeInt64(Int64 v) + { + byte[] getdata = BitConverter.GetBytes(v); + for(int i=0; i> 8 & 0xff)); + } + + public void writeUint32(UInt32 v) + { + for(int i=0; i<4; i++) + writeUint8((Byte)(v >> i * 8 & 0xff)); + } + + public void writeUint64(UInt64 v) + { + byte[] getdata = BitConverter.GetBytes(v); + for(int i=0; i space()) + { + Dbg.ERROR_MSG("memorystream::writeBlob: no free!"); + return; + } + + writeUint32(size); + + for(UInt32 i=0; i space()) + { + Dbg.ERROR_MSG("memorystream::writeString: no free!"); + return; + } + + byte[] getdata = System.Text.Encoding.ASCII.GetBytes(v); + for(int i=0; i BUFFER_MAX) + datas_ = new byte[BUFFER_MAX]; + } + + //--------------------------------------------------------------------------------- + public byte[] getbuffer() + { + byte[] buf = new byte[length()]; + Array.Copy(data(), rpos, buf, 0, length()); + return buf; + } + + //--------------------------------------------------------------------------------- + public string toString() + { + string s = ""; + int ii = 0; + byte[] buf = getbuffer(); + + for(int i=0; i= 200) + { + s = ""; + ii = 0; + } + + s += buf[i]; + s += " "; + } + + return s; + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MemoryStream.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MemoryStream.cs.meta new file mode 100644 index 00000000..5ade691f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MemoryStream.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 88ca295c95e2ae34cbdf9875b80a9697 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderBase.cs new file mode 100644 index 00000000..b40488d9 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderBase.cs @@ -0,0 +1,18 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + using MessageLengthEx = System.UInt32; + + /* + 消息阅读模块 + 从数据包流中分析出所有的消息包并将其交给对应的消息处理函数 + */ + public abstract class MessageReaderBase + { + public abstract void process(byte[] datas, MessageLengthEx offset, MessageLengthEx length); + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderBase.cs.meta new file mode 100644 index 00000000..db5bbda7 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a4e0d601a8214744d9ae2797665f8843 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderKCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderKCP.cs new file mode 100644 index 00000000..5f76598d --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderKCP.cs @@ -0,0 +1,18 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + using MessageLengthEx = System.UInt32; + + /* + 消息阅读模块 + 从数据包流中分析出所有的消息包并将其交给对应的消息处理函数 + 由于KCP是模拟的TCP流,一个UDP包中可能包含一个或者多个包,并且最后一个包可能是不完整的,因此直接继承MessageReaderTCP + */ + public class MessageReaderKCP : MessageReaderTCP + { + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderKCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderKCP.cs.meta new file mode 100644 index 00000000..057a187f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderKCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: ce4cc52cacccf584abc6697985d41542 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderTCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderTCP.cs new file mode 100644 index 00000000..56327269 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderTCP.cs @@ -0,0 +1,185 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + using MessageLengthEx = System.UInt32; + + /* + 消息阅读模块 + 从数据包流中分析出所有的消息包并将其交给对应的消息处理函数 + */ + public class MessageReaderTCP : MessageReaderBase + { + enum READ_STATE + { + // 消息ID + READ_STATE_MSGID = 0, + + // 消息的长度65535以内 + READ_STATE_MSGLEN = 1, + + // 当上面的消息长度都无法到达要求时使用扩展长度 + // uint32 + READ_STATE_MSGLEN_EX = 2, + + // 消息的内容 + READ_STATE_BODY = 3 + } + + private MessageID msgid = 0; + private MessageLength msglen = 0; + private MessageLengthEx expectSize = 2; + private READ_STATE state = READ_STATE.READ_STATE_MSGID; + private MemoryStream stream = new MemoryStream(); + + public MessageReaderTCP() + { + } + + public override void process(byte[] datas, MessageLengthEx offset, MessageLengthEx length) + { + MessageLengthEx totallen = offset; + + while(length > 0 && expectSize > 0) + { + if(state == READ_STATE.READ_STATE_MSGID) + { + if(length >= expectSize) + { + Array.Copy(datas, totallen, stream.data(), stream.wpos, expectSize); + totallen += expectSize; + stream.wpos += (int)expectSize; + length -= expectSize; + msgid = stream.readUint16(); + stream.clear(); + + Message msg = Messages.clientMessages[msgid]; + + if(msg.msglen == -1) + { + state = READ_STATE.READ_STATE_MSGLEN; + expectSize = 2; + } + else if(msg.msglen == 0) + { + // 如果是0个参数的消息,那么没有后续内容可读了,处理本条消息并且直接跳到下一条消息 + #if UNITY_EDITOR + Dbg.profileStart(msg.name); + #endif + + msg.handleMessage(stream); + + #if UNITY_EDITOR + Dbg.profileEnd(msg.name); + #endif + + state = READ_STATE.READ_STATE_MSGID; + expectSize = 2; + } + else + { + expectSize = (MessageLengthEx)msg.msglen; + state = READ_STATE.READ_STATE_BODY; + } + } + else + { + Array.Copy(datas, totallen, stream.data(), stream.wpos, length); + stream.wpos += (int)length; + expectSize -= length; + break; + } + } + else if(state == READ_STATE.READ_STATE_MSGLEN) + { + if(length >= expectSize) + { + Array.Copy(datas, totallen, stream.data(), stream.wpos, expectSize); + totallen += expectSize; + stream.wpos += (int)expectSize; + length -= expectSize; + + msglen = stream.readUint16(); + stream.clear(); + + // 长度扩展 + if(msglen >= 65535) + { + state = READ_STATE.READ_STATE_MSGLEN_EX; + expectSize = 4; + } + else + { + state = READ_STATE.READ_STATE_BODY; + expectSize = msglen; + } + } + else + { + Array.Copy(datas, totallen, stream.data(), stream.wpos, length); + stream.wpos += (int)length; + expectSize -= length; + break; + } + } + else if(state == READ_STATE.READ_STATE_MSGLEN_EX) + { + if(length >= expectSize) + { + Array.Copy(datas, totallen, stream.data(), stream.wpos, expectSize); + totallen += expectSize; + stream.wpos += (int)expectSize; + length -= expectSize; + + expectSize = stream.readUint32(); + stream.clear(); + + state = READ_STATE.READ_STATE_BODY; + } + else + { + Array.Copy(datas, totallen, stream.data(), stream.wpos, length); + stream.wpos += (int)length; + expectSize -= length; + break; + } + } + else if(state == READ_STATE.READ_STATE_BODY) + { + if(length >= expectSize) + { + stream.append (datas, totallen, expectSize); + totallen += expectSize; + length -= expectSize; + + Message msg = Messages.clientMessages[msgid]; + +#if UNITY_EDITOR + Dbg.profileStart(msg.name); +#endif + + msg.handleMessage(stream); + +#if UNITY_EDITOR + Dbg.profileEnd(msg.name); +#endif + + stream.clear(); + + state = READ_STATE.READ_STATE_MSGID; + expectSize = 2; + } + else + { + stream.append (datas, totallen, length); + expectSize -= length; + break; + } + } + } + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderTCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderTCP.cs.meta new file mode 100644 index 00000000..9507e7c3 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MessageReaderTCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 5850c20a68853be4796b04c56aa42165 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Messages.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Messages.cs new file mode 100644 index 00000000..03ec3d53 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Messages.cs @@ -0,0 +1,2141 @@ +/* + Generated by KBEngine! + Please do not modify this file! + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + using MessageID = System.UInt16; + + // engine-c++ messages + + public class Message + { + public MessageID id = 0; + public string name; + public Int16 msglen = -1; + public List argtypes = null; + public sbyte argsType = 0; + + public Message(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes) + { + id = msgid; + name = msgname; + msglen = length; + argsType = argstype; + + argtypes = msgargtypes; + // Dbg.DEBUG_MSG(string.Format("Message::Message() : ({ 0 } / {1} / {2})!", + // msgname, msgid, msglen)); + } + + public virtual void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Client_onReloginBaseappFailed : Message + { + + public Message_Client_onReloginBaseappFailed(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt16 arg1 = msgstream.readUint16(); + KBEngineApp.app.Client_onReloginBaseappFailed(arg1); + } + } + + public class Message_Client_onEntityLeaveWorldOptimized : Message + { + + public Message_Client_onEntityLeaveWorldOptimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onEntityLeaveWorldOptimized(msgstream); + } + } + + public class Message_Client_onRemoteMethodCallOptimized : Message + { + + public Message_Client_onRemoteMethodCallOptimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onRemoteMethodCallOptimized(msgstream); + } + } + + public class Message_Client_onUpdatePropertysOptimized : Message + { + + public Message_Client_onUpdatePropertysOptimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdatePropertysOptimized(msgstream); + } + } + + public class Message_Client_onSetEntityPosAndDir : Message + { + + public Message_Client_onSetEntityPosAndDir(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onSetEntityPosAndDir(msgstream); + } + } + + public class Message_Client_onUpdateBasePos : Message + { + + public Message_Client_onUpdateBasePos(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + float arg1 = msgstream.readFloat(); + float arg2 = msgstream.readFloat(); + float arg3 = msgstream.readFloat(); + KBEngineApp.app.Client_onUpdateBasePos(arg1, arg2, arg3); + } + } + + public class Message_Client_onUpdateBaseDir : Message + { + + public Message_Client_onUpdateBaseDir(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateBaseDir(msgstream); + } + } + + public class Message_Client_onUpdateBasePosXZ : Message + { + + public Message_Client_onUpdateBasePosXZ(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + float arg1 = msgstream.readFloat(); + float arg2 = msgstream.readFloat(); + KBEngineApp.app.Client_onUpdateBasePosXZ(arg1, arg2); + } + } + + public class Message_Client_onUpdateData : Message + { + + public Message_Client_onUpdateData(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData(msgstream); + } + } + + public class Message_Client_onUpdateData_ypr : Message + { + + public Message_Client_onUpdateData_ypr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_ypr(msgstream); + } + } + + public class Message_Client_onUpdateData_yp : Message + { + + public Message_Client_onUpdateData_yp(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_yp(msgstream); + } + } + + public class Message_Client_onUpdateData_yr : Message + { + + public Message_Client_onUpdateData_yr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_yr(msgstream); + } + } + + public class Message_Client_onUpdateData_pr : Message + { + + public Message_Client_onUpdateData_pr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_pr(msgstream); + } + } + + public class Message_Client_onUpdateData_y : Message + { + + public Message_Client_onUpdateData_y(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_y(msgstream); + } + } + + public class Message_Client_onUpdateData_p : Message + { + + public Message_Client_onUpdateData_p(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_p(msgstream); + } + } + + public class Message_Client_onUpdateData_r : Message + { + + public Message_Client_onUpdateData_r(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_r(msgstream); + } + } + + public class Message_Client_onUpdateData_xz : Message + { + + public Message_Client_onUpdateData_xz(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_ypr : Message + { + + public Message_Client_onUpdateData_xz_ypr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_ypr(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_yp : Message + { + + public Message_Client_onUpdateData_xz_yp(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_yp(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_yr : Message + { + + public Message_Client_onUpdateData_xz_yr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_yr(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_pr : Message + { + + public Message_Client_onUpdateData_xz_pr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_pr(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_y : Message + { + + public Message_Client_onUpdateData_xz_y(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_y(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_p : Message + { + + public Message_Client_onUpdateData_xz_p(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_p(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_r : Message + { + + public Message_Client_onUpdateData_xz_r(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_r(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz : Message + { + + public Message_Client_onUpdateData_xyz(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_ypr : Message + { + + public Message_Client_onUpdateData_xyz_ypr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_ypr(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_yp : Message + { + + public Message_Client_onUpdateData_xyz_yp(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_yp(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_yr : Message + { + + public Message_Client_onUpdateData_xyz_yr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_yr(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_pr : Message + { + + public Message_Client_onUpdateData_xyz_pr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_pr(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_y : Message + { + + public Message_Client_onUpdateData_xyz_y(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_y(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_p : Message + { + + public Message_Client_onUpdateData_xyz_p(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_p(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_r : Message + { + + public Message_Client_onUpdateData_xyz_r(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_r(msgstream); + } + } + + public class Message_Client_onUpdateData_ypr_optimized : Message + { + + public Message_Client_onUpdateData_ypr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_ypr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_yp_optimized : Message + { + + public Message_Client_onUpdateData_yp_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_yp_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_yr_optimized : Message + { + + public Message_Client_onUpdateData_yr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_yr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_pr_optimized : Message + { + + public Message_Client_onUpdateData_pr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_pr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_y_optimized : Message + { + + public Message_Client_onUpdateData_y_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_y_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_p_optimized : Message + { + + public Message_Client_onUpdateData_p_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_p_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_r_optimized : Message + { + + public Message_Client_onUpdateData_r_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_r_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_optimized : Message + { + + public Message_Client_onUpdateData_xz_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_ypr_optimized : Message + { + + public Message_Client_onUpdateData_xz_ypr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_ypr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_yp_optimized : Message + { + + public Message_Client_onUpdateData_xz_yp_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_yp_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_yr_optimized : Message + { + + public Message_Client_onUpdateData_xz_yr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_yr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_pr_optimized : Message + { + + public Message_Client_onUpdateData_xz_pr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_pr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_y_optimized : Message + { + + public Message_Client_onUpdateData_xz_y_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_y_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_p_optimized : Message + { + + public Message_Client_onUpdateData_xz_p_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_p_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xz_r_optimized : Message + { + + public Message_Client_onUpdateData_xz_r_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xz_r_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_optimized : Message + { + + public Message_Client_onUpdateData_xyz_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_ypr_optimized : Message + { + + public Message_Client_onUpdateData_xyz_ypr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_ypr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_yp_optimized : Message + { + + public Message_Client_onUpdateData_xyz_yp_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_yp_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_yr_optimized : Message + { + + public Message_Client_onUpdateData_xyz_yr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_yr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_pr_optimized : Message + { + + public Message_Client_onUpdateData_xyz_pr_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_pr_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_y_optimized : Message + { + + public Message_Client_onUpdateData_xyz_y_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_y_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_p_optimized : Message + { + + public Message_Client_onUpdateData_xyz_p_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_p_optimized(msgstream); + } + } + + public class Message_Client_onUpdateData_xyz_r_optimized : Message + { + + public Message_Client_onUpdateData_xyz_r_optimized(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdateData_xyz_r_optimized(msgstream); + } + } + + public class Message_Client_onImportServerErrorsDescr : Message + { + + public Message_Client_onImportServerErrorsDescr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onImportServerErrorsDescr(msgstream); + } + } + + public class Message_Client_onImportClientSDK : Message + { + + public Message_Client_onImportClientSDK(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onImportClientSDK(msgstream); + } + } + + public class Message_Client_initSpaceData : Message + { + + public Message_Client_initSpaceData(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_initSpaceData(msgstream); + } + } + + public class Message_Client_setSpaceData : Message + { + + public Message_Client_setSpaceData(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt32 arg1 = msgstream.readUint32(); + string arg2 = msgstream.readString(); + string arg3 = msgstream.readString(); + KBEngineApp.app.Client_setSpaceData(arg1, arg2, arg3); + } + } + + public class Message_Client_delSpaceData : Message + { + + public Message_Client_delSpaceData(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt32 arg1 = msgstream.readUint32(); + string arg2 = msgstream.readString(); + KBEngineApp.app.Client_delSpaceData(arg1, arg2); + } + } + + public class Message_Client_onReqAccountResetPasswordCB : Message + { + + public Message_Client_onReqAccountResetPasswordCB(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt16 arg1 = msgstream.readUint16(); + KBEngineApp.app.Client_onReqAccountResetPasswordCB(arg1); + } + } + + public class Message_Client_onReqAccountBindEmailCB : Message + { + + public Message_Client_onReqAccountBindEmailCB(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt16 arg1 = msgstream.readUint16(); + KBEngineApp.app.Client_onReqAccountBindEmailCB(arg1); + } + } + + public class Message_Client_onReqAccountNewPasswordCB : Message + { + + public Message_Client_onReqAccountNewPasswordCB(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt16 arg1 = msgstream.readUint16(); + KBEngineApp.app.Client_onReqAccountNewPasswordCB(arg1); + } + } + + public class Message_Client_onReloginBaseappSuccessfully : Message + { + + public Message_Client_onReloginBaseappSuccessfully(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onReloginBaseappSuccessfully(msgstream); + } + } + + public class Message_Client_onAppActiveTickCB : Message + { + + public Message_Client_onAppActiveTickCB(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onAppActiveTickCB(); + } + } + + public class Message_Client_onCreateAccountResult : Message + { + + public Message_Client_onCreateAccountResult(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onCreateAccountResult(msgstream); + } + } + + public class Message_Client_onLoginSuccessfully : Message + { + + public Message_Client_onLoginSuccessfully(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onLoginSuccessfully(msgstream); + } + } + + public class Message_Client_onLoginFailed : Message + { + + public Message_Client_onLoginFailed(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onLoginFailed(msgstream); + } + } + + public class Message_Client_onCreatedProxies : Message + { + + public Message_Client_onCreatedProxies(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt64 arg1 = msgstream.readUint64(); + Int32 arg2 = msgstream.readInt32(); + string arg3 = msgstream.readString(); + KBEngineApp.app.Client_onCreatedProxies(arg1, arg2, arg3); + } + } + + public class Message_Client_onLoginBaseappFailed : Message + { + + public Message_Client_onLoginBaseappFailed(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt16 arg1 = msgstream.readUint16(); + KBEngineApp.app.Client_onLoginBaseappFailed(arg1); + } + } + + public class Message_Client_onRemoteMethodCall : Message + { + + public Message_Client_onRemoteMethodCall(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onRemoteMethodCall(msgstream); + } + } + + public class Message_Client_onEntityEnterWorld : Message + { + + public Message_Client_onEntityEnterWorld(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onEntityEnterWorld(msgstream); + } + } + + public class Message_Client_onEntityLeaveWorld : Message + { + + public Message_Client_onEntityLeaveWorld(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + Int32 arg1 = msgstream.readInt32(); + KBEngineApp.app.Client_onEntityLeaveWorld(arg1); + } + } + + public class Message_Client_onEntityEnterSpace : Message + { + + public Message_Client_onEntityEnterSpace(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onEntityEnterSpace(msgstream); + } + } + + public class Message_Client_onEntityLeaveSpace : Message + { + + public Message_Client_onEntityLeaveSpace(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + Int32 arg1 = msgstream.readInt32(); + KBEngineApp.app.Client_onEntityLeaveSpace(arg1); + } + } + + public class Message_Client_onUpdatePropertys : Message + { + + public Message_Client_onUpdatePropertys(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onUpdatePropertys(msgstream); + } + } + + public class Message_Client_onEntityDestroyed : Message + { + + public Message_Client_onEntityDestroyed(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + Int32 arg1 = msgstream.readInt32(); + KBEngineApp.app.Client_onEntityDestroyed(arg1); + } + } + + public class Message_Client_onStreamDataStarted : Message + { + + public Message_Client_onStreamDataStarted(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + Int16 arg1 = msgstream.readInt16(); + UInt32 arg2 = msgstream.readUint32(); + string arg3 = msgstream.readString(); + KBEngineApp.app.Client_onStreamDataStarted(arg1, arg2, arg3); + } + } + + public class Message_Client_onStreamDataRecv : Message + { + + public Message_Client_onStreamDataRecv(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onStreamDataRecv(msgstream); + } + } + + public class Message_Client_onStreamDataCompleted : Message + { + + public Message_Client_onStreamDataCompleted(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + Int16 arg1 = msgstream.readInt16(); + KBEngineApp.app.Client_onStreamDataCompleted(arg1); + } + } + + public class Message_Client_onKicked : Message + { + + public Message_Client_onKicked(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + UInt16 arg1 = msgstream.readUint16(); + KBEngineApp.app.Client_onKicked(arg1); + } + } + + public class Message_Client_onImportClientMessages : Message + { + + public Message_Client_onImportClientMessages(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onImportClientMessages(msgstream); + } + } + + public class Message_Client_onImportClientEntityDef : Message + { + + public Message_Client_onImportClientEntityDef(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onImportClientEntityDef(msgstream); + } + } + + public class Message_Client_onHelloCB : Message + { + + public Message_Client_onHelloCB(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onHelloCB(msgstream); + } + } + + public class Message_Client_onScriptVersionNotMatch : Message + { + + public Message_Client_onScriptVersionNotMatch(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onScriptVersionNotMatch(msgstream); + } + } + + public class Message_Client_onVersionNotMatch : Message + { + + public Message_Client_onVersionNotMatch(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + KBEngineApp.app.Client_onVersionNotMatch(msgstream); + } + } + + public class Message_Client_onControlEntity : Message + { + + public Message_Client_onControlEntity(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + Int32 arg1 = msgstream.readInt32(); + SByte arg2 = msgstream.readInt8(); + KBEngineApp.app.Client_onControlEntity(arg1, arg2); + } + } + + public class Message_Loginapp_reqCreateAccount : Message + { + + public Message_Loginapp_reqCreateAccount(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_login : Message + { + + public Message_Loginapp_login(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_hello : Message + { + + public Message_Loginapp_hello(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_importClientMessages : Message + { + + public Message_Loginapp_importClientMessages(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_reqCreateMailAccount : Message + { + + public Message_Loginapp_reqCreateMailAccount(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_importClientSDK : Message + { + + public Message_Loginapp_importClientSDK(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_importServerErrorsDescr : Message + { + + public Message_Loginapp_importServerErrorsDescr(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_onClientActiveTick : Message + { + + public Message_Loginapp_onClientActiveTick(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Loginapp_reqAccountResetPassword : Message + { + + public Message_Loginapp_reqAccountResetPassword(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_logoutBaseapp : Message + { + + public Message_Baseapp_logoutBaseapp(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_onUpdateDataFromClient : Message + { + + public Message_Baseapp_onUpdateDataFromClient(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_onUpdateDataFromClientForControlledEntity : Message + { + + public Message_Baseapp_onUpdateDataFromClientForControlledEntity(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_reqAccountBindEmail : Message + { + + public Message_Baseapp_reqAccountBindEmail(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_reqAccountNewPassword : Message + { + + public Message_Baseapp_reqAccountNewPassword(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Entity_forwardEntityMessageToCellappFromClient : Message + { + + public Message_Entity_forwardEntityMessageToCellappFromClient(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_hello : Message + { + + public Message_Baseapp_hello(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_loginBaseapp : Message + { + + public Message_Baseapp_loginBaseapp(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_reloginBaseapp : Message + { + + public Message_Baseapp_reloginBaseapp(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_onRemoteCallCellMethodFromClient : Message + { + + public Message_Baseapp_onRemoteCallCellMethodFromClient(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_onClientActiveTick : Message + { + + public Message_Baseapp_onClientActiveTick(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_importClientMessages : Message + { + + public Message_Baseapp_importClientMessages(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Baseapp_importClientEntityDef : Message + { + + public Message_Baseapp_importClientEntityDef(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Message_Entity_onRemoteMethodCall : Message + { + + public Message_Entity_onRemoteMethodCall(MessageID msgid, string msgname, Int16 length, sbyte argstype, List msgargtypes): + base(msgid, msgname, length, argstype, msgargtypes) + { + + } + + public override void handleMessage(MemoryStream msgstream) + { + } + } + + public class Messages + { + public static Dictionary loginappMessages = new Dictionary(); + public static Dictionary baseappMessages = new Dictionary(); + public static Dictionary clientMessages = new Dictionary(); + public static Dictionary messages = new Dictionary(); + + public static void clear() + { + loginappMessages = new Dictionary(); + baseappMessages = new Dictionary(); + clientMessages = new Dictionary(); + messages = new Dictionary(); + + init(); + } + + + public static bool init() + { + + List Client_onReloginBaseappFailed_argstypes = new List(); + Client_onReloginBaseappFailed_argstypes.Add(3); + Messages.messages["Client_onReloginBaseappFailed"] = new Message_Client_onReloginBaseappFailed(8, "Client_onReloginBaseappFailed", 2, 0, Client_onReloginBaseappFailed_argstypes); + Messages.clientMessages[8] = Messages.messages["Client_onReloginBaseappFailed"]; + + Messages.messages["Client_onEntityLeaveWorldOptimized"] = new Message_Client_onEntityLeaveWorldOptimized(9, "Client_onEntityLeaveWorldOptimized", -1, -1, new List()); + Messages.clientMessages[9] = Messages.messages["Client_onEntityLeaveWorldOptimized"]; + + Messages.messages["Client_onRemoteMethodCallOptimized"] = new Message_Client_onRemoteMethodCallOptimized(10, "Client_onRemoteMethodCallOptimized", -1, -1, new List()); + Messages.clientMessages[10] = Messages.messages["Client_onRemoteMethodCallOptimized"]; + + Messages.messages["Client_onUpdatePropertysOptimized"] = new Message_Client_onUpdatePropertysOptimized(11, "Client_onUpdatePropertysOptimized", -1, -1, new List()); + Messages.clientMessages[11] = Messages.messages["Client_onUpdatePropertysOptimized"]; + + Messages.messages["Client_onSetEntityPosAndDir"] = new Message_Client_onSetEntityPosAndDir(12, "Client_onSetEntityPosAndDir", -1, -1, new List()); + Messages.clientMessages[12] = Messages.messages["Client_onSetEntityPosAndDir"]; + + + List Client_onUpdateBasePos_argstypes = new List(); + Client_onUpdateBasePos_argstypes.Add(13); + Client_onUpdateBasePos_argstypes.Add(13); + Client_onUpdateBasePos_argstypes.Add(13); + Messages.messages["Client_onUpdateBasePos"] = new Message_Client_onUpdateBasePos(13, "Client_onUpdateBasePos", 12, 0, Client_onUpdateBasePos_argstypes); + Messages.clientMessages[13] = Messages.messages["Client_onUpdateBasePos"]; + + Messages.messages["Client_onUpdateBaseDir"] = new Message_Client_onUpdateBaseDir(14, "Client_onUpdateBaseDir", -1, -1, new List()); + Messages.clientMessages[14] = Messages.messages["Client_onUpdateBaseDir"]; + + + List Client_onUpdateBasePosXZ_argstypes = new List(); + Client_onUpdateBasePosXZ_argstypes.Add(13); + Client_onUpdateBasePosXZ_argstypes.Add(13); + Messages.messages["Client_onUpdateBasePosXZ"] = new Message_Client_onUpdateBasePosXZ(15, "Client_onUpdateBasePosXZ", 8, 0, Client_onUpdateBasePosXZ_argstypes); + Messages.clientMessages[15] = Messages.messages["Client_onUpdateBasePosXZ"]; + + Messages.messages["Client_onUpdateData"] = new Message_Client_onUpdateData(16, "Client_onUpdateData", -1, -1, new List()); + Messages.clientMessages[16] = Messages.messages["Client_onUpdateData"]; + + Messages.messages["Client_onUpdateData_ypr"] = new Message_Client_onUpdateData_ypr(17, "Client_onUpdateData_ypr", -1, -1, new List()); + Messages.clientMessages[17] = Messages.messages["Client_onUpdateData_ypr"]; + + Messages.messages["Client_onUpdateData_yp"] = new Message_Client_onUpdateData_yp(18, "Client_onUpdateData_yp", -1, -1, new List()); + Messages.clientMessages[18] = Messages.messages["Client_onUpdateData_yp"]; + + Messages.messages["Client_onUpdateData_yr"] = new Message_Client_onUpdateData_yr(19, "Client_onUpdateData_yr", -1, -1, new List()); + Messages.clientMessages[19] = Messages.messages["Client_onUpdateData_yr"]; + + Messages.messages["Client_onUpdateData_pr"] = new Message_Client_onUpdateData_pr(20, "Client_onUpdateData_pr", -1, -1, new List()); + Messages.clientMessages[20] = Messages.messages["Client_onUpdateData_pr"]; + + Messages.messages["Client_onUpdateData_y"] = new Message_Client_onUpdateData_y(21, "Client_onUpdateData_y", -1, -1, new List()); + Messages.clientMessages[21] = Messages.messages["Client_onUpdateData_y"]; + + Messages.messages["Client_onUpdateData_p"] = new Message_Client_onUpdateData_p(22, "Client_onUpdateData_p", -1, -1, new List()); + Messages.clientMessages[22] = Messages.messages["Client_onUpdateData_p"]; + + Messages.messages["Client_onUpdateData_r"] = new Message_Client_onUpdateData_r(23, "Client_onUpdateData_r", -1, -1, new List()); + Messages.clientMessages[23] = Messages.messages["Client_onUpdateData_r"]; + + Messages.messages["Client_onUpdateData_xz"] = new Message_Client_onUpdateData_xz(24, "Client_onUpdateData_xz", -1, -1, new List()); + Messages.clientMessages[24] = Messages.messages["Client_onUpdateData_xz"]; + + Messages.messages["Client_onUpdateData_xz_ypr"] = new Message_Client_onUpdateData_xz_ypr(25, "Client_onUpdateData_xz_ypr", -1, -1, new List()); + Messages.clientMessages[25] = Messages.messages["Client_onUpdateData_xz_ypr"]; + + Messages.messages["Client_onUpdateData_xz_yp"] = new Message_Client_onUpdateData_xz_yp(26, "Client_onUpdateData_xz_yp", -1, -1, new List()); + Messages.clientMessages[26] = Messages.messages["Client_onUpdateData_xz_yp"]; + + Messages.messages["Client_onUpdateData_xz_yr"] = new Message_Client_onUpdateData_xz_yr(27, "Client_onUpdateData_xz_yr", -1, -1, new List()); + Messages.clientMessages[27] = Messages.messages["Client_onUpdateData_xz_yr"]; + + Messages.messages["Client_onUpdateData_xz_pr"] = new Message_Client_onUpdateData_xz_pr(28, "Client_onUpdateData_xz_pr", -1, -1, new List()); + Messages.clientMessages[28] = Messages.messages["Client_onUpdateData_xz_pr"]; + + Messages.messages["Client_onUpdateData_xz_y"] = new Message_Client_onUpdateData_xz_y(29, "Client_onUpdateData_xz_y", -1, -1, new List()); + Messages.clientMessages[29] = Messages.messages["Client_onUpdateData_xz_y"]; + + Messages.messages["Client_onUpdateData_xz_p"] = new Message_Client_onUpdateData_xz_p(30, "Client_onUpdateData_xz_p", -1, -1, new List()); + Messages.clientMessages[30] = Messages.messages["Client_onUpdateData_xz_p"]; + + Messages.messages["Client_onUpdateData_xz_r"] = new Message_Client_onUpdateData_xz_r(31, "Client_onUpdateData_xz_r", -1, -1, new List()); + Messages.clientMessages[31] = Messages.messages["Client_onUpdateData_xz_r"]; + + Messages.messages["Client_onUpdateData_xyz"] = new Message_Client_onUpdateData_xyz(32, "Client_onUpdateData_xyz", -1, -1, new List()); + Messages.clientMessages[32] = Messages.messages["Client_onUpdateData_xyz"]; + + Messages.messages["Client_onUpdateData_xyz_ypr"] = new Message_Client_onUpdateData_xyz_ypr(33, "Client_onUpdateData_xyz_ypr", -1, -1, new List()); + Messages.clientMessages[33] = Messages.messages["Client_onUpdateData_xyz_ypr"]; + + Messages.messages["Client_onUpdateData_xyz_yp"] = new Message_Client_onUpdateData_xyz_yp(34, "Client_onUpdateData_xyz_yp", -1, -1, new List()); + Messages.clientMessages[34] = Messages.messages["Client_onUpdateData_xyz_yp"]; + + Messages.messages["Client_onUpdateData_xyz_yr"] = new Message_Client_onUpdateData_xyz_yr(35, "Client_onUpdateData_xyz_yr", -1, -1, new List()); + Messages.clientMessages[35] = Messages.messages["Client_onUpdateData_xyz_yr"]; + + Messages.messages["Client_onUpdateData_xyz_pr"] = new Message_Client_onUpdateData_xyz_pr(36, "Client_onUpdateData_xyz_pr", -1, -1, new List()); + Messages.clientMessages[36] = Messages.messages["Client_onUpdateData_xyz_pr"]; + + Messages.messages["Client_onUpdateData_xyz_y"] = new Message_Client_onUpdateData_xyz_y(37, "Client_onUpdateData_xyz_y", -1, -1, new List()); + Messages.clientMessages[37] = Messages.messages["Client_onUpdateData_xyz_y"]; + + Messages.messages["Client_onUpdateData_xyz_p"] = new Message_Client_onUpdateData_xyz_p(38, "Client_onUpdateData_xyz_p", -1, -1, new List()); + Messages.clientMessages[38] = Messages.messages["Client_onUpdateData_xyz_p"]; + + Messages.messages["Client_onUpdateData_xyz_r"] = new Message_Client_onUpdateData_xyz_r(39, "Client_onUpdateData_xyz_r", -1, -1, new List()); + Messages.clientMessages[39] = Messages.messages["Client_onUpdateData_xyz_r"]; + + Messages.messages["Client_onUpdateData_ypr_optimized"] = new Message_Client_onUpdateData_ypr_optimized(40, "Client_onUpdateData_ypr_optimized", -1, -1, new List()); + Messages.clientMessages[40] = Messages.messages["Client_onUpdateData_ypr_optimized"]; + + Messages.messages["Client_onUpdateData_yp_optimized"] = new Message_Client_onUpdateData_yp_optimized(41, "Client_onUpdateData_yp_optimized", -1, -1, new List()); + Messages.clientMessages[41] = Messages.messages["Client_onUpdateData_yp_optimized"]; + + Messages.messages["Client_onUpdateData_yr_optimized"] = new Message_Client_onUpdateData_yr_optimized(42, "Client_onUpdateData_yr_optimized", -1, -1, new List()); + Messages.clientMessages[42] = Messages.messages["Client_onUpdateData_yr_optimized"]; + + Messages.messages["Client_onUpdateData_pr_optimized"] = new Message_Client_onUpdateData_pr_optimized(43, "Client_onUpdateData_pr_optimized", -1, -1, new List()); + Messages.clientMessages[43] = Messages.messages["Client_onUpdateData_pr_optimized"]; + + Messages.messages["Client_onUpdateData_y_optimized"] = new Message_Client_onUpdateData_y_optimized(44, "Client_onUpdateData_y_optimized", -1, -1, new List()); + Messages.clientMessages[44] = Messages.messages["Client_onUpdateData_y_optimized"]; + + Messages.messages["Client_onUpdateData_p_optimized"] = new Message_Client_onUpdateData_p_optimized(45, "Client_onUpdateData_p_optimized", -1, -1, new List()); + Messages.clientMessages[45] = Messages.messages["Client_onUpdateData_p_optimized"]; + + Messages.messages["Client_onUpdateData_r_optimized"] = new Message_Client_onUpdateData_r_optimized(46, "Client_onUpdateData_r_optimized", -1, -1, new List()); + Messages.clientMessages[46] = Messages.messages["Client_onUpdateData_r_optimized"]; + + Messages.messages["Client_onUpdateData_xz_optimized"] = new Message_Client_onUpdateData_xz_optimized(47, "Client_onUpdateData_xz_optimized", -1, -1, new List()); + Messages.clientMessages[47] = Messages.messages["Client_onUpdateData_xz_optimized"]; + + Messages.messages["Client_onUpdateData_xz_ypr_optimized"] = new Message_Client_onUpdateData_xz_ypr_optimized(48, "Client_onUpdateData_xz_ypr_optimized", -1, -1, new List()); + Messages.clientMessages[48] = Messages.messages["Client_onUpdateData_xz_ypr_optimized"]; + + Messages.messages["Client_onUpdateData_xz_yp_optimized"] = new Message_Client_onUpdateData_xz_yp_optimized(49, "Client_onUpdateData_xz_yp_optimized", -1, -1, new List()); + Messages.clientMessages[49] = Messages.messages["Client_onUpdateData_xz_yp_optimized"]; + + Messages.messages["Client_onUpdateData_xz_yr_optimized"] = new Message_Client_onUpdateData_xz_yr_optimized(50, "Client_onUpdateData_xz_yr_optimized", -1, -1, new List()); + Messages.clientMessages[50] = Messages.messages["Client_onUpdateData_xz_yr_optimized"]; + + Messages.messages["Client_onUpdateData_xz_pr_optimized"] = new Message_Client_onUpdateData_xz_pr_optimized(51, "Client_onUpdateData_xz_pr_optimized", -1, -1, new List()); + Messages.clientMessages[51] = Messages.messages["Client_onUpdateData_xz_pr_optimized"]; + + Messages.messages["Client_onUpdateData_xz_y_optimized"] = new Message_Client_onUpdateData_xz_y_optimized(52, "Client_onUpdateData_xz_y_optimized", -1, -1, new List()); + Messages.clientMessages[52] = Messages.messages["Client_onUpdateData_xz_y_optimized"]; + + Messages.messages["Client_onUpdateData_xz_p_optimized"] = new Message_Client_onUpdateData_xz_p_optimized(53, "Client_onUpdateData_xz_p_optimized", -1, -1, new List()); + Messages.clientMessages[53] = Messages.messages["Client_onUpdateData_xz_p_optimized"]; + + Messages.messages["Client_onUpdateData_xz_r_optimized"] = new Message_Client_onUpdateData_xz_r_optimized(54, "Client_onUpdateData_xz_r_optimized", -1, -1, new List()); + Messages.clientMessages[54] = Messages.messages["Client_onUpdateData_xz_r_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_optimized"] = new Message_Client_onUpdateData_xyz_optimized(55, "Client_onUpdateData_xyz_optimized", -1, -1, new List()); + Messages.clientMessages[55] = Messages.messages["Client_onUpdateData_xyz_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_ypr_optimized"] = new Message_Client_onUpdateData_xyz_ypr_optimized(56, "Client_onUpdateData_xyz_ypr_optimized", -1, -1, new List()); + Messages.clientMessages[56] = Messages.messages["Client_onUpdateData_xyz_ypr_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_yp_optimized"] = new Message_Client_onUpdateData_xyz_yp_optimized(57, "Client_onUpdateData_xyz_yp_optimized", -1, -1, new List()); + Messages.clientMessages[57] = Messages.messages["Client_onUpdateData_xyz_yp_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_yr_optimized"] = new Message_Client_onUpdateData_xyz_yr_optimized(58, "Client_onUpdateData_xyz_yr_optimized", -1, -1, new List()); + Messages.clientMessages[58] = Messages.messages["Client_onUpdateData_xyz_yr_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_pr_optimized"] = new Message_Client_onUpdateData_xyz_pr_optimized(59, "Client_onUpdateData_xyz_pr_optimized", -1, -1, new List()); + Messages.clientMessages[59] = Messages.messages["Client_onUpdateData_xyz_pr_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_y_optimized"] = new Message_Client_onUpdateData_xyz_y_optimized(60, "Client_onUpdateData_xyz_y_optimized", -1, -1, new List()); + Messages.clientMessages[60] = Messages.messages["Client_onUpdateData_xyz_y_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_p_optimized"] = new Message_Client_onUpdateData_xyz_p_optimized(61, "Client_onUpdateData_xyz_p_optimized", -1, -1, new List()); + Messages.clientMessages[61] = Messages.messages["Client_onUpdateData_xyz_p_optimized"]; + + Messages.messages["Client_onUpdateData_xyz_r_optimized"] = new Message_Client_onUpdateData_xyz_r_optimized(62, "Client_onUpdateData_xyz_r_optimized", -1, -1, new List()); + Messages.clientMessages[62] = Messages.messages["Client_onUpdateData_xyz_r_optimized"]; + + Messages.messages["Client_onImportServerErrorsDescr"] = new Message_Client_onImportServerErrorsDescr(63, "Client_onImportServerErrorsDescr", -1, -1, new List()); + Messages.clientMessages[63] = Messages.messages["Client_onImportServerErrorsDescr"]; + + Messages.messages["Client_onImportClientSDK"] = new Message_Client_onImportClientSDK(64, "Client_onImportClientSDK", -1, -1, new List()); + Messages.clientMessages[64] = Messages.messages["Client_onImportClientSDK"]; + + Messages.messages["Client_initSpaceData"] = new Message_Client_initSpaceData(65, "Client_initSpaceData", -1, -1, new List()); + Messages.clientMessages[65] = Messages.messages["Client_initSpaceData"]; + + + List Client_setSpaceData_argstypes = new List(); + Client_setSpaceData_argstypes.Add(4); + Client_setSpaceData_argstypes.Add(1); + Client_setSpaceData_argstypes.Add(1); + Messages.messages["Client_setSpaceData"] = new Message_Client_setSpaceData(66, "Client_setSpaceData", -1, 0, Client_setSpaceData_argstypes); + Messages.clientMessages[66] = Messages.messages["Client_setSpaceData"]; + + + List Client_delSpaceData_argstypes = new List(); + Client_delSpaceData_argstypes.Add(4); + Client_delSpaceData_argstypes.Add(1); + Messages.messages["Client_delSpaceData"] = new Message_Client_delSpaceData(67, "Client_delSpaceData", -1, 0, Client_delSpaceData_argstypes); + Messages.clientMessages[67] = Messages.messages["Client_delSpaceData"]; + + + List Client_onReqAccountResetPasswordCB_argstypes = new List(); + Client_onReqAccountResetPasswordCB_argstypes.Add(3); + Messages.messages["Client_onReqAccountResetPasswordCB"] = new Message_Client_onReqAccountResetPasswordCB(68, "Client_onReqAccountResetPasswordCB", 2, 0, Client_onReqAccountResetPasswordCB_argstypes); + Messages.clientMessages[68] = Messages.messages["Client_onReqAccountResetPasswordCB"]; + + + List Client_onReqAccountBindEmailCB_argstypes = new List(); + Client_onReqAccountBindEmailCB_argstypes.Add(3); + Messages.messages["Client_onReqAccountBindEmailCB"] = new Message_Client_onReqAccountBindEmailCB(69, "Client_onReqAccountBindEmailCB", 2, 0, Client_onReqAccountBindEmailCB_argstypes); + Messages.clientMessages[69] = Messages.messages["Client_onReqAccountBindEmailCB"]; + + + List Client_onReqAccountNewPasswordCB_argstypes = new List(); + Client_onReqAccountNewPasswordCB_argstypes.Add(3); + Messages.messages["Client_onReqAccountNewPasswordCB"] = new Message_Client_onReqAccountNewPasswordCB(70, "Client_onReqAccountNewPasswordCB", 2, 0, Client_onReqAccountNewPasswordCB_argstypes); + Messages.clientMessages[70] = Messages.messages["Client_onReqAccountNewPasswordCB"]; + + Messages.messages["Client_onReloginBaseappSuccessfully"] = new Message_Client_onReloginBaseappSuccessfully(71, "Client_onReloginBaseappSuccessfully", -1, -1, new List()); + Messages.clientMessages[71] = Messages.messages["Client_onReloginBaseappSuccessfully"]; + + Messages.messages["Client_onAppActiveTickCB"] = new Message_Client_onAppActiveTickCB(72, "Client_onAppActiveTickCB", 0, 0, new List()); + Messages.clientMessages[72] = Messages.messages["Client_onAppActiveTickCB"]; + + Messages.messages["Client_onCreateAccountResult"] = new Message_Client_onCreateAccountResult(501, "Client_onCreateAccountResult", -1, -1, new List()); + Messages.clientMessages[501] = Messages.messages["Client_onCreateAccountResult"]; + + Messages.messages["Client_onLoginSuccessfully"] = new Message_Client_onLoginSuccessfully(502, "Client_onLoginSuccessfully", -1, -1, new List()); + Messages.clientMessages[502] = Messages.messages["Client_onLoginSuccessfully"]; + + Messages.messages["Client_onLoginFailed"] = new Message_Client_onLoginFailed(503, "Client_onLoginFailed", -1, -1, new List()); + Messages.clientMessages[503] = Messages.messages["Client_onLoginFailed"]; + + + List Client_onCreatedProxies_argstypes = new List(); + Client_onCreatedProxies_argstypes.Add(5); + Client_onCreatedProxies_argstypes.Add(8); + Client_onCreatedProxies_argstypes.Add(1); + Messages.messages["Client_onCreatedProxies"] = new Message_Client_onCreatedProxies(504, "Client_onCreatedProxies", -1, 0, Client_onCreatedProxies_argstypes); + Messages.clientMessages[504] = Messages.messages["Client_onCreatedProxies"]; + + + List Client_onLoginBaseappFailed_argstypes = new List(); + Client_onLoginBaseappFailed_argstypes.Add(3); + Messages.messages["Client_onLoginBaseappFailed"] = new Message_Client_onLoginBaseappFailed(505, "Client_onLoginBaseappFailed", 2, 0, Client_onLoginBaseappFailed_argstypes); + Messages.clientMessages[505] = Messages.messages["Client_onLoginBaseappFailed"]; + + Messages.messages["Client_onRemoteMethodCall"] = new Message_Client_onRemoteMethodCall(506, "Client_onRemoteMethodCall", -1, -1, new List()); + Messages.clientMessages[506] = Messages.messages["Client_onRemoteMethodCall"]; + + Messages.messages["Client_onEntityEnterWorld"] = new Message_Client_onEntityEnterWorld(507, "Client_onEntityEnterWorld", -1, -1, new List()); + Messages.clientMessages[507] = Messages.messages["Client_onEntityEnterWorld"]; + + + List Client_onEntityLeaveWorld_argstypes = new List(); + Client_onEntityLeaveWorld_argstypes.Add(8); + Messages.messages["Client_onEntityLeaveWorld"] = new Message_Client_onEntityLeaveWorld(508, "Client_onEntityLeaveWorld", 4, 0, Client_onEntityLeaveWorld_argstypes); + Messages.clientMessages[508] = Messages.messages["Client_onEntityLeaveWorld"]; + + Messages.messages["Client_onEntityEnterSpace"] = new Message_Client_onEntityEnterSpace(509, "Client_onEntityEnterSpace", -1, -1, new List()); + Messages.clientMessages[509] = Messages.messages["Client_onEntityEnterSpace"]; + + + List Client_onEntityLeaveSpace_argstypes = new List(); + Client_onEntityLeaveSpace_argstypes.Add(8); + Messages.messages["Client_onEntityLeaveSpace"] = new Message_Client_onEntityLeaveSpace(510, "Client_onEntityLeaveSpace", 4, 0, Client_onEntityLeaveSpace_argstypes); + Messages.clientMessages[510] = Messages.messages["Client_onEntityLeaveSpace"]; + + Messages.messages["Client_onUpdatePropertys"] = new Message_Client_onUpdatePropertys(511, "Client_onUpdatePropertys", -1, -1, new List()); + Messages.clientMessages[511] = Messages.messages["Client_onUpdatePropertys"]; + + + List Client_onEntityDestroyed_argstypes = new List(); + Client_onEntityDestroyed_argstypes.Add(8); + Messages.messages["Client_onEntityDestroyed"] = new Message_Client_onEntityDestroyed(512, "Client_onEntityDestroyed", 4, 0, Client_onEntityDestroyed_argstypes); + Messages.clientMessages[512] = Messages.messages["Client_onEntityDestroyed"]; + + + List Client_onStreamDataStarted_argstypes = new List(); + Client_onStreamDataStarted_argstypes.Add(7); + Client_onStreamDataStarted_argstypes.Add(4); + Client_onStreamDataStarted_argstypes.Add(1); + Messages.messages["Client_onStreamDataStarted"] = new Message_Client_onStreamDataStarted(514, "Client_onStreamDataStarted", -1, 0, Client_onStreamDataStarted_argstypes); + Messages.clientMessages[514] = Messages.messages["Client_onStreamDataStarted"]; + + Messages.messages["Client_onStreamDataRecv"] = new Message_Client_onStreamDataRecv(515, "Client_onStreamDataRecv", -1, -1, new List()); + Messages.clientMessages[515] = Messages.messages["Client_onStreamDataRecv"]; + + + List Client_onStreamDataCompleted_argstypes = new List(); + Client_onStreamDataCompleted_argstypes.Add(7); + Messages.messages["Client_onStreamDataCompleted"] = new Message_Client_onStreamDataCompleted(516, "Client_onStreamDataCompleted", 2, 0, Client_onStreamDataCompleted_argstypes); + Messages.clientMessages[516] = Messages.messages["Client_onStreamDataCompleted"]; + + + List Client_onKicked_argstypes = new List(); + Client_onKicked_argstypes.Add(3); + Messages.messages["Client_onKicked"] = new Message_Client_onKicked(517, "Client_onKicked", 2, 0, Client_onKicked_argstypes); + Messages.clientMessages[517] = Messages.messages["Client_onKicked"]; + + Messages.messages["Client_onImportClientMessages"] = new Message_Client_onImportClientMessages(518, "Client_onImportClientMessages", -1, -1, new List()); + Messages.clientMessages[518] = Messages.messages["Client_onImportClientMessages"]; + + Messages.messages["Client_onImportClientEntityDef"] = new Message_Client_onImportClientEntityDef(519, "Client_onImportClientEntityDef", -1, -1, new List()); + Messages.clientMessages[519] = Messages.messages["Client_onImportClientEntityDef"]; + + Messages.messages["Client_onHelloCB"] = new Message_Client_onHelloCB(521, "Client_onHelloCB", -1, -1, new List()); + Messages.clientMessages[521] = Messages.messages["Client_onHelloCB"]; + + Messages.messages["Client_onScriptVersionNotMatch"] = new Message_Client_onScriptVersionNotMatch(522, "Client_onScriptVersionNotMatch", -1, -1, new List()); + Messages.clientMessages[522] = Messages.messages["Client_onScriptVersionNotMatch"]; + + Messages.messages["Client_onVersionNotMatch"] = new Message_Client_onVersionNotMatch(523, "Client_onVersionNotMatch", -1, -1, new List()); + Messages.clientMessages[523] = Messages.messages["Client_onVersionNotMatch"]; + + + List Client_onControlEntity_argstypes = new List(); + Client_onControlEntity_argstypes.Add(8); + Client_onControlEntity_argstypes.Add(6); + Messages.messages["Client_onControlEntity"] = new Message_Client_onControlEntity(524, "Client_onControlEntity", 5, 0, Client_onControlEntity_argstypes); + Messages.clientMessages[524] = Messages.messages["Client_onControlEntity"]; + + Messages.messages["Loginapp_reqCreateAccount"] = new Message_Loginapp_reqCreateAccount(2, "Loginapp_reqCreateAccount", -1, 0, new List()); + Messages.loginappMessages[2] = Messages.messages["Loginapp_reqCreateAccount"]; + + Messages.messages["Loginapp_login"] = new Message_Loginapp_login(3, "Loginapp_login", -1, 0, new List()); + Messages.loginappMessages[3] = Messages.messages["Loginapp_login"]; + + Messages.messages["Loginapp_hello"] = new Message_Loginapp_hello(4, "Loginapp_hello", -1, 0, new List()); + Messages.loginappMessages[4] = Messages.messages["Loginapp_hello"]; + + Messages.messages["Loginapp_importClientMessages"] = new Message_Loginapp_importClientMessages(5, "Loginapp_importClientMessages", 0, 0, new List()); + Messages.loginappMessages[5] = Messages.messages["Loginapp_importClientMessages"]; + + Messages.messages["Loginapp_reqCreateMailAccount"] = new Message_Loginapp_reqCreateMailAccount(6, "Loginapp_reqCreateMailAccount", -1, 0, new List()); + Messages.loginappMessages[6] = Messages.messages["Loginapp_reqCreateMailAccount"]; + + Messages.messages["Loginapp_importClientSDK"] = new Message_Loginapp_importClientSDK(7, "Loginapp_importClientSDK", -1, 0, new List()); + Messages.loginappMessages[7] = Messages.messages["Loginapp_importClientSDK"]; + + Messages.messages["Loginapp_importServerErrorsDescr"] = new Message_Loginapp_importServerErrorsDescr(8, "Loginapp_importServerErrorsDescr", 0, 0, new List()); + Messages.loginappMessages[8] = Messages.messages["Loginapp_importServerErrorsDescr"]; + + Messages.messages["Loginapp_onClientActiveTick"] = new Message_Loginapp_onClientActiveTick(11, "Loginapp_onClientActiveTick", 0, 0, new List()); + Messages.loginappMessages[11] = Messages.messages["Loginapp_onClientActiveTick"]; + + + List Loginapp_reqAccountResetPassword_argstypes = new List(); + Loginapp_reqAccountResetPassword_argstypes.Add(1); + Messages.messages["Loginapp_reqAccountResetPassword"] = new Message_Loginapp_reqAccountResetPassword(12, "Loginapp_reqAccountResetPassword", -1, 0, Loginapp_reqAccountResetPassword_argstypes); + Messages.loginappMessages[12] = Messages.messages["Loginapp_reqAccountResetPassword"]; + + + List Baseapp_logoutBaseapp_argstypes = new List(); + Baseapp_logoutBaseapp_argstypes.Add(5); + Baseapp_logoutBaseapp_argstypes.Add(8); + Messages.messages["Baseapp_logoutBaseapp"] = new Message_Baseapp_logoutBaseapp(24, "Baseapp_logoutBaseapp", 12, 0, Baseapp_logoutBaseapp_argstypes); + Messages.baseappMessages[24] = Messages.messages["Baseapp_logoutBaseapp"]; + + Messages.messages["Baseapp_onUpdateDataFromClient"] = new Message_Baseapp_onUpdateDataFromClient(27, "Baseapp_onUpdateDataFromClient", -1, -1, new List()); + Messages.baseappMessages[27] = Messages.messages["Baseapp_onUpdateDataFromClient"]; + + Messages.messages["Baseapp_onUpdateDataFromClientForControlledEntity"] = new Message_Baseapp_onUpdateDataFromClientForControlledEntity(28, "Baseapp_onUpdateDataFromClientForControlledEntity", -1, -1, new List()); + Messages.baseappMessages[28] = Messages.messages["Baseapp_onUpdateDataFromClientForControlledEntity"]; + + + List Baseapp_reqAccountBindEmail_argstypes = new List(); + Baseapp_reqAccountBindEmail_argstypes.Add(8); + Baseapp_reqAccountBindEmail_argstypes.Add(1); + Baseapp_reqAccountBindEmail_argstypes.Add(1); + Messages.messages["Baseapp_reqAccountBindEmail"] = new Message_Baseapp_reqAccountBindEmail(50, "Baseapp_reqAccountBindEmail", -1, 0, Baseapp_reqAccountBindEmail_argstypes); + Messages.baseappMessages[50] = Messages.messages["Baseapp_reqAccountBindEmail"]; + + + List Baseapp_reqAccountNewPassword_argstypes = new List(); + Baseapp_reqAccountNewPassword_argstypes.Add(8); + Baseapp_reqAccountNewPassword_argstypes.Add(1); + Baseapp_reqAccountNewPassword_argstypes.Add(1); + Messages.messages["Baseapp_reqAccountNewPassword"] = new Message_Baseapp_reqAccountNewPassword(53, "Baseapp_reqAccountNewPassword", -1, 0, Baseapp_reqAccountNewPassword_argstypes); + Messages.baseappMessages[53] = Messages.messages["Baseapp_reqAccountNewPassword"]; + + Messages.messages["Entity_forwardEntityMessageToCellappFromClient"] = new Message_Entity_forwardEntityMessageToCellappFromClient(57, "Entity_forwardEntityMessageToCellappFromClient", -1, -1, new List()); + Messages.baseappMessages[57] = Messages.messages["Entity_forwardEntityMessageToCellappFromClient"]; + + Messages.messages["Baseapp_hello"] = new Message_Baseapp_hello(200, "Baseapp_hello", -1, -1, new List()); + Messages.baseappMessages[200] = Messages.messages["Baseapp_hello"]; + + + List Baseapp_loginBaseapp_argstypes = new List(); + Baseapp_loginBaseapp_argstypes.Add(1); + Baseapp_loginBaseapp_argstypes.Add(1); + Messages.messages["Baseapp_loginBaseapp"] = new Message_Baseapp_loginBaseapp(202, "Baseapp_loginBaseapp", -1, 0, Baseapp_loginBaseapp_argstypes); + Messages.baseappMessages[202] = Messages.messages["Baseapp_loginBaseapp"]; + + + List Baseapp_reloginBaseapp_argstypes = new List(); + Baseapp_reloginBaseapp_argstypes.Add(1); + Baseapp_reloginBaseapp_argstypes.Add(1); + Baseapp_reloginBaseapp_argstypes.Add(5); + Baseapp_reloginBaseapp_argstypes.Add(8); + Messages.messages["Baseapp_reloginBaseapp"] = new Message_Baseapp_reloginBaseapp(204, "Baseapp_reloginBaseapp", -1, 0, Baseapp_reloginBaseapp_argstypes); + Messages.baseappMessages[204] = Messages.messages["Baseapp_reloginBaseapp"]; + + Messages.messages["Baseapp_onRemoteCallCellMethodFromClient"] = new Message_Baseapp_onRemoteCallCellMethodFromClient(205, "Baseapp_onRemoteCallCellMethodFromClient", -1, -1, new List()); + Messages.baseappMessages[205] = Messages.messages["Baseapp_onRemoteCallCellMethodFromClient"]; + + Messages.messages["Baseapp_onClientActiveTick"] = new Message_Baseapp_onClientActiveTick(206, "Baseapp_onClientActiveTick", 0, 0, new List()); + Messages.baseappMessages[206] = Messages.messages["Baseapp_onClientActiveTick"]; + + Messages.messages["Baseapp_importClientMessages"] = new Message_Baseapp_importClientMessages(207, "Baseapp_importClientMessages", 0, 0, new List()); + Messages.baseappMessages[207] = Messages.messages["Baseapp_importClientMessages"]; + + Messages.messages["Baseapp_importClientEntityDef"] = new Message_Baseapp_importClientEntityDef(208, "Baseapp_importClientEntityDef", 0, 0, new List()); + Messages.baseappMessages[208] = Messages.messages["Baseapp_importClientEntityDef"]; + + Messages.messages["Entity_onRemoteMethodCall"] = new Message_Entity_onRemoteMethodCall(302, "Entity_onRemoteMethodCall", -1, -1, new List()); + Messages.baseappMessages[302] = Messages.messages["Entity_onRemoteMethodCall"]; + + + return true; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Messages.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Messages.cs.meta new file mode 100644 index 00000000..8dc08a9b --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Messages.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: cfb32370343d2004c9de86018507b9aa +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Method.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Method.cs new file mode 100644 index 00000000..92167e9b --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Method.cs @@ -0,0 +1,26 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + /* + 实体定义的方法模块 + 抽象出一个def文件中定义的方法,改模块类提供了该方法的相关描述信息 + 例如:方法的参数、方法的id、方法对应脚本的handler + */ + public class Method + { + public string name = ""; + public UInt16 methodUtype = 0; + public Int16 aliasID = -1; + public List args = null; + + public Method() + { + + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Method.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Method.cs.meta new file mode 100644 index 00000000..b133dc06 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Method.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 580c3e7331c42ac4385a6065dadc2bae +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MonsterBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MonsterBase.cs new file mode 100644 index 00000000..8ec41268 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MonsterBase.cs @@ -0,0 +1,806 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class Monster : MonsterBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Monster.def + // Please inherit and implement "class Monster : MonsterBase" + public abstract class MonsterBase : Entity + { + public EntityBaseEntityCall_MonsterBase baseEntityCall = null; + public EntityCellEntityCall_MonsterBase cellEntityCall = null; + + public Int32 HP = 0; + public virtual void onHPChanged(Int32 oldValue) {} + public Int32 HP_Max = 0; + public virtual void onHP_MaxChanged(Int32 oldValue) {} + public Int32 MP = 0; + public virtual void onMPChanged(Int32 oldValue) {} + public Int32 MP_Max = 0; + public virtual void onMP_MaxChanged(Int32 oldValue) {} + public UInt32 entityNO = 0; + public virtual void onEntityNOChanged(UInt32 oldValue) {} + public Int32 forbids = 0; + public virtual void onForbidsChanged(Int32 oldValue) {} + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public Byte moveSpeed = 50; + public virtual void onMoveSpeedChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public SByte state = 0; + public virtual void onStateChanged(SByte oldValue) {} + public Byte subState = 0; + public virtual void onSubStateChanged(Byte oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + public abstract void recvDamage(Int32 arg1, Int32 arg2, Int32 arg3, Int32 arg4); + + public MonsterBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_MonsterBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_MonsterBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Monster"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + case 34: + Int32 recvDamage_arg1 = stream.readInt32(); + Int32 recvDamage_arg2 = stream.readInt32(); + Int32 recvDamage_arg3 = stream.readInt32(); + Int32 recvDamage_arg4 = stream.readInt32(); + recvDamage(recvDamage_arg1, recvDamage_arg2, recvDamage_arg3, recvDamage_arg4); + break; + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Monster"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 47001: + Int32 oldval_HP = HP; + HP = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onHPChanged(oldval_HP); + } + else + { + if(inWorld) + onHPChanged(oldval_HP); + } + + break; + case 47002: + Int32 oldval_HP_Max = HP_Max; + HP_Max = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onHP_MaxChanged(oldval_HP_Max); + } + else + { + if(inWorld) + onHP_MaxChanged(oldval_HP_Max); + } + + break; + case 47003: + Int32 oldval_MP = MP; + MP = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onMPChanged(oldval_MP); + } + else + { + if(inWorld) + onMPChanged(oldval_MP); + } + + break; + case 47004: + Int32 oldval_MP_Max = MP_Max; + MP_Max = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onMP_MaxChanged(oldval_MP_Max); + } + else + { + if(inWorld) + onMP_MaxChanged(oldval_MP_Max); + } + + break; + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 51007: + UInt32 oldval_entityNO = entityNO; + entityNO = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onEntityNOChanged(oldval_entityNO); + } + else + { + if(inWorld) + onEntityNOChanged(oldval_entityNO); + } + + break; + case 47005: + Int32 oldval_forbids = forbids; + forbids = stream.readInt32(); + + if(prop.isBase()) + { + if(inited) + onForbidsChanged(oldval_forbids); + } + else + { + if(inWorld) + onForbidsChanged(oldval_forbids); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 32: + Byte oldval_moveSpeed = moveSpeed; + moveSpeed = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onMoveSpeedChanged(oldval_moveSpeed); + } + else + { + if(inWorld) + onMoveSpeedChanged(oldval_moveSpeed); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 47006: + SByte oldval_state = state; + state = stream.readInt8(); + + if(prop.isBase()) + { + if(inited) + onStateChanged(oldval_state); + } + else + { + if(inWorld) + onStateChanged(oldval_state); + } + + break; + case 47007: + Byte oldval_subState = subState; + subState = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onSubStateChanged(oldval_subState); + } + else + { + if(inWorld) + onSubStateChanged(oldval_subState); + } + + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["Monster"]; + Dictionary pdatas = sm.idpropertys; + + Int32 oldval_HP = HP; + Property prop_HP = pdatas[4]; + if(prop_HP.isBase()) + { + if(inited && !inWorld) + onHPChanged(oldval_HP); + } + else + { + if(inWorld) + { + if(prop_HP.isOwnerOnly() && !isPlayer()) + { + } + else + { + onHPChanged(oldval_HP); + } + } + } + + Int32 oldval_HP_Max = HP_Max; + Property prop_HP_Max = pdatas[5]; + if(prop_HP_Max.isBase()) + { + if(inited && !inWorld) + onHP_MaxChanged(oldval_HP_Max); + } + else + { + if(inWorld) + { + if(prop_HP_Max.isOwnerOnly() && !isPlayer()) + { + } + else + { + onHP_MaxChanged(oldval_HP_Max); + } + } + } + + Int32 oldval_MP = MP; + Property prop_MP = pdatas[6]; + if(prop_MP.isBase()) + { + if(inited && !inWorld) + onMPChanged(oldval_MP); + } + else + { + if(inWorld) + { + if(prop_MP.isOwnerOnly() && !isPlayer()) + { + } + else + { + onMPChanged(oldval_MP); + } + } + } + + Int32 oldval_MP_Max = MP_Max; + Property prop_MP_Max = pdatas[7]; + if(prop_MP_Max.isBase()) + { + if(inited && !inWorld) + onMP_MaxChanged(oldval_MP_Max); + } + else + { + if(inWorld) + { + if(prop_MP_Max.isOwnerOnly() && !isPlayer()) + { + } + else + { + onMP_MaxChanged(oldval_MP_Max); + } + } + } + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt32 oldval_entityNO = entityNO; + Property prop_entityNO = pdatas[8]; + if(prop_entityNO.isBase()) + { + if(inited && !inWorld) + onEntityNOChanged(oldval_entityNO); + } + else + { + if(inWorld) + { + if(prop_entityNO.isOwnerOnly() && !isPlayer()) + { + } + else + { + onEntityNOChanged(oldval_entityNO); + } + } + } + + Int32 oldval_forbids = forbids; + Property prop_forbids = pdatas[9]; + if(prop_forbids.isBase()) + { + if(inited && !inWorld) + onForbidsChanged(oldval_forbids); + } + else + { + if(inWorld) + { + if(prop_forbids.isOwnerOnly() && !isPlayer()) + { + } + else + { + onForbidsChanged(oldval_forbids); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[10]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[11]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + Byte oldval_moveSpeed = moveSpeed; + Property prop_moveSpeed = pdatas[12]; + if(prop_moveSpeed.isBase()) + { + if(inited && !inWorld) + onMoveSpeedChanged(oldval_moveSpeed); + } + else + { + if(inWorld) + { + if(prop_moveSpeed.isOwnerOnly() && !isPlayer()) + { + } + else + { + onMoveSpeedChanged(oldval_moveSpeed); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[13]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + SByte oldval_state = state; + Property prop_state = pdatas[14]; + if(prop_state.isBase()) + { + if(inited && !inWorld) + onStateChanged(oldval_state); + } + else + { + if(inWorld) + { + if(prop_state.isOwnerOnly() && !isPlayer()) + { + } + else + { + onStateChanged(oldval_state); + } + } + } + + Byte oldval_subState = subState; + Property prop_subState = pdatas[15]; + if(prop_subState.isBase()) + { + if(inited && !inWorld) + onSubStateChanged(oldval_subState); + } + else + { + if(inWorld) + { + if(prop_subState.isOwnerOnly() && !isPlayer()) + { + } + else + { + onSubStateChanged(oldval_subState); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[16]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[17]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MonsterBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MonsterBase.cs.meta new file mode 100644 index 00000000..3eb28904 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/MonsterBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 5789c493eb32f0e40aec2d97201ef6b8 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NPCBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NPCBase.cs new file mode 100644 index 00000000..75f016ba --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NPCBase.cs @@ -0,0 +1,525 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class NPC : NPCBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/NPC.def + // Please inherit and implement "class NPC : NPCBase" + public abstract class NPCBase : Entity + { + public EntityBaseEntityCall_NPCBase baseEntityCall = null; + public EntityCellEntityCall_NPCBase cellEntityCall = null; + + public UInt32 entityNO = 0; + public virtual void onEntityNOChanged(UInt32 oldValue) {} + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public Byte moveSpeed = 50; + public virtual void onMoveSpeedChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + + public NPCBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_NPCBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_NPCBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["NPC"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["NPC"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 51007: + UInt32 oldval_entityNO = entityNO; + entityNO = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onEntityNOChanged(oldval_entityNO); + } + else + { + if(inWorld) + onEntityNOChanged(oldval_entityNO); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 43: + Byte oldval_moveSpeed = moveSpeed; + moveSpeed = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onMoveSpeedChanged(oldval_moveSpeed); + } + else + { + if(inWorld) + onMoveSpeedChanged(oldval_moveSpeed); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["NPC"]; + Dictionary pdatas = sm.idpropertys; + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt32 oldval_entityNO = entityNO; + Property prop_entityNO = pdatas[4]; + if(prop_entityNO.isBase()) + { + if(inited && !inWorld) + onEntityNOChanged(oldval_entityNO); + } + else + { + if(inWorld) + { + if(prop_entityNO.isOwnerOnly() && !isPlayer()) + { + } + else + { + onEntityNOChanged(oldval_entityNO); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[5]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[6]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + Byte oldval_moveSpeed = moveSpeed; + Property prop_moveSpeed = pdatas[7]; + if(prop_moveSpeed.isBase()) + { + if(inited && !inWorld) + onMoveSpeedChanged(oldval_moveSpeed); + } + else + { + if(inWorld) + { + if(prop_moveSpeed.isOwnerOnly() && !isPlayer()) + { + } + else + { + onMoveSpeedChanged(oldval_moveSpeed); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[8]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[9]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[10]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NPCBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NPCBase.cs.meta new file mode 100644 index 00000000..936543cd --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NPCBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f15a9cfdc931cd54ebef20859fa544bb +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceBase.cs new file mode 100644 index 00000000..55c5cea0 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceBase.cs @@ -0,0 +1,268 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /// + /// 网络模块 + /// 处理连接、收发数据 + /// + public abstract class NetworkInterfaceBase + { + public const int TCP_PACKET_MAX = 1460; + public const int UDP_PACKET_MAX = 1472; + public const string UDP_HELLO = "62a559f3fa7748bc22f8e0766019d498"; + public const string UDP_HELLO_ACK = "1432ad7c829170a76dd31982c3501eca"; + + public delegate void AsyncConnectMethod(ConnectState state); + public delegate void ConnectCallback(string ip, int port, bool success, object userData); + + protected Socket _socket = null; + protected PacketReceiverBase _packetReceiver = null; + protected PacketSenderBase _packetSender = null; + protected EncryptionFilter _filter = null; + + public bool connected = false; + + public class ConnectState + { + // for connect + public string connectIP = ""; + public int connectPort = 0; + public ConnectCallback connectCB = null; + public AsyncConnectMethod caller = null; + public object userData = null; + public Socket socket = null; + public NetworkInterfaceBase networkInterface = null; + public string error = ""; + } + + public NetworkInterfaceBase() + { + reset(); + } + + ~NetworkInterfaceBase() + { + Dbg.DEBUG_MSG("NetworkInterfaceBase::~NetworkInterfaceBase(), destructed!!!"); + reset(); + } + + public virtual Socket sock() + { + return _socket; + } + + public virtual void reset() + { + _packetReceiver = null; + _packetSender = null; + _filter = null; + connected = false; + + if(_socket != null) + { + try + { + if(_socket.RemoteEndPoint != null) + Dbg.DEBUG_MSG(string.Format("NetworkInterfaceBase::reset(), close socket from '{0}'", _socket.RemoteEndPoint.ToString())); + } + catch (Exception e) + { + + } + + _socket.Close(0); + _socket = null; + } + } + + + public virtual void close() + { + if(_socket != null) + { + _socket.Close(0); + _socket = null; + Event.fireAll(EventOutTypes.onDisconnected); + } + + _socket = null; + connected = false; + } + + protected abstract PacketReceiverBase createPacketReceiver(); + protected abstract PacketSenderBase createPacketSender(); + protected abstract Socket createSocket(); + protected abstract void onAsyncConnect(ConnectState state); + + public virtual PacketReceiverBase packetReceiver() + { + return _packetReceiver; + } + + public virtual PacketSenderBase PacketSender() + { + return _packetSender; + } + + public virtual bool valid() + { + return ((_socket != null) && (_socket.Connected == true)); + } + + public void _onConnectionState(ConnectState state) + { + KBEngine.Event.deregisterIn(this); + + bool success = (state.error == "" && valid()); + if (success) + { + Dbg.DEBUG_MSG(string.Format("NetworkInterfaceBase::_onConnectionState(), connect to {0}:{1} is success!", state.connectIP, state.connectPort)); + _packetReceiver = createPacketReceiver(); + _packetReceiver.startRecv(); + connected = true; + } + else + { + reset(); + Dbg.ERROR_MSG(string.Format("NetworkInterfaceBase::_onConnectionState(), connect error! ip: {0}:{1}, err: {2}", state.connectIP, state.connectPort, state.error)); + } + + Event.fireAll(EventOutTypes.onConnectionState, success); + + if (state.connectCB != null) + state.connectCB(state.connectIP, state.connectPort, success, state.userData); + } + + private static void connectCB(IAsyncResult ar) + { + ConnectState state = null; + + try + { + // Retrieve the socket from the state object. + state = (ConnectState) ar.AsyncState; + + // Complete the connection. + state.socket.EndConnect(ar); + + Event.fireIn("_onConnectionState", new object[] { state }); + } + catch (Exception e) + { + state.error = e.ToString(); + Event.fireIn("_onConnectionState", new object[] { state }); + } + } + + /// + /// 在非主线程执行:连接服务器 + /// + private void _asyncConnect(ConnectState state) + { + Dbg.DEBUG_MSG(string.Format("NetworkInterfaceBase::_asyncConnect(), will connect to '{0}:{1}' ...", state.connectIP, state.connectPort)); + onAsyncConnect(state); + } + + protected virtual void onAsyncConnectCB(ConnectState state) + { + + } + + /// + /// 在非主线程执行:连接服务器结果回调 + /// + private void _asyncConnectCB(IAsyncResult ar) + { + ConnectState state = (ConnectState)ar.AsyncState; + + onAsyncConnectCB(state); + + Dbg.DEBUG_MSG(string.Format("NetworkInterfaceBase::_asyncConnectCB(), connect to '{0}:{1}' finish. error = '{2}'", state.connectIP, state.connectPort, state.error)); + + // Call EndInvoke to retrieve the results. + state.caller.EndInvoke(ar); + Event.fireIn("_onConnectionState", new object[] { state }); + } + + public void connectTo(string ip, int port, ConnectCallback callback, object userData) + { + if (valid()) + throw new InvalidOperationException("Have already connected!"); + + if (!(new Regex(@"((?:(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d)))\.){3}(?:25[0-5]|2[0-4]\d|((1\d{2})|([1-9]?\d))))")).IsMatch(ip)) + { + IPHostEntry ipHost = Dns.GetHostEntry(ip); + ip = ipHost.AddressList[0].ToString(); + } + + _socket = createSocket(); + + AsyncConnectMethod asyncConnectMethod = new AsyncConnectMethod(this._asyncConnect); + + ConnectState state = new ConnectState(); + state.connectIP = ip; + state.connectPort = port; + state.connectCB = callback; + state.userData = userData; + state.socket = _socket; + state.networkInterface = this; + state.caller = asyncConnectMethod; + + Dbg.DEBUG_MSG("connect to " + ip + ":" + port + " ..."); + connected = false; + + // 先注册一个事件回调,该事件在当前线程触发 + Event.registerIn("_onConnectionState", this, "_onConnectionState"); + + asyncConnectMethod.BeginInvoke(state, new AsyncCallback(this._asyncConnectCB), state); + } + + public virtual bool send(MemoryStream stream) + { + if (!valid()) + { + throw new ArgumentException("invalid socket!"); + } + + if (_packetSender == null) + _packetSender = createPacketSender(); + + if (_filter != null) + return _filter.send(_packetSender, stream); + + return _packetSender.send(stream); + } + + public virtual void process() + { + if (!valid()) + return; + + if (_packetReceiver != null) + _packetReceiver.process(); + } + + + public EncryptionFilter fileter() + { + return _filter; + } + + public void setFilter(EncryptionFilter filter) + { + _filter = filter; + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceBase.cs.meta new file mode 100644 index 00000000..9144d4e1 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9e0fe4fa3e32d6543b277127e00e7d00 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceKCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceKCP.cs new file mode 100644 index 00000000..6633c689 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceKCP.cs @@ -0,0 +1,218 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /// + /// 网络模块 + /// 处理连接、收发数据 + /// + public class NetworkInterfaceKCP : NetworkInterfaceBase + { + private Deps.KCP kcp_ = null; + public UInt32 connID; + public UInt32 nextTickKcpUpdate = 0; + public EndPoint remoteEndPint = null; + + protected override Socket createSocket() + { + Socket pSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + return pSocket; + } + + protected override PacketReceiverBase createPacketReceiver() + { + return new PacketReceiverKCP(this); + } + + protected override PacketSenderBase createPacketSender() + { + return new PacketSenderKCP(this); + } + + public override void reset() + { + finiKCP(); + base.reset(); + } + + public override void close() + { + finiKCP(); + base.close(); + } + + public override bool valid() + { + return ((kcp_ != null) && (_socket != null) && connected); + } + + protected void outputKCP(byte[] data, int size, object userData) + { + if (!valid()) + { + throw new ArgumentException("invalid socket!"); + } + + if (_packetSender == null) + _packetSender = createPacketSender(); + + ((PacketSenderKCP)_packetSender).sendto(data, size); + } + + bool initKCP() + { + kcp_ = new Deps.KCP(connID, this); + kcp_.SetOutput(outputKCP); + + kcp_.SetMTU(1400); + kcp_.WndSize(KBEngineApp.app.getInitArgs().getUDPSendBufferSize(), KBEngineApp.app.getInitArgs().getUDPRecvBufferSize()); + kcp_.NoDelay(1, 10, 2, 1); + kcp_.SetMinRTO(10); + + nextTickKcpUpdate = 0; + return true; + } + + bool finiKCP() + { + if(kcp_ != null) + { + kcp_.SetOutput(null); + kcp_.Release(); + kcp_ = null; + } + + remoteEndPint = null; + connID = 0; + nextTickKcpUpdate = 0; + return true; + } + + public Deps.KCP kcp() + { + return kcp_; + } + + public override bool send(MemoryStream stream) + { + if (!valid()) + { + throw new ArgumentException("invalid socket!"); + } + + if(_filter != null) + { + _filter.encrypt(stream); + } + + nextTickKcpUpdate = 0; + return kcp_.Send(stream.data(), stream.rpos, (int)stream.length()) >= 0; + } + + public override void process() + { + if (!valid()) + return; + + uint current = Deps.KCP.TimeUtils.iclock(); + if(current >= nextTickKcpUpdate) + { + kcp_.Update(current); + nextTickKcpUpdate = kcp_.Check(current); + } + + if (_packetReceiver != null) + _packetReceiver.process(); + } + + protected override void onAsyncConnectCB(ConnectState state) + { + if(state.error.Length > 0 || !initKCP()) + return; + + connected = true; + remoteEndPint = new IPEndPoint(IPAddress.Parse(state.connectIP), state.connectPort); + } + + protected override void onAsyncConnect(ConnectState state) + { + try + { + //state.socket.Connect(state.connectIP, state.connectPort); + + byte[] helloPacket = System.Text.Encoding.ASCII.GetBytes(UDP_HELLO); + state.socket.SendTo(helloPacket, helloPacket.Length, SocketFlags.None, new IPEndPoint(IPAddress.Parse(state.connectIP), state.connectPort)); + + ArrayList readList = new ArrayList(); + readList.Add(state.socket); + Socket.Select(readList, null, null, 3000000); + + if(readList.Count > 0) + { + byte[] buffer = new byte[UDP_PACKET_MAX]; + int length = state.socket.Receive(buffer); + + if (length <= 0) + { + Dbg.ERROR_MSG(string.Format("NetworkInterfaceKCP::_asyncConnect(), failed to connect to '{0}:{1}'! receive hello-ack error!", state.connectIP, state.connectPort)); + state.error = "receive hello-ack error!"; + } + else + { + MemoryStream stream = new MemoryStream(); + Array.Copy(buffer, 0, stream.data(), stream.wpos, length); + stream.wpos = length; + string helloAck = stream.readString(); + string versionString = stream.readString(); + uint conv = stream.readUint32(); + + if (helloAck != UDP_HELLO_ACK) + { + Dbg.ERROR_MSG(string.Format("NetworkInterfaceKCP::_asyncConnect(), failed to connect to '{0}:{1}'! receive hello-ack({2}!={3}) mismatch!", + state.connectIP, state.connectPort, helloAck, UDP_HELLO_ACK)); + + state.error = "hello-ack mismatch!"; + } + else if(KBEngineApp.app.serverVersion != versionString) + { + Dbg.ERROR_MSG(string.Format("NetworkInterfaceKCP::_asyncConnect(), failed to connect to '{0}:{1}'! version({2}!={3}) mismatch!", + state.connectIP, state.connectPort, versionString, KBEngineApp.app.serverVersion)); + + state.error = "version mismatch!"; + } + else if(conv == 0) + { + Dbg.ERROR_MSG(string.Format("NetworkInterfaceKCP::_asyncConnect(), failed to connect to '{0}:{1}'! conv is 0!", + state.connectIP, state.connectPort)); + + state.error = "kcp conv error!"; + } + + ((NetworkInterfaceKCP)state.networkInterface).connID = conv; + } + } + else + { + Dbg.ERROR_MSG(string.Format("NetworkInterfaceKCP::_asyncConnect(), connect to '{0}:{1}' timeout!'", state.connectIP, state.connectPort)); + state.error = "timeout!"; + } + } + catch (Exception e) + { + Dbg.ERROR_MSG(string.Format("NetworkInterfaceKCP::_asyncConnect(), connect to '{0}:{1}' fault! error = '{2}'", state.connectIP, state.connectPort, e)); + state.error = e.ToString(); + } + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceKCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceKCP.cs.meta new file mode 100644 index 00000000..06ec9e6f --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceKCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 13aaf1bccbe7a5c4e96d4c09665770ed +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceTCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceTCP.cs new file mode 100644 index 00000000..8563d1fe --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceTCP.cs @@ -0,0 +1,61 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /// + /// 网络模块 + /// 处理连接、收发数据 + /// + public class NetworkInterfaceTCP : NetworkInterfaceBase + { + public override bool valid() + { + return ((_socket != null) && (_socket.Connected == true)); + } + + protected override Socket createSocket() + { + // Security.PrefetchSocketPolicy(ip, 843); + Socket pSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + pSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, KBEngineApp.app.getInitArgs().getTCPRecvBufferSize() * 2); + pSocket.SetSocketOption(System.Net.Sockets.SocketOptionLevel.Socket, SocketOptionName.SendBuffer, KBEngineApp.app.getInitArgs().getTCPSendBufferSize() * 2); + pSocket.NoDelay = true; + //pSocket.Blocking = false; + return pSocket; + } + + protected override PacketReceiverBase createPacketReceiver() + { + return new PacketReceiverTCP(this); + } + + protected override PacketSenderBase createPacketSender() + { + return new PacketSenderTCP(this); + } + + protected override void onAsyncConnect(ConnectState state) + { + try + { + state.socket.Connect(state.connectIP, state.connectPort); + } + catch (Exception e) + { + Dbg.ERROR_MSG(string.Format("NetworkInterfaceTCP::_asyncConnect(), connect to '{0}:{1}' fault! error = '{2}'", state.connectIP, state.connectPort, e)); + state.error = e.ToString(); + } + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceTCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceTCP.cs.meta new file mode 100644 index 00000000..cb88f5fb --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/NetworkInterfaceTCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0e0383fe75c02e746992acc6c45efb0c +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ObjectPool.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ObjectPool.cs new file mode 100644 index 00000000..9d77e7ee --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ObjectPool.cs @@ -0,0 +1,44 @@ +using UnityEngine; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Threading; + + +namespace KBEngine +{ + /// + /// 简单的对象池 + /// + /// 对象类型 + public class ObjectPool where T : new() + { + private static Stack _objects = new Stack(); + private static T v; + + public static T createObject() + { + lock (_objects) + { + if (_objects.Count > 0) + { + v = _objects.Pop(); + return v; + } + else + { + return new T(); + } + } + } + + public static void reclaimObject(T item) + { + lock (_objects) + { + _objects.Push(item); + } + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ObjectPool.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ObjectPool.cs.meta new file mode 100644 index 00000000..dd361d76 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ObjectPool.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 7195f5414262cbd48a325ddb65ec7986 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverBase.cs new file mode 100644 index 00000000..54f70100 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverBase.cs @@ -0,0 +1,62 @@ +namespace KBEngine +{ + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /* + 包接收模块(与服务端网络部分的名称对应) + 处理网络数据的接收 + */ + public abstract class PacketReceiverBase + { + public delegate void AsyncReceiveMethod(); + protected MessageReaderBase _messageReader = null; + protected NetworkInterfaceBase _networkInterface = null; + + public PacketReceiverBase(NetworkInterfaceBase networkInterface) + { + _networkInterface = networkInterface; + } + + ~PacketReceiverBase() + { + } + + public NetworkInterfaceBase networkInterface() + { + return _networkInterface; + } + + public abstract void process(); + + public virtual void startRecv() + { + AsyncReceiveMethod asyncReceiveMethod = new AsyncReceiveMethod(this._asyncReceive); + asyncReceiveMethod.BeginInvoke(new AsyncCallback(_onRecv), asyncReceiveMethod); + } + + protected abstract void _asyncReceive(); + + private void _onRecv(IAsyncResult ar) + { + try + { + AsyncReceiveMethod caller = (AsyncReceiveMethod)ar.AsyncState; + caller.EndInvoke(ar); + } + catch(ObjectDisposedException) + { + //通常出现这个错误, 是因为longin_baseapp时, networkInterface已经reset, _packetReceiver被置为null, 而之后刚好该回调被调用 + } + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverBase.cs.meta new file mode 100644 index 00000000..f7a1bbc5 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 26615527d652bca4b8cd9d1e144fb66a +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverKCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverKCP.cs new file mode 100644 index 00000000..d22685bc --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverKCP.cs @@ -0,0 +1,101 @@ +namespace KBEngine +{ + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + using MessageLengthEx = System.UInt32; + + /* + 包接收模块(与服务端网络部分的名称对应) + 处理网络数据的接收 + */ + public class PacketReceiverKCP : PacketReceiverBase + { + private byte[] _buffer; + private Deps.KCP kcp_ = null; + + public PacketReceiverKCP(NetworkInterfaceBase networkInterface) : base(networkInterface) + { + _buffer = new byte[MessageLength.MaxValue + (Deps.KCP.IKCP_OVERHEAD * 2)]; + _messageReader = new MessageReaderKCP(); + + kcp_ = ((NetworkInterfaceKCP)networkInterface).kcp(); + } + + ~PacketReceiverKCP() + { + kcp_ = null; + Dbg.DEBUG_MSG("PacketReceiverKCP::~PacketReceiverKCP(), destroyed!"); + } + + public override void process() + { + Socket socket = _networkInterface.sock(); + + while (socket.Available > 0) + { + int length = 0; + + try + { + length = socket.Receive(_buffer); + } + catch (Exception e) + { + Dbg.ERROR_MSG("PacketReceiverKCP::process: " + e.ToString()); + Event.fireIn("_closeNetwork", new object[] { _networkInterface }); + return; + } + + if (length <= 0) + { + Dbg.WARNING_MSG("PacketReceiverKCP::_asyncReceive(): KCP Receive <= 0!"); + return; + } + + ((NetworkInterfaceKCP)_networkInterface).nextTickKcpUpdate = 0; + if(kcp_.Input(_buffer, 0, length) < 0) + { + Dbg.WARNING_MSG(string.Format("PacketReceiverKCP::_asyncReceive(): KCP Input get {0}!", length)); + return; + } + + while (true) + { + length = kcp_.Recv(_buffer, 0, _buffer.Length); + if (length < 0) + { + break; + } + + if (_networkInterface.fileter() != null) + { + _networkInterface.fileter().recv(_messageReader, _buffer, 0, (MessageLengthEx)length); + } + else + { + _messageReader.process(_buffer, 0, (MessageLengthEx)length); + } + } + } + } + + public override void startRecv() + { + //var v = new AsyncReceiveMethod(this._asyncReceive); + //v.BeginInvoke(new AsyncCallback(_onRecv), null); + } + + protected override void _asyncReceive() + { + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverKCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverKCP.cs.meta new file mode 100644 index 00000000..8de8e1c7 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverKCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f9ee5825e49510349af2b1e721ec571b +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverTCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverTCP.cs new file mode 100644 index 00000000..7caf0e7c --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverTCP.cs @@ -0,0 +1,161 @@ +namespace KBEngine +{ + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /* + 包接收模块(与服务端网络部分的名称对应) + 处理网络数据的接收 + */ + public class PacketReceiverTCP : PacketReceiverBase + { + private byte[] _buffer; + + // socket向缓冲区写的起始位置 + int _wpos = 0; + + // 主线程读取数据的起始位置 + int _rpos = 0; + + public PacketReceiverTCP(NetworkInterfaceBase networkInterface) : base(networkInterface) + { + _buffer = new byte[KBEngineApp.app.getInitArgs().TCP_RECV_BUFFER_MAX]; + _messageReader = new MessageReaderTCP(); + } + + ~PacketReceiverTCP() + { + Dbg.DEBUG_MSG("PacketReceiverTCP::~PacketReceiverTCP(), destroyed!"); + } + + public override void process() + { + int t_wpos = Interlocked.Add(ref _wpos, 0); + + if (_rpos < t_wpos) + { + if (_networkInterface.fileter() != null) + { + _networkInterface.fileter().recv(_messageReader, _buffer, (UInt32)_rpos, (UInt32)(t_wpos - _rpos)); + } + else + { + _messageReader.process(_buffer, (UInt32)_rpos, (UInt32)(t_wpos - _rpos)); + } + + Interlocked.Exchange(ref _rpos, t_wpos); + } + else if (t_wpos < _rpos) + { + if (_networkInterface.fileter() != null) + { + _networkInterface.fileter().recv(_messageReader, _buffer, (UInt32)_rpos, (UInt32)(_buffer.Length - _rpos)); + _networkInterface.fileter().recv(_messageReader, _buffer, (UInt32)0, (UInt32)t_wpos); + } + else + { + _messageReader.process(_buffer, (UInt32)_rpos, (UInt32)(_buffer.Length - _rpos)); + _messageReader.process(_buffer, (UInt32)0, (UInt32)t_wpos); + } + + Interlocked.Exchange(ref _rpos, t_wpos); + } + else + { + // 没有可读数据 + } + } + + int _free() + { + int t_rpos = Interlocked.Add(ref _rpos, 0); + + if (_wpos == _buffer.Length) + { + if (t_rpos == 0) + { + return 0; + } + + Interlocked.Exchange(ref _wpos, 0); + } + + if (t_rpos <= _wpos) + { + return _buffer.Length - _wpos; + } + + return t_rpos - _wpos - 1; + } + + protected override void _asyncReceive() + { + if (_networkInterface == null || !_networkInterface.valid()) + { + Dbg.WARNING_MSG("PacketReceiverTCP::_asyncReceive(): network interface invalid!"); + return; + } + + var socket = _networkInterface.sock(); + + while (true) + { + // 必须有空间可写,否则我们阻塞在线程中直到有空间为止 + int first = 0; + int space = _free(); + + while (space == 0) + { + if (first > 0) + { + if (first > 1000) + { + Dbg.ERROR_MSG("PacketReceiverTCP::_asyncReceive(): no space!"); + Event.fireIn("_closeNetwork", new object[] { _networkInterface }); + return; + } + + Dbg.WARNING_MSG("PacketReceiverTCP::_asyncReceive(): waiting for space, Please adjust 'RECV_BUFFER_MAX'! retries=" + first); + System.Threading.Thread.Sleep(5); + } + + first += 1; + space = _free(); + } + + int bytesRead = 0; + try + { + bytesRead = socket.Receive(_buffer, _wpos, space, 0); + } + catch (SocketException se) + { + Dbg.ERROR_MSG(string.Format("PacketReceiverTCP::_asyncReceive(): receive error, disconnect from '{0}'! error = '{1}'", socket.RemoteEndPoint, se)); + Event.fireIn("_closeNetwork", new object[] { _networkInterface }); + return; + } + + if (bytesRead > 0) + { + // 更新写位置 + Interlocked.Add(ref _wpos, bytesRead); + } + else + { + Dbg.WARNING_MSG(string.Format("PacketReceiverTCP::_asyncReceive(): receive 0 bytes, disconnect from '{0}'!", socket.RemoteEndPoint)); + Event.fireIn("_closeNetwork", new object[] { _networkInterface }); + return; + } + } + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverTCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverTCP.cs.meta new file mode 100644 index 00000000..a5184972 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketReceiverTCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 9d9ebc916dceed448aabbcc244504a01 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderBase.cs new file mode 100644 index 00000000..6e8c2fc2 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderBase.cs @@ -0,0 +1,61 @@ +namespace KBEngine +{ + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /* + 包发送模块(与服务端网络部分的名称对应) + 处理网络数据的发送 + */ + public abstract class PacketSenderBase + { + public delegate void AsyncSendMethod(); + + protected NetworkInterfaceBase _networkInterface = null; + AsyncCallback _asyncCallback = null; + AsyncSendMethod _asyncSendMethod; + + public PacketSenderBase(NetworkInterfaceBase networkInterface) + { + _networkInterface = networkInterface; + _asyncSendMethod = new AsyncSendMethod(this._asyncSend); + _asyncCallback = new AsyncCallback(_onSent); + } + + ~PacketSenderBase() + { + } + + public NetworkInterfaceBase networkInterface() + { + return _networkInterface; + } + + public abstract bool send(MemoryStream stream); + + protected void _startSend() + { + // 由于socket用的是非阻塞式,因此在这里不能直接使用socket.send()方法 + // 必须放到另一个线程中去做 + + _asyncSendMethod.BeginInvoke(_asyncCallback, _asyncSendMethod); + } + + protected abstract void _asyncSend(); + + protected static void _onSent(IAsyncResult ar) + { + AsyncSendMethod caller = (AsyncSendMethod)ar.AsyncState; + caller.EndInvoke(ar); + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderBase.cs.meta new file mode 100644 index 00000000..c22505a5 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 31463b5131a461c4b8be6da64d653eb4 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderKCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderKCP.cs new file mode 100644 index 00000000..c0e26b37 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderKCP.cs @@ -0,0 +1,77 @@ +namespace KBEngine +{ + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /* + 包发送模块(与服务端网络部分的名称对应) + 处理网络数据的发送 + */ + public class PacketSenderKCP : PacketSenderBase + { + Socket socket_; + EndPoint remoteEndPint_; + + public PacketSenderKCP(NetworkInterfaceBase networkInterface) : base(networkInterface) + { + socket_ = _networkInterface.sock(); + remoteEndPint_ = ((NetworkInterfaceKCP)_networkInterface).remoteEndPint; + } + + ~PacketSenderKCP() + { + Dbg.DEBUG_MSG("PacketSenderKCP::~PacketSenderKCP(), destroyed!"); + } + + public override bool send(MemoryStream stream) + { + //MemoryStream udpPacket = MemoryStream.createObject(); + //udpPacket.swap(stream); + return true; + } + + public bool sendto(byte[] packet, int size) + { + try + { + socket_.SendTo(packet, size, SocketFlags.None, remoteEndPint_); + } + catch (SocketException se) + { + Dbg.ERROR_MSG(string.Format("PacketSenderKCP::sendto(): send data error, disconnect from '{0}'! error = '{1}'", socket_.RemoteEndPoint, se)); + Event.fireIn("_closeNetwork", new object[] { _networkInterface }); + return false; + } + + return true; + } + + protected override void _asyncSend() + { + /* + if (_networkInterface == null || !_networkInterface.valid()) + { + Dbg.WARNING_MSG("PacketSenderKCP::_asyncSend(): network interface invalid!"); + return; + } + + var socket = _networkInterface.sock(); + EndPoint remoteEndPint = ((NetworkInterfaceKCP)_networkInterface).remoteEndPint; + + while (true) + { + socket.SendTo(data, size, SocketFlags.None, remoteEndPint); + } + */ + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderKCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderKCP.cs.meta new file mode 100644 index 00000000..27796e01 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderKCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: a7ceceeab28e1ab4688c274fcfaf5e20 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderTCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderTCP.cs new file mode 100644 index 00000000..3cb1e278 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderTCP.cs @@ -0,0 +1,156 @@ +namespace KBEngine +{ + using System; + using System.Net.Sockets; + using System.Net; + using System.Collections; + using System.Collections.Generic; + using System.Text; + using System.Text.RegularExpressions; + using System.Threading; + + using MessageID = System.UInt16; + using MessageLength = System.UInt16; + + /* + 包发送模块(与服务端网络部分的名称对应) + 处理网络数据的发送 + */ + public class PacketSenderTCP : PacketSenderBase + { + private byte[] _buffer; + + int _wpos = 0; // 写入的数据位置 + int _spos = 0; // 发送完毕的数据位置 + + object _sendingObj = new object(); + Boolean _sending = false; + + public PacketSenderTCP(NetworkInterfaceBase networkInterface) : base(networkInterface) + { + _buffer = new byte[KBEngineApp.app.getInitArgs().TCP_SEND_BUFFER_MAX]; + + _wpos = 0; + _spos = 0; + _sending = false; + } + + ~PacketSenderTCP() + { + Dbg.DEBUG_MSG("PacketSenderTCP::~PacketSenderTCP(), destroyed!"); + } + + public override bool send(MemoryStream stream) + { + int dataLength = (int)stream.length(); + if (dataLength <= 0) + return true; + + Monitor.Enter(_sendingObj); + if (!_sending) + { + if (_wpos == _spos) + { + _wpos = 0; + _spos = 0; + } + } + + int t_spos =_spos; + int space = 0; + int tt_wpos = _wpos % _buffer.Length; + int tt_spos = t_spos % _buffer.Length; + + if(tt_wpos >= tt_spos) + space = _buffer.Length - tt_wpos + tt_spos - 1; + else + space = tt_spos - tt_wpos - 1; + + if (dataLength > space) + { + Dbg.ERROR_MSG("PacketSenderTCP::send(): no space, Please adjust 'SEND_BUFFER_MAX'! data(" + dataLength + + ") > space(" + space + "), wpos=" + _wpos + ", spos=" + t_spos); + + return false; + } + + int expect_total = tt_wpos + dataLength; + if(expect_total <= _buffer.Length) + { + Array.Copy(stream.data(), stream.rpos, _buffer, tt_wpos, dataLength); + } + else + { + int remain = _buffer.Length - tt_wpos; + Array.Copy(stream.data(), stream.rpos, _buffer, tt_wpos, remain); + Array.Copy(stream.data(), stream.rpos + remain, _buffer, 0, expect_total - _buffer.Length); + } + + _wpos += dataLength; + + if (!_sending) + { + _sending = true; + Monitor.Exit(_sendingObj); + + _startSend(); + } + else + { + Monitor.Exit(_sendingObj); + } + + return true; + } + + protected override void _asyncSend() + { + if (_networkInterface == null || !_networkInterface.valid()) + { + Dbg.WARNING_MSG("PacketSenderTCP::_asyncSend(): network interface invalid!"); + return; + } + + var socket = _networkInterface.sock(); + + while (true) + { + Monitor.Enter(_sendingObj); + + int sendSize = _wpos - _spos; + int t_spos = _spos % _buffer.Length; + if (t_spos == 0) + t_spos = sendSize; + + if (sendSize > _buffer.Length - t_spos) + sendSize = _buffer.Length - t_spos; + + int bytesSent = 0; + try + { + bytesSent = socket.Send(_buffer, _spos % _buffer.Length, sendSize, 0); + } + catch (SocketException se) + { + Dbg.ERROR_MSG(string.Format("PacketSenderTCP::_asyncSend(): send data error, disconnect from '{0}'! error = '{1}'", socket.RemoteEndPoint, se)); + Event.fireIn("_closeNetwork", new object[] { _networkInterface }); + + Monitor.Exit(_sendingObj); + return; + } + + _spos += bytesSent; + + // 所有数据发送完毕了 + if (_spos == _wpos) + { + _sending = false; + Monitor.Exit(_sendingObj); + return; + } + + Monitor.Exit(_sendingObj); + } + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderTCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderTCP.cs.meta new file mode 100644 index 00000000..2cbb6160 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/PacketSenderTCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 20a3d2aeecd2cc04883ba9ed72f643b8 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Profile.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Profile.cs new file mode 100644 index 00000000..9f2e4173 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Profile.cs @@ -0,0 +1,39 @@ +using System; +using System.Net.Sockets; +using System.Net; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; + +namespace KBEngine +{ + public class Profile + { + System.DateTime startTime; + string _name = ""; + + public Profile(string name) + { + _name = name; + } + + ~Profile() + { + } + + public void start() + { + startTime = System.DateTime.Now; + } + + public void end() + { + System.TimeSpan time = System.DateTime.Now - startTime; + + if(time.TotalMilliseconds >= 100) + Dbg.WARNING_MSG("Profile::profile(): '" + _name + "' took " + time.TotalMilliseconds + " ms"); + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Profile.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Profile.cs.meta new file mode 100644 index 00000000..9d32f690 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Profile.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 8c22d139d303b4e4aa1bd1f77db4f3a8 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Property.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Property.cs new file mode 100644 index 00000000..499781d3 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Property.cs @@ -0,0 +1,55 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + + /* + 抽象出一个entitydef中定义的属性 + 该模块描述了属性的id以及数据类型等信息 + */ + public class Property + { + public enum EntityDataFlags + { + ED_FLAG_UNKOWN = 0x00000000, // 未定义 + ED_FLAG_CELL_PUBLIC = 0x00000001, // 相关所有cell广播 + ED_FLAG_CELL_PRIVATE = 0x00000002, // 当前cell + ED_FLAG_ALL_CLIENTS = 0x00000004, // cell广播与所有客户端 + ED_FLAG_CELL_PUBLIC_AND_OWN = 0x00000008, // cell广播与自己的客户端 + ED_FLAG_OWN_CLIENT = 0x00000010, // 当前cell和客户端 + ED_FLAG_BASE_AND_CLIENT = 0x00000020, // base和客户端 + ED_FLAG_BASE = 0x00000040, // 当前base + ED_FLAG_OTHER_CLIENTS = 0x00000080, // cell广播和其他客户端 + }; + + public string name = ""; + public UInt16 properUtype = 0; + public UInt32 properFlags = 0; + public Int16 aliasID = -1; + public object defaultVal = null; + + public Property() + { + + } + + public bool isBase() + { + return properFlags == (UInt32)EntityDataFlags.ED_FLAG_BASE_AND_CLIENT || + properFlags == (UInt32)EntityDataFlags.ED_FLAG_BASE; + } + + public bool isOwnerOnly() + { + return properFlags == (UInt32)EntityDataFlags.ED_FLAG_CELL_PUBLIC_AND_OWN || + properFlags == (UInt32)EntityDataFlags.ED_FLAG_OWN_CLIENT; + } + + public bool isOtherOnly() + { + return properFlags == (UInt32)EntityDataFlags.ED_FLAG_OTHER_CLIENTS || + properFlags == (UInt32)EntityDataFlags.ED_FLAG_OTHER_CLIENTS; + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Property.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Property.cs.meta new file mode 100644 index 00000000..0c07f31c --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/Property.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d46f82469529d6f409b05a27df8ead1a +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/README.md b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/README.md new file mode 100644 index 00000000..269cb81c --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/README.md @@ -0,0 +1,365 @@ +kbengine_unity3d_plugins +======================== + +Usage +--------------------- + + 1: Generate client plugins through projects + 1: Double click to run kbengine\*assets\gensdk.bat + 2: Copy kbengine_unity3d_plugins to {UnityProjectName}\Assets\Plugins + + 2: Create clientapp.cs + using KBEngine; + public class clientapp : KBEMain + { + } + + 3: Implment the KBE defined entity (including the client part) + See: kbengine\kbengine_demos_assets\scripts\entities.xml->hasClient="true" need to implment + + + + + + public class Account : AccountBase + { + // entity initialization + public override void __init__() + { + } + } + + Call entity server method + Account.cs: baseEntityCall.reqAvatarList(); + Avatar.cs: cellEntityCall.relive(reliveType); + + Reference: https://github.com/kbengine/kbengine/issues/532 + + 4: Monitor KBE-plugins event + For example: + public class UI : MonoBehaviour + { + void Start () + { + KBEngine.Event.registerOut("onConnectionState", this, "onConnectionState"); + } + + public void onConnectionState(bool success) + { + // KBE-plugins event fired + } + } + + 5: Fire events to the KBE-plugins + For example: + KBEngine.Event.fireIn("login", "stringAccount", "stringPasswd", System.Text.Encoding.UTF8.GetBytes("kbengine_unity3d_demo")); + + + +KBE-Plugin fire-out events(KBE => Unity): +--------------------- + + Entity events: + onEnterWorld + Description: + Entity enter the client-world. + + Event-datas: + Enity + + + onLeaveWorld + Description: + Entity leave the client-world. + + Event-datas: + Enity + + onEnterSpace + Description: + Player enter the new space. + + Event-datas: + Enity + + onLeaveSpace + Description: + Player enter the space. + + Event-datas: + Enity + + onCreateAccountResult + Description: + Create account feedback results. + + Event-datas: + uint16: retcode + http://kbengine.org/docs/configuration/server_errors.html + + bytes: datas + If you use third-party account system, the system may fill some of the third-party additional datas. + + onControlled + Description: + Triggered when the entity is controlled or out of control. + + Event-datas: + Enity + bool: isControlled + + onLoseControlledEntity + Description: + Lose controlled entity. + + Event-datas: + Enity + + set_position + Description: + Sets the current position of the entity. + + Event-datas: + Enity + + set_direction + Description: + Sets the current direction of the entity. + + Event-datas: + Enity + + updatePosition + Description: + The entity position is updated, you can smooth the moving entity to new location. + + Event-datas: + Enity + + Protocol events: + onVersionNotMatch + Description: + Engine version mismatch. + + Event-datas: + string: clientVersion + string: serverVersion + + onScriptVersionNotMatch + Description: + script version mismatch. + + Event-datas: + string: clientScriptVersion + string: serverScriptVersion + + Loginapp_importClientMessages + Description: + Importing the message protocol for loginapp and client. + + Event-datas: + No datas. + + Baseapp_importClientMessages + Description: + Importing the message protocol for baseapp and client. + + Event-datas: + No datas. + + Baseapp_importClientEntityDef + Description: + Protocol description for importing entities. + + Event-datas: + No datas. + + Login and Logout status: + onLoginBaseapp + Description: + Login to baseapp. + + Event-datas: + No datas. + + onReloginBaseapp + Description: + Relogin to baseapp. + + Event-datas: + No datas. + + onKicked + Description: + Kicked of the current server. + + Event-datas: + uint16: retcode + http://kbengine.org/docs/configuration/server_errors.html + + onLoginFailed + Description: + Login failed. + + Event-datas: + uint16: retcode + bytes: serverdatas + http://kbengine.org/docs/configuration/server_errors.html + + onLoginBaseappFailed + Description: + Login baseapp failed. + + Event-datas: + uint16: retcode + http://kbengine.org/docs/configuration/server_errors.html + + onReloginBaseappFailed + Description: + Relogin baseapp failed. + + Event-datas: + uint16: retcode + http://kbengine.org/docs/configuration/server_errors.html + + onReloginBaseappSuccessfully + Description: + Relogin baseapp success. + + Event-datas: + No datas. + + Space events: + addSpaceGeometryMapping + Description: + The current space is specified by the geometry mapping. + Popular said is to load the specified Map Resources. + + Event-datas: + string: resPath + + onSetSpaceData + Description: + Server spaceData set data. + + Event-datas: + int32: spaceID + string: key + string value + + onDelSpaceData + Description: + Server spaceData delete data. + + Event-datas: + int32: spaceID + string: key + + Network events: + onConnectionState + Description: + Status of connection server. + + Event-datas: + bool: success or fail + + onDisconnected + Description: + Status of connection server. + + Event-datas: + No datas. + + Download events: + onStreamDataStarted + Description: + Start downloading data. + + Event-datas: + uint16: resouce id + uint32: data size + string: description + + onStreamDataRecv + Description: + Receive data. + + Event-datas: + uint16: resouce id + bytes: datas + + onStreamDataCompleted + Description: + The downloaded data is completed. + + Event-datas: + uint16: resouce id + + + +KBE-Plugin fire-in events(Unity => KBE): +--------------------- + + createAccount + Description: + Create new account. + + Event-datas: + string: accountName + string: password + bytes: datas + Datas by user defined. + Data will be recorded into the KBE account database, you can access the datas through the script layer. + If you use third-party account system, datas will be submitted to the third-party system. + + login + Description: + Login to server. + + Event-datas: + string: accountName + string: password + bytes: datas + Datas by user defined. + Data will be recorded into the KBE account database, you can access the datas through the script layer. + If you use third-party account system, datas will be submitted to the third-party system. + + logout + Description: + Logout to baseapp, called when exiting the client. + + Event-datas: + No datas. + + reloginBaseapp + Description: + Relogin to baseapp. + + Event-datas: + No datas. + + resetPassword + Description: + Reset password. + + Event-datas: + string: accountName + + newPassword + Description: + Request to set up a new password for the account. + Note: account must be online + + Event-datas: + string: old_password + string: new_password + + bindAccountEmail + Description: + Request server binding account Email. + Note: account must be online + + Event-datas: + string: emailAddress + + diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/README.md.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/README.md.meta new file mode 100644 index 00000000..914dd6e0 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/README.md.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 35d8c19bdd407cd42b038bb4b47d5b86 +timeCreated: 1531901400 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ScriptModule.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ScriptModule.cs new file mode 100644 index 00000000..d1931651 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ScriptModule.cs @@ -0,0 +1,56 @@ +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + using System.Reflection; + + /* + 一个entitydef中定义的脚本模块的描述类 + 包含了某个entity定义的属性与方法以及该entity脚本模块的名称与模块ID + */ + public class ScriptModule + { + public string name; + public bool usePropertyDescrAlias; + public bool useMethodDescrAlias; + + public Dictionary propertys = new Dictionary(); + public Dictionary idpropertys = new Dictionary(); + + public Dictionary methods = new Dictionary(); + public Dictionary base_methods = new Dictionary(); + public Dictionary cell_methods = new Dictionary(); + + public Dictionary idmethods = new Dictionary(); + public Dictionary idbase_methods = new Dictionary(); + public Dictionary idcell_methods = new Dictionary(); + + public Type entityScript = null; + + public ScriptModule(string modulename) + { + name = modulename; + + foreach (System.Reflection.Assembly ass in AppDomain.CurrentDomain.GetAssemblies()) + { + entityScript = ass.GetType("KBEngine." + modulename); + if(entityScript == null) + { + entityScript = ass.GetType(modulename); + } + + if(entityScript != null) + break; + } + + usePropertyDescrAlias = false; + useMethodDescrAlias = false; + + if(entityScript == null) + Dbg.ERROR_MSG("can't load(KBEngine." + modulename + ")!"); + } + } + +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ScriptModule.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ScriptModule.cs.meta new file mode 100644 index 00000000..049e0504 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ScriptModule.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e18ad8026708a0445b3b6022d78cdad3 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ServerErrorDescrs.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ServerErrorDescrs.cs new file mode 100644 index 00000000..75092d29 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ServerErrorDescrs.cs @@ -0,0 +1,401 @@ +/* + Generated by KBEngine! + Please do not modify this file! + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + public struct ServerErr + { + public string name; + public string descr; + public UInt16 id; + } + + // defined in */res/server/server_errors.xml + + public class ServerErrorDescrs + { + public static Dictionary serverErrs = new Dictionary(); + + public ServerErrorDescrs() + { + { + ServerErr e; + e.id = 0; + e.name = "SUCCESS"; + e.descr = "成功。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 1; + e.name = "SERVER_ERR_SRV_NO_READY"; + e.descr = "服务器没有准备好。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 2; + e.name = "SERVER_ERR_SRV_OVERLOAD"; + e.descr = "服务器负载过重。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 3; + e.name = "SERVER_ERR_ILLEGAL_LOGIN"; + e.descr = "非法登录。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 4; + e.name = "SERVER_ERR_NAME_PASSWORD"; + e.descr = "用户名或者密码不正确。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 5; + e.name = "SERVER_ERR_NAME"; + e.descr = "用户名不正确。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 6; + e.name = "SERVER_ERR_PASSWORD"; + e.descr = "密码不正确。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 7; + e.name = "SERVER_ERR_ACCOUNT_CREATE_FAILED"; + e.descr = "创建账号失败。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 8; + e.name = "SERVER_ERR_BUSY"; + e.descr = "操作过于繁忙(例如:在服务器前一次请求未执行完毕的情况下连续N次创建账号)。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 9; + e.name = "SERVER_ERR_ACCOUNT_LOGIN_ANOTHER"; + e.descr = "当前账号在另一处登录了。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 10; + e.name = "SERVER_ERR_ACCOUNT_IS_ONLINE"; + e.descr = "账号已登陆。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 11; + e.name = "SERVER_ERR_PROXY_DESTROYED"; + e.descr = "与客户端关联的proxy在服务器上已经销毁。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 12; + e.name = "SERVER_ERR_ENTITYDEFS_NOT_MATCH"; + e.descr = "EntityDefs不匹配。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 13; + e.name = "SERVER_ERR_SERVER_IN_SHUTTINGDOWN"; + e.descr = "服务器正在关闭中。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 14; + e.name = "SERVER_ERR_NAME_MAIL"; + e.descr = "Email地址错误。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 15; + e.name = "SERVER_ERR_ACCOUNT_LOCK"; + e.descr = "账号被冻结。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 16; + e.name = "SERVER_ERR_ACCOUNT_DEADLINE"; + e.descr = "账号已过期。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 17; + e.name = "SERVER_ERR_ACCOUNT_NOT_ACTIVATED"; + e.descr = "账号未激活。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 18; + e.name = "SERVER_ERR_VERSION_NOT_MATCH"; + e.descr = "与服务端的版本不匹配。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 19; + e.name = "SERVER_ERR_OP_FAILED"; + e.descr = "操作失败。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 20; + e.name = "SERVER_ERR_SRV_STARTING"; + e.descr = "服务器正在启动中。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 21; + e.name = "SERVER_ERR_ACCOUNT_REGISTER_NOT_AVAILABLE"; + e.descr = "未开放账号注册功能。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 22; + e.name = "SERVER_ERR_CANNOT_USE_MAIL"; + e.descr = "不能使用email地址。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 23; + e.name = "SERVER_ERR_NOT_FOUND_ACCOUNT"; + e.descr = "找不到此账号。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 24; + e.name = "SERVER_ERR_DB"; + e.descr = "数据库错误(请检查dbmgr日志和DB)。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 25; + e.name = "SERVER_ERR_USER1"; + e.descr = "用户自定义错误码1。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 26; + e.name = "SERVER_ERR_USER2"; + e.descr = "用户自定义错误码2。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 27; + e.name = "SERVER_ERR_USER3"; + e.descr = "用户自定义错误码3。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 28; + e.name = "SERVER_ERR_USER4"; + e.descr = "用户自定义错误码4。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 29; + e.name = "SERVER_ERR_USER5"; + e.descr = "用户自定义错误码5。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 30; + e.name = "SERVER_ERR_USER6"; + e.descr = "用户自定义错误码6。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 31; + e.name = "SERVER_ERR_USER7"; + e.descr = "用户自定义错误码7。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 32; + e.name = "SERVER_ERR_USER8"; + e.descr = "用户自定义错误码8。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 33; + e.name = "SERVER_ERR_USER9"; + e.descr = "用户自定义错误码9。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 34; + e.name = "SERVER_ERR_USER10"; + e.descr = "用户自定义错误码10。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 35; + e.name = "SERVER_ERR_LOCAL_PROCESSING"; + e.descr = "本地处理,通常为某件事情不由第三方处理而是由KBE服务器处理。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 36; + e.name = "SERVER_ERR_ACCOUNT_RESET_PASSWORD_NOT_AVAILABLE"; + e.descr = "未开放账号重置密码功能。"; + + serverErrs.Add(e.id, e); + } + + { + ServerErr e; + e.id = 37; + e.name = "SERVER_ERR_ACCOUNT_LOGIN_ANOTHER_SERVER"; + e.descr = "当前账号在其他服务器登陆了。"; + + serverErrs.Add(e.id, e); + } + + + } + + public void Clear() + { + serverErrs.Clear(); + } + + public string serverErrStr(UInt16 id) + { + ServerErr e; + if(!serverErrs.TryGetValue(id, out e)) + { + return ""; + } + + return e.name + "[" + e.descr + "]"; + } + + public ServerErr serverErr(UInt16 id) + { + ServerErr e; + serverErrs.TryGetValue(id, out e); + return e; + } + + + + + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ServerErrorDescrs.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ServerErrorDescrs.cs.meta new file mode 100644 index 00000000..d47ca29d --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/ServerErrorDescrs.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 451557aebf8ad124fa57c504c376499f +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceBase.cs new file mode 100644 index 00000000..329ae9ab --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceBase.cs @@ -0,0 +1,447 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class Space : SpaceBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Space.def + // Please inherit and implement "class Space : SpaceBase" + public abstract class SpaceBase : Entity + { + public EntityBaseEntityCall_SpaceBase baseEntityCall = null; + public EntityCellEntityCall_SpaceBase cellEntityCall = null; + + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + + public SpaceBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_SpaceBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_SpaceBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Space"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Space"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["Space"]; + Dictionary pdatas = sm.idpropertys; + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[4]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[5]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[6]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[7]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[8]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceBase.cs.meta new file mode 100644 index 00000000..7dbee0e2 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6365dd5c0940695498a2cc1c6ac12edb +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceDuplicateBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceDuplicateBase.cs new file mode 100644 index 00000000..73361046 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceDuplicateBase.cs @@ -0,0 +1,447 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class SpaceDuplicate : SpaceDuplicateBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/SpaceDuplicate.def + // Please inherit and implement "class SpaceDuplicate : SpaceDuplicateBase" + public abstract class SpaceDuplicateBase : Entity + { + public EntityBaseEntityCall_SpaceDuplicateBase baseEntityCall = null; + public EntityCellEntityCall_SpaceDuplicateBase cellEntityCall = null; + + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + + public SpaceDuplicateBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_SpaceDuplicateBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_SpaceDuplicateBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["SpaceDuplicate"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["SpaceDuplicate"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["SpaceDuplicate"]; + Dictionary pdatas = sm.idpropertys; + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[4]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[5]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[6]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[7]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[8]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceDuplicateBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceDuplicateBase.cs.meta new file mode 100644 index 00000000..8961f7b8 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpaceDuplicateBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 2b5a9c493ba683443bb8deb3ff0186fd +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpacesBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpacesBase.cs new file mode 100644 index 00000000..51da96cb --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpacesBase.cs @@ -0,0 +1,447 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class Spaces : SpacesBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Spaces.def + // Please inherit and implement "class Spaces : SpacesBase" + public abstract class SpacesBase : Entity + { + public EntityBaseEntityCall_SpacesBase baseEntityCall = null; + public EntityCellEntityCall_SpacesBase cellEntityCall = null; + + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + + public SpacesBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_SpacesBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_SpacesBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Spaces"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Spaces"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["Spaces"]; + Dictionary pdatas = sm.idpropertys; + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[4]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[5]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[6]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[7]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[8]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpacesBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpacesBase.cs.meta new file mode 100644 index 00000000..a754b79a --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpacesBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 75df76f2e6b3c0444a58f6560fc2d8ac +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpawnPointBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpawnPointBase.cs new file mode 100644 index 00000000..8206c575 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpawnPointBase.cs @@ -0,0 +1,447 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class SpawnPoint : SpawnPointBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/SpawnPoint.def + // Please inherit and implement "class SpawnPoint : SpawnPointBase" + public abstract class SpawnPointBase : Entity + { + public EntityBaseEntityCall_SpawnPointBase baseEntityCall = null; + public EntityCellEntityCall_SpawnPointBase cellEntityCall = null; + + public UInt32 modelID = 0; + public virtual void onModelIDChanged(UInt32 oldValue) {} + public Byte modelScale = 30; + public virtual void onModelScaleChanged(Byte oldValue) {} + public string name = ""; + public virtual void onNameChanged(string oldValue) {} + public UInt32 uid = 0; + public virtual void onUidChanged(UInt32 oldValue) {} + public UInt32 utype = 0; + public virtual void onUtypeChanged(UInt32 oldValue) {} + + + public SpawnPointBase() + { + } + + public override void onComponentsEnterworld() + { + } + + public override void onComponentsLeaveworld() + { + } + + public override void onGetBase() + { + baseEntityCall = new EntityBaseEntityCall_SpawnPointBase(id, className); + } + + public override void onGetCell() + { + cellEntityCall = new EntityCellEntityCall_SpawnPointBase(id, className); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override EntityCall getBaseEntityCall() + { + return baseEntityCall; + } + + public override EntityCall getCellEntityCall() + { + return cellEntityCall; + } + + public override void attachComponents() + { + } + + public override void detachComponents() + { + } + + public override void onRemoteMethodCall(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["SpawnPoint"]; + + UInt16 methodUtype = 0; + UInt16 componentPropertyUType = 0; + + if(sm.usePropertyDescrAlias) + { + componentPropertyUType = stream.readUint8(); + } + else + { + componentPropertyUType = stream.readUint16(); + } + + if(sm.useMethodDescrAlias) + { + methodUtype = stream.readUint8(); + } + else + { + methodUtype = stream.readUint16(); + } + + Method method = null; + + if(componentPropertyUType == 0) + { + method = sm.idmethods[methodUtype]; + } + else + { + Property pComponentPropertyDescription = sm.idpropertys[componentPropertyUType]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(method.methodUtype) + { + default: + break; + }; + } + + public override void onUpdatePropertys(MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["SpawnPoint"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = 0; + + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + if(_t_utype == 0) + { + prop = pdatas[_t_child_utype]; + } + else + { + Property pComponentPropertyDescription = pdatas[_t_utype]; + switch(pComponentPropertyDescription.properUtype) + { + default: + break; + } + + return; + } + + switch(prop.properUtype) + { + case 40001: + Vector3 oldval_direction = direction; + direction = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + onDirectionChanged(oldval_direction); + } + + break; + case 41006: + UInt32 oldval_modelID = modelID; + modelID = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + onModelIDChanged(oldval_modelID); + } + + break; + case 41007: + Byte oldval_modelScale = modelScale; + modelScale = stream.readUint8(); + + if(prop.isBase()) + { + if(inited) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + onModelScaleChanged(oldval_modelScale); + } + + break; + case 41003: + string oldval_name = name; + name = stream.readUnicode(); + + if(prop.isBase()) + { + if(inited) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + onNameChanged(oldval_name); + } + + break; + case 40000: + Vector3 oldval_position = position; + position = stream.readVector3(); + + if(prop.isBase()) + { + if(inited) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + onPositionChanged(oldval_position); + } + + break; + case 40002: + stream.readUint32(); + break; + case 41004: + UInt32 oldval_uid = uid; + uid = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + onUidChanged(oldval_uid); + } + + break; + case 41005: + UInt32 oldval_utype = utype; + utype = stream.readUint32(); + + if(prop.isBase()) + { + if(inited) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + onUtypeChanged(oldval_utype); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["SpawnPoint"]; + Dictionary pdatas = sm.idpropertys; + + Vector3 oldval_direction = direction; + Property prop_direction = pdatas[2]; + if(prop_direction.isBase()) + { + if(inited && !inWorld) + onDirectionChanged(oldval_direction); + } + else + { + if(inWorld) + { + if(prop_direction.isOwnerOnly() && !isPlayer()) + { + } + else + { + onDirectionChanged(oldval_direction); + } + } + } + + UInt32 oldval_modelID = modelID; + Property prop_modelID = pdatas[4]; + if(prop_modelID.isBase()) + { + if(inited && !inWorld) + onModelIDChanged(oldval_modelID); + } + else + { + if(inWorld) + { + if(prop_modelID.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelIDChanged(oldval_modelID); + } + } + } + + Byte oldval_modelScale = modelScale; + Property prop_modelScale = pdatas[5]; + if(prop_modelScale.isBase()) + { + if(inited && !inWorld) + onModelScaleChanged(oldval_modelScale); + } + else + { + if(inWorld) + { + if(prop_modelScale.isOwnerOnly() && !isPlayer()) + { + } + else + { + onModelScaleChanged(oldval_modelScale); + } + } + } + + string oldval_name = name; + Property prop_name = pdatas[6]; + if(prop_name.isBase()) + { + if(inited && !inWorld) + onNameChanged(oldval_name); + } + else + { + if(inWorld) + { + if(prop_name.isOwnerOnly() && !isPlayer()) + { + } + else + { + onNameChanged(oldval_name); + } + } + } + + Vector3 oldval_position = position; + Property prop_position = pdatas[1]; + if(prop_position.isBase()) + { + if(inited && !inWorld) + onPositionChanged(oldval_position); + } + else + { + if(inWorld) + { + if(prop_position.isOwnerOnly() && !isPlayer()) + { + } + else + { + onPositionChanged(oldval_position); + } + } + } + + UInt32 oldval_uid = uid; + Property prop_uid = pdatas[7]; + if(prop_uid.isBase()) + { + if(inited && !inWorld) + onUidChanged(oldval_uid); + } + else + { + if(inWorld) + { + if(prop_uid.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUidChanged(oldval_uid); + } + } + } + + UInt32 oldval_utype = utype; + Property prop_utype = pdatas[8]; + if(prop_utype.isBase()) + { + if(inited && !inWorld) + onUtypeChanged(oldval_utype); + } + else + { + if(inWorld) + { + if(prop_utype.isOwnerOnly() && !isPlayer()) + { + } + else + { + onUtypeChanged(oldval_utype); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpawnPointBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpawnPointBase.cs.meta new file mode 100644 index 00000000..f4867bb4 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/SpawnPointBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: bea9089d74f16cc489ce96d2fd67ae5a +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestBase.cs new file mode 100644 index 00000000..b446964b --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestBase.cs @@ -0,0 +1,188 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class Test : TestBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/Test.def + public abstract class TestBase : EntityComponent + { + public EntityBaseEntityCall_TestBase baseEntityCall = null; + public EntityCellEntityCall_TestBase cellEntityCall = null; + + public Int32 own = 1001; + public virtual void onOwnChanged(Int32 oldValue) {} + public Int32 state = 100; + public virtual void onStateChanged(Int32 oldValue) {} + + public abstract void helloCB(Int32 arg1); + + public override void createFromStream(MemoryStream stream) + { + base.createFromStream(stream); + } + + public override void onGetBase() + { + ownerID = owner.id; + baseEntityCall = new EntityBaseEntityCall_TestBase(entityComponentPropertyID, ownerID); + } + + public override void onGetCell() + { + ownerID = owner.id; + cellEntityCall = new EntityCellEntityCall_TestBase(entityComponentPropertyID, ownerID); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override ScriptModule getScriptModule() + { + return EntityDef.moduledefs["Test"]; + } + + public override void onRemoteMethodCall(UInt16 methodUtype, MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["Test"]; + + Method method = sm.idmethods[methodUtype]; + switch(method.methodUtype) + { + case 28: + Int32 helloCB_arg1 = stream.readInt32(); + helloCB(helloCB_arg1); + break; + default: + break; + }; + } + + public override void onUpdatePropertys(UInt16 propUtype, MemoryStream stream, int maxCount) + { + ScriptModule sm = EntityDef.moduledefs["Test"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0 && maxCount-- != 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = propUtype; + + if(_t_child_utype == 0) + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + prop = pdatas[_t_child_utype]; + + switch(prop.properUtype) + { + case 18: + Int32 oldval_own = own; + own = stream.readInt32(); + + if(prop.isBase()) + { + if(owner.inited) + onOwnChanged(oldval_own); + } + else + { + if(owner.inWorld) + onOwnChanged(oldval_own); + } + + break; + case 17: + Int32 oldval_state = state; + state = stream.readInt32(); + + if(prop.isBase()) + { + if(owner.inited) + onStateChanged(oldval_state); + } + else + { + if(owner.inWorld) + onStateChanged(oldval_state); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["Test"]; + Dictionary pdatas = sm.idpropertys; + + Int32 oldval_own = own; + Property prop_own = pdatas[4]; + if(prop_own.isBase()) + { + if(owner.inited && !owner.inWorld) + onOwnChanged(oldval_own); + } + else + { + if(owner.inWorld) + { + if(prop_own.isOwnerOnly() && !owner.isPlayer()) + { + } + else + { + onOwnChanged(oldval_own); + } + } + } + + Int32 oldval_state = state; + Property prop_state = pdatas[5]; + if(prop_state.isBase()) + { + if(owner.inited && !owner.inWorld) + onStateChanged(oldval_state); + } + else + { + if(owner.inWorld) + { + if(prop_state.isOwnerOnly() && !owner.isPlayer()) + { + } + else + { + onStateChanged(oldval_state); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestBase.cs.meta new file mode 100644 index 00000000..c3175c73 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0ffec40471ea0114384ec5d6161f6c69 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestNoBaseBase.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestNoBaseBase.cs new file mode 100644 index 00000000..cddf5afa --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestNoBaseBase.cs @@ -0,0 +1,188 @@ +/* + Generated by KBEngine! + Please do not modify this file! + Please inherit this module, such as: (class TestNoBase : TestNoBaseBase) + tools = kbcmd +*/ + +namespace KBEngine +{ + using UnityEngine; + using System; + using System.Collections; + using System.Collections.Generic; + + // defined in */scripts/entity_defs/TestNoBase.def + public abstract class TestNoBaseBase : EntityComponent + { + public EntityBaseEntityCall_TestNoBaseBase baseEntityCall = null; + public EntityCellEntityCall_TestNoBaseBase cellEntityCall = null; + + public Int32 own = 1001; + public virtual void onOwnChanged(Int32 oldValue) {} + public Int32 state = 100; + public virtual void onStateChanged(Int32 oldValue) {} + + public abstract void helloCB(Int32 arg1); + + public override void createFromStream(MemoryStream stream) + { + base.createFromStream(stream); + } + + public override void onGetBase() + { + ownerID = owner.id; + baseEntityCall = new EntityBaseEntityCall_TestNoBaseBase(entityComponentPropertyID, ownerID); + } + + public override void onGetCell() + { + ownerID = owner.id; + cellEntityCall = new EntityCellEntityCall_TestNoBaseBase(entityComponentPropertyID, ownerID); + } + + public override void onLoseCell() + { + cellEntityCall = null; + } + + public override ScriptModule getScriptModule() + { + return EntityDef.moduledefs["TestNoBase"]; + } + + public override void onRemoteMethodCall(UInt16 methodUtype, MemoryStream stream) + { + ScriptModule sm = EntityDef.moduledefs["TestNoBase"]; + + Method method = sm.idmethods[methodUtype]; + switch(method.methodUtype) + { + case 30: + Int32 helloCB_arg1 = stream.readInt32(); + helloCB(helloCB_arg1); + break; + default: + break; + }; + } + + public override void onUpdatePropertys(UInt16 propUtype, MemoryStream stream, int maxCount) + { + ScriptModule sm = EntityDef.moduledefs["TestNoBase"]; + Dictionary pdatas = sm.idpropertys; + + while(stream.length() > 0 && maxCount-- != 0) + { + UInt16 _t_utype = 0; + UInt16 _t_child_utype = propUtype; + + if(_t_child_utype == 0) + { + if(sm.usePropertyDescrAlias) + { + _t_utype = stream.readUint8(); + _t_child_utype = stream.readUint8(); + } + else + { + _t_utype = stream.readUint16(); + _t_child_utype = stream.readUint16(); + } + } + + Property prop = null; + + prop = pdatas[_t_child_utype]; + + switch(prop.properUtype) + { + case 24: + Int32 oldval_own = own; + own = stream.readInt32(); + + if(prop.isBase()) + { + if(owner.inited) + onOwnChanged(oldval_own); + } + else + { + if(owner.inWorld) + onOwnChanged(oldval_own); + } + + break; + case 23: + Int32 oldval_state = state; + state = stream.readInt32(); + + if(prop.isBase()) + { + if(owner.inited) + onStateChanged(oldval_state); + } + else + { + if(owner.inWorld) + onStateChanged(oldval_state); + } + + break; + default: + break; + }; + } + } + + public override void callPropertysSetMethods() + { + ScriptModule sm = EntityDef.moduledefs["TestNoBase"]; + Dictionary pdatas = sm.idpropertys; + + Int32 oldval_own = own; + Property prop_own = pdatas[4]; + if(prop_own.isBase()) + { + if(owner.inited && !owner.inWorld) + onOwnChanged(oldval_own); + } + else + { + if(owner.inWorld) + { + if(prop_own.isOwnerOnly() && !owner.isPlayer()) + { + } + else + { + onOwnChanged(oldval_own); + } + } + } + + Int32 oldval_state = state; + Property prop_state = pdatas[5]; + if(prop_state.isBase()) + { + if(owner.inited && !owner.inWorld) + onStateChanged(oldval_state); + } + else + { + if(owner.inWorld) + { + if(prop_state.isOwnerOnly() && !owner.isPlayer()) + { + } + else + { + onStateChanged(oldval_state); + } + } + } + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestNoBaseBase.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestNoBaseBase.cs.meta new file mode 100644 index 00000000..622b822c --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/TestNoBaseBase.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 282cff8120eddfc40ac6e6432ef75c91 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps.meta new file mode 100644 index 00000000..eb8656aa --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 6c7fd64fa742cb74a81d01733527ec53 +folderAsset: yes +timeCreated: 1531385543 +licenseType: Free +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps/KCP.cs b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps/KCP.cs new file mode 100644 index 00000000..0d0895d2 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps/KCP.cs @@ -0,0 +1,1166 @@ +// Copyright (C) 2017 ichenq@outlook.com. All rights reserved. +// Distributed under the terms and conditions of the MIT License. +// See accompanying files LICENSE. + +using System; +using System.Diagnostics; +using System.Collections.Generic; + +namespace Deps +{ + public class KCP + { + public class TimeUtils + { + private static readonly DateTime epoch = new DateTime(1970, 1, 1); + private static readonly DateTime twepoch = new DateTime(2000, 1, 1); + + public static UInt32 iclock() + { + var now = Convert.ToInt64(DateTime.Now.Subtract(twepoch).TotalMilliseconds); + return (UInt32)(now & 0xFFFFFFFF); + } + + public static Int64 LocalUnixTime() + { + return Convert.ToInt64(DateTime.Now.Subtract(epoch).TotalMilliseconds); + } + + // local datetime to unix timestamp + public static Int64 ToUnixTimestamp(DateTime t) + { + var timespan = t.ToUniversalTime().Subtract(epoch); + return (Int64)Math.Truncate(timespan.TotalSeconds); + } + } + + public const int IKCP_RTO_NDL = 30; // no delay min rto + public const int IKCP_RTO_MIN = 100; // normal min rto + public const int IKCP_RTO_DEF = 200; + public const int IKCP_RTO_MAX = 60000; + public const int IKCP_CMD_PUSH = 81; // cmd: push data + public const int IKCP_CMD_ACK = 82; // cmd: ack + public const int IKCP_CMD_WASK = 83; // cmd: window probe (ask) + public const int IKCP_CMD_WINS = 84; // cmd: window size (tell) + public const int IKCP_ASK_SEND = 1; // need to send IKCP_CMD_WASK + public const int IKCP_ASK_TELL = 2; // need to send IKCP_CMD_WINS + public const int IKCP_WND_SND = 32; + public const int IKCP_WND_RCV = 32; + public const int IKCP_MTU_DEF = 1400; + public const int IKCP_ACK_FAST = 3; + public const int IKCP_INTERVAL = 100; + public const int IKCP_OVERHEAD = 24; + public const int IKCP_DEADLINK = 20; + public const int IKCP_THRESH_INIT = 2; + public const int IKCP_THRESH_MIN = 2; + public const int IKCP_PROBE_INIT = 7000; // 7 secs to probe window size + public const int IKCP_PROBE_LIMIT = 120000; // up to 120 secs to probe window + + public const int IKCP_LOG_OUTPUT = 0x1; + public const int IKCP_LOG_INPUT = 0x2; + public const int IKCP_LOG_SEND = 0x4; + public const int IKCP_LOG_RECV = 0x8; + public const int IKCP_LOG_IN_DATA = 0x10; + public const int IKCP_LOG_IN_ACK = 0x20; + public const int IKCP_LOG_IN_PROBE = 0x40; + public const int IKCP_LOG_IN_WINS = 0x80; + public const int IKCP_LOG_OUT_DATA = 0x100; + public const int IKCP_LOG_OUT_ACK = 0x200; + public const int IKCP_LOG_OUT_PROBE = 0x400; + public const int IKCP_LOG_OUT_WINS = 0x800; + + + // encode 8 bits unsigned int + public static void ikcp_encode8u(byte[] p, int offset, byte c) + { + p[offset] = c; + } + + // decode 8 bits unsigned int + public static byte ikcp_decode8u(byte[] p, ref int offset) + { + return p[offset++]; + } + + // encode 16 bits unsigned int (lsb) + public static void ikcp_encode16u(byte[] p, int offset, UInt16 v) + { + p[offset] = (byte)(v & 0xFF); + p[offset + 1] = (byte)(v >> 8); + } + + // decode 16 bits unsigned int (lsb) + public static UInt16 ikcp_decode16u(byte[] p, ref int offset) + { + int pos = offset; + offset += 2; + return (UInt16)((UInt16)p[pos] | (UInt16)(p[pos + 1] << 8)); + } + + // encode 32 bits unsigned int (lsb) + public static void ikcp_encode32u(byte[] p, int offset, UInt32 l) + { + p[offset] = (byte)(l & 0xFF); + p[offset + 1] = (byte)(l >> 8); + p[offset + 2] = (byte)(l >> 16); + p[offset + 3] = (byte)(l >> 24); + } + + // decode 32 bits unsigned int (lsb) + public static UInt32 ikcp_decode32u(byte[] p, ref int offset) + { + int pos = offset; + offset += 4; + return ((UInt32)p[pos] | (UInt32)(p[pos + 1] << 8) + | (UInt32)(p[pos + 2] << 16) | (UInt32)(p[pos + 3] << 24)); + } + + public static UInt32 _imin_(UInt32 a, UInt32 b) + { + return a <= b ? a : b; + } + + public static UInt32 _imax_(UInt32 a, UInt32 b) + { + return a >= b ? a : b; + } + + public static UInt32 _ibound_(UInt32 lower, UInt32 middle, UInt32 upper) + { + return _imin_(_imax_(lower, middle), upper); + } + + public static Int32 _itimediff(UInt32 later, UInt32 earlier) + { + return (Int32)(later - earlier); + } + + internal class Segment + { + internal UInt32 conv = 0; + internal UInt32 cmd = 0; + internal UInt32 frg = 0; + internal UInt32 wnd = 0; + internal UInt32 ts = 0; + internal UInt32 sn = 0; + internal UInt32 una = 0; + internal UInt32 resendts = 0; + internal UInt32 rto = 0; + internal UInt32 faskack = 0; + internal UInt32 xmit = 0; + internal byte[] data; + + internal Segment(int size = 0) + { + data = new byte[size]; + } + + internal void Encode(byte[] ptr, ref int offset) + { + UInt32 len = (UInt32)data.Length; + ikcp_encode32u(ptr, offset, conv); + ikcp_encode8u(ptr, offset + 4, (byte)cmd); + ikcp_encode8u(ptr, offset + 5, (byte)frg); + ikcp_encode16u(ptr, offset + 6, (UInt16)wnd); + ikcp_encode32u(ptr, offset + 8, ts); + ikcp_encode32u(ptr, offset + 12, sn); + ikcp_encode32u(ptr, offset + 16, una); + ikcp_encode32u(ptr, offset + 20, len); + offset += IKCP_OVERHEAD; + } + + } + + UInt32 conv_ = 0; + UInt32 mtu_ = 0; + UInt32 mss_ = 0; + UInt32 state_ = 0; + + UInt32 snd_una_ = 0; + UInt32 snd_nxt_ = 0; + UInt32 rcv_nxt_ = 0; + + //UInt32 ts_recent_ = 0; + //UInt32 ts_lastack_ = 0; + UInt32 ssthresh_ = 0; + + Int32 rx_rttval_ = 0; + Int32 rx_srtt_ = 0; + Int32 rx_rto_ = 0; + Int32 rx_minrto_ = 0; + + UInt32 snd_wnd_ = 0; + UInt32 rcv_wnd_ = 0; + UInt32 rmt_wnd_ = 0; + UInt32 cwnd_ = 0; + UInt32 probe_ = 0; + + UInt32 current_ = 0; + UInt32 interval_ = 0; + UInt32 ts_flush_ = 0; + UInt32 xmit_ = 0; + + UInt32 nrcv_buf_ = 0; + UInt32 nsnd_buf_ = 0; + UInt32 nrcv_que_ = 0; + UInt32 nsnd_que_ = 0; + + UInt32 nodelay_ = 0; + UInt32 updated_ = 0; + UInt32 ts_probe_ = 0; + UInt32 probe_wait_ = 0; + UInt32 dead_link_ = 0; + UInt32 incr_ = 0; + + LinkedList snd_queue_; + LinkedList rcv_queue_; + LinkedList snd_buf_; + LinkedList rcv_buf_; + + UInt32[] acklist_; + UInt32 ackcount_ = 0; + UInt32 ackblock_ = 0; + + byte[] buffer_; + object user_; + + Int32 fastresend_ = 0; + Int32 nocwnd_ = 0; + + public delegate void OutputDelegate(byte[] data, int size, object user); + OutputDelegate output_; + + // create a new kcp control object, 'conv' must equal in two endpoint + // from the same connection. 'user' will be passed to the output callback + // output callback can be setup like this: 'kcp->output = my_udp_output' + public KCP(UInt32 conv, object user) + { + Debug.Assert(BitConverter.IsLittleEndian); // we only support little endian device + + user_ = user; + conv_ = conv; + snd_wnd_ = IKCP_WND_SND; + rcv_wnd_ = IKCP_WND_RCV; + rmt_wnd_ = IKCP_WND_RCV; + mtu_ = IKCP_MTU_DEF; + mss_ = mtu_ - IKCP_OVERHEAD; + rx_rto_ = IKCP_RTO_DEF; + rx_minrto_ = IKCP_RTO_MIN; + interval_ = IKCP_INTERVAL; + ts_flush_ = IKCP_INTERVAL; + ssthresh_ = IKCP_THRESH_INIT; + dead_link_ = IKCP_DEADLINK; + buffer_ = new byte[(mtu_ + IKCP_OVERHEAD) * 3]; + snd_queue_ = new LinkedList(); + rcv_queue_ = new LinkedList(); + snd_buf_ = new LinkedList(); + rcv_buf_ = new LinkedList(); + } + + // release kcp control object + public void Release() + { + snd_buf_.Clear(); + rcv_buf_.Clear(); + snd_queue_.Clear(); + rcv_queue_.Clear(); + nrcv_buf_ = 0; + nsnd_buf_ = 0; + nrcv_que_ = 0; + nsnd_que_ = 0; + ackblock_ = 0; + ackcount_ = 0; + buffer_ = null; + acklist_ = null; + } + + // set output callback, which will be invoked by kcp + public void SetOutput(OutputDelegate output) + { + output_ = output; + } + + // user/upper level recv: returns size, returns below zero for EAGAIN + public int Recv(byte[] buffer, int offset, int len) + { + int ispeek = (len < 0 ? 1 : 0); + int recover = 0; + + if (rcv_queue_.Count == 0) + return -1; + + if (len < 0) + len = -len; + + int peeksize = PeekSize(); + if (peeksize < 0) + return -2; + + if (peeksize > len) + return -3; + + if (nrcv_que_ >= rcv_wnd_) + recover = 1; + + // merge fragment + len = 0; + LinkedListNode next = null; + for (var node = rcv_queue_.First; node != null; node = next) + { + int fragment = 0; + var seg = node.Value; + next = node.Next; + + if (buffer != null) + { + Buffer.BlockCopy(seg.data, 0, buffer, offset, seg.data.Length); + offset += seg.data.Length; + } + len += seg.data.Length; + fragment = (int)seg.frg; + + Log(IKCP_LOG_RECV, "recv sn={0}", seg.sn); + + if (ispeek == 0) + { + rcv_queue_.Remove(node); + nrcv_que_--; + } + + if (fragment == 0) + break; + } + + Debug.Assert(len == peeksize); + + // move available data from rcv_buf -> rcv_queue + while (rcv_buf_.Count > 0) + { + var node = rcv_buf_.First; + var seg = node.Value; + if (seg.sn == rcv_nxt_ && nrcv_que_ < rcv_wnd_) + { + rcv_buf_.Remove(node); + nrcv_buf_--; + rcv_queue_.AddLast(node); + nrcv_que_++; + rcv_nxt_++; + } + else + { + break; + } + } + + // fast recover + if (nrcv_que_ < rcv_wnd_ && recover != 0) + { + // ready to send back IKCP_CMD_WINS in ikcp_flush + // tell remote my window size + probe_ |= IKCP_ASK_TELL; + } + + return len; + } + + // check the size of next message in the recv queue + public int PeekSize() + { + if (rcv_queue_.Count == 0) + return -1; + + var node = rcv_queue_.First; + var seg = node.Value; + if (seg.frg == 0) + return seg.data.Length; + + if (nrcv_que_ < seg.frg + 1) + return -1; + + int length = 0; + for (node = rcv_queue_.First; node != null; node = node.Next) + { + seg = node.Value; + length += seg.data.Length; + if (seg.frg == 0) + break; + } + return length; + } + + // user/upper level send, returns below zero for error + public int Send(byte[] buffer, int offset, int len) + { + Debug.Assert(mss_ > 0); + if (len < 0) + return -1; + + // + // not implement streaming mode here as ikcp.c + // + + int count = 0; + if (len <= (int)mss_) + count = 1; + else + count = (len + (int)mss_ - 1) / (int)mss_; + + if (count > 255) // maximum value `frg` can present + return -2; + + if (count == 0) + count = 1; + + // fragment + for (int i = 0; i < count; i++) + { + int size = len > (int)mss_ ? (int)mss_ : len; + var seg = new Segment(size); + if (buffer != null && len > 0) + { + Buffer.BlockCopy(buffer, offset, seg.data, 0, size); + offset += size; + } + seg.frg = (UInt32)(count - i - 1); + snd_queue_.AddLast(seg); + nsnd_que_++; + len -= size; + } + return 0; + } + + // parse ack + void UpdateACK(Int32 rtt) + { + if (rx_srtt_ == 0) + { + rx_srtt_ = rtt; + rx_rttval_ = rtt / 2; + } + else + { + Int32 delta = rtt - rx_srtt_; + if (delta < 0) + delta = -delta; + + rx_rttval_ = (3 * rx_rttval_ + delta) / 4; + rx_srtt_ = (7 * rx_srtt_ + rtt) / 8; + if (rx_srtt_ < 1) + rx_srtt_ = 1; + } + + var rto = rx_srtt_ + _imax_(interval_, (UInt32)(4 * rx_rttval_)); + rx_rto_ = (Int32)_ibound_((UInt32)rx_minrto_, (UInt32)rto, IKCP_RTO_MAX); + } + + void ShrinkBuf() + { + var node = snd_buf_.First; + if (node != null) + { + var seg = node.Value; + snd_una_ = seg.sn; + } + else + { + snd_una_ = snd_nxt_; + } + } + + void ParseACK(UInt32 sn) + { + if (_itimediff(sn, snd_una_) < 0 || _itimediff(sn, snd_nxt_) >= 0) + return; + + LinkedListNode next = null; + for (var node = snd_buf_.First; node != null; node = next) + { + var seg = node.Value; + next = node.Next; + if (sn == seg.sn) + { + snd_buf_.Remove(node); + nsnd_buf_--; + break; + } + if (_itimediff(sn, seg.sn) < 0) + break; + } + } + + void ParseUNA(UInt32 una) + { + LinkedListNode next = null; + for (var node = snd_buf_.First; node != null; node = next) + { + var seg = node.Value; + next = node.Next; + if (_itimediff(una, seg.sn) > 0) + { + snd_buf_.Remove(node); + nsnd_buf_--; + } + else + { + break; + } + } + } + + void ParseFastACK(UInt32 sn) + { + if (_itimediff(sn, snd_una_) < 0 || _itimediff(sn, snd_nxt_) >= 0) + return; + + LinkedListNode next = null; + for (var node = snd_buf_.First; node != null; node = next) + { + var seg = node.Value; + next = node.Next; + if (_itimediff(sn, seg.sn) < 0) + { + break; + } + else if (sn != seg.sn) + { + seg.faskack++; + } + } + } + + // ack append + void ACKPush(UInt32 sn, UInt32 ts) + { + var newsize = ackcount_ + 1; + if (newsize > ackblock_) + { + UInt32 newblock = 8; + for (; newblock < newsize; newblock <<= 1) + ; + + var acklist = new UInt32[newblock * 2]; + if (acklist_ != null) + { + for (var i = 0; i < ackcount_; i++) + { + acklist[i * 2] = acklist_[i * 2]; + acklist[i * 2 + 1] = acklist_[i * 2 + 1]; + } + } + acklist_ = acklist; + ackblock_ = newblock; + } + acklist_[ackcount_ * 2] = sn; + acklist_[ackcount_ * 2 + 1] = ts; + ackcount_++; + } + + void ACKGet(int pos, ref UInt32 sn, ref UInt32 ts) + { + sn = acklist_[pos * 2]; + ts = acklist_[pos * 2 + 1]; + } + + // parse data + void ParseData(Segment newseg) + { + UInt32 sn = newseg.sn; + int repeat = 0; + + if (_itimediff(sn, rcv_nxt_ + rcv_wnd_) >= 0 || + _itimediff(sn, rcv_nxt_) < 0) + { + return; + } + + LinkedListNode node = null; + LinkedListNode prev = null; + for (node = rcv_buf_.Last; node != null; node = prev) + { + var seg = node.Value; + prev = node.Previous; + if (seg.sn == sn) + { + repeat = 1; + break; + } + if (_itimediff(sn, seg.sn) > 0) + { + break; + } + } + if (repeat == 0) + { + if (node != null) + { + rcv_buf_.AddAfter(node, newseg); + } + else + { + rcv_buf_.AddFirst(newseg); + } + nrcv_buf_++; + } + + // move available data from rcv_buf -> rcv_queue + while (rcv_buf_.Count > 0) + { + node = rcv_buf_.First; + var seg = node.Value; + if (seg.sn == rcv_nxt_ && nrcv_que_ < rcv_wnd_) + { + rcv_buf_.Remove(node); + nrcv_buf_--; + rcv_queue_.AddLast(node); + nrcv_que_++; + rcv_nxt_++; + } + else + { + break; + } + } + } + + // when you received a low level packet (eg. UDP packet), call it + public int Input(byte[] data, int offset, int size) + { + UInt32 maxack = 0; + int flag = 0; + + Log(IKCP_LOG_INPUT, "[RI] {0} bytes", size); + + if (data == null || size < IKCP_OVERHEAD) + return -1; + + while (true) + { + if (size < IKCP_OVERHEAD) + break; + + UInt32 conv = ikcp_decode32u(data, ref offset); + if (conv_ != conv) + return -1; + UInt32 cmd = ikcp_decode8u(data, ref offset); + UInt32 frg = ikcp_decode8u(data, ref offset); + UInt32 wnd = ikcp_decode16u(data, ref offset); + UInt32 ts = ikcp_decode32u(data, ref offset); + UInt32 sn = ikcp_decode32u(data, ref offset); + UInt32 una = ikcp_decode32u(data, ref offset); + UInt32 len = ikcp_decode32u(data, ref offset); + + size -= IKCP_OVERHEAD; + if (size < len) + return -2; + + if (cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK && + cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS) + return -3; + + rmt_wnd_ = wnd; + ParseUNA(una); + ShrinkBuf(); + + if (cmd == IKCP_CMD_ACK) + { + if (_itimediff(current_, ts) >= 0) + { + UpdateACK(_itimediff(current_, ts)); + } + ParseACK(sn); + ShrinkBuf(); + if (flag == 0) + { + flag = 1; + maxack = sn; + } + else + { + if (_itimediff(sn, maxack) > 0) + { + maxack = sn; + } + } + Log(IKCP_LOG_IN_DATA, "input ack: sn={0} rtt={1} rto={2}", + sn, _itimediff(current_, ts), rx_rto_); + } + else if (cmd == IKCP_CMD_PUSH) + { + Log(IKCP_LOG_IN_DATA, "input psh: sn={0} ts={1}", sn, ts); + if (_itimediff(sn, rcv_nxt_ + rcv_wnd_) < 0) + { + ACKPush(sn, ts); + if (_itimediff(sn, rcv_nxt_) >= 0) + { + var seg = new Segment((int)len); + seg.conv = conv; + seg.cmd = cmd; + seg.frg = frg; + seg.wnd = wnd; + seg.ts = ts; + seg.sn = sn; + seg.una = una; + if (len > 0) + { + Buffer.BlockCopy(data, offset, seg.data, 0, (int)len); + } + ParseData(seg); + } + } + } + else if (cmd == IKCP_CMD_WASK) + { + // ready to send back IKCP_CMD_WINS in ikcp_flush + // tell remote my window size + probe_ |= IKCP_ASK_TELL; + Log(IKCP_LOG_IN_PROBE, "input probe"); + } + else if (cmd == IKCP_CMD_WINS) + { + // do nothing + Log(IKCP_LOG_IN_WINS, "input wins: {0}", wnd); + } + else + { + return -3; + } + + offset += (int)len; + size -= (int)len; + } + + if (flag != 0) + { + ParseFastACK(maxack); + } + + UInt32 unack = snd_una_; + if (_itimediff(snd_una_, unack) > 0) + { + if (cwnd_ < rmt_wnd_) + { + if (cwnd_ < ssthresh_) + { + cwnd_++; + incr_ += mss_; + } + else + { + if (incr_ < mss_) + incr_ = mss_; + incr_ += (mss_ * mss_) / incr_ + (mss_ / 16); + if ((cwnd_ + 1) * mss_ <= incr_) + cwnd_++; + } + if (cwnd_ > rmt_wnd_) + { + cwnd_ = rmt_wnd_; + incr_ = rmt_wnd_ * mss_; + } + } + } + + return 0; + } + + int WndUnused() + { + if (nrcv_que_ < rcv_wnd_) + return (int)(rcv_wnd_ - nrcv_que_); + return 0; + } + + // flush pending data + void Flush() + { + int change = 0; + int lost = 0; + int offset = 0; + + // 'ikcp_update' haven't been called. + if (updated_ == 0) + return; + + var seg = new Segment + { + conv = conv_, + cmd = IKCP_CMD_ACK, + wnd = (UInt32)WndUnused(), + una = rcv_nxt_, + }; + + // flush acknowledges + int count = (int)ackcount_; + for (int i = 0; i < count; i++) + { + if ((offset + IKCP_OVERHEAD) > mtu_) + { + output_(buffer_, offset, user_); + offset = 0; + } + ACKGet(i, ref seg.sn, ref seg.ts); + seg.Encode(buffer_, ref offset); + } + + ackcount_ = 0; + + // probe window size (if remote window size equals zero) + if (rmt_wnd_ == 0) + { + if (probe_wait_ == 0) + { + probe_wait_ = IKCP_PROBE_INIT; + ts_probe_ = current_ + probe_wait_; + } + else + { + if (_itimediff(current_, ts_probe_) >= 0) + { + if (probe_wait_ < IKCP_PROBE_INIT) + probe_wait_ = IKCP_PROBE_INIT; + probe_wait_ += probe_wait_ / 2; + if (probe_wait_ > IKCP_PROBE_LIMIT) + probe_wait_ = IKCP_PROBE_LIMIT; + ts_probe_ = current_ + probe_wait_; + probe_ |= IKCP_ASK_SEND; + } + } + } + else + { + ts_probe_ = 0; + probe_wait_ = 0; + } + + // flush window probing commands + if ((probe_ & IKCP_ASK_SEND) > 0) + { + seg.cmd = IKCP_CMD_WASK; + if ((offset + IKCP_OVERHEAD) > mtu_) + { + output_(buffer_, offset, user_); + offset = 0; + } + seg.Encode(buffer_, ref offset); + } + + // flush window probing commands + if ((probe_ & IKCP_ASK_TELL) > 0) + { + seg.cmd = IKCP_CMD_WINS; + if ((offset + IKCP_OVERHEAD) > mtu_) + { + output_(buffer_, offset, user_); + offset = 0; + } + seg.Encode(buffer_, ref offset); + } + + probe_ = 0; + + // calculate window size + UInt32 cwnd = _imin_(snd_wnd_, rmt_wnd_); + if (nocwnd_ == 0) + cwnd = _imin_(cwnd_, cwnd); + + // move data from snd_queue to snd_buf + while (_itimediff(snd_nxt_, snd_una_ + cwnd) < 0) + { + if (snd_queue_.Count == 0) + break; + + var node = snd_queue_.First; + var newseg = node.Value; + snd_queue_.Remove(node); + snd_buf_.AddLast(node); + nsnd_que_--; + nsnd_buf_++; + + newseg.conv = conv_; + newseg.cmd = IKCP_CMD_PUSH; + newseg.wnd = seg.wnd; + newseg.ts = current_; + newseg.sn = snd_nxt_++; + newseg.una = rcv_nxt_; + newseg.resendts = current_; + newseg.rto = (UInt32)rx_rto_; + newseg.faskack = 0; + newseg.xmit = 0; + } + + // calculate resent + UInt32 resent = (fastresend_ > 0 ? (UInt32)fastresend_ : 0xffffffff); + UInt32 rtomin = (nodelay_ == 0 ? (UInt32)(rx_rto_ >> 3) : 0); + + // flush data segments + for (var node = snd_buf_.First; node != null; node = node.Next) + { + var segment = node.Value; + int needsend = 0; + if (segment.xmit == 0) + { + needsend = 1; + segment.xmit++; + segment.rto = (UInt32)rx_rto_; + segment.resendts = current_ + segment.rto + rtomin; + } + else if (_itimediff(current_, segment.resendts) >= 0) + { + needsend = 1; + segment.xmit++; + xmit_++; + if (nodelay_ == 0) + segment.rto += (UInt32)rx_rto_; + else + segment.rto += (UInt32)rx_rto_ / 2; + segment.resendts = current_ + segment.rto; + lost = 1; + } + else if (segment.faskack >= resent) + { + needsend = 1; + segment.xmit++; + segment.faskack = 0; + segment.resendts = current_ + segment.rto; + change++; + } + + if (needsend > 0) + { + segment.ts = current_; + segment.wnd = seg.wnd; + segment.una = rcv_nxt_; + + int need = IKCP_OVERHEAD; + if (segment.data != null) + need += segment.data.Length; + + if (offset + need > mtu_) + { + output_(buffer_, offset, user_); + offset = 0; + } + segment.Encode(buffer_, ref offset); + if (segment.data.Length > 0) + { + Buffer.BlockCopy(segment.data, 0, buffer_, offset, segment.data.Length); + offset += segment.data.Length; + } + if (segment.xmit >= dead_link_) + state_ = 0xffffffff; + } + } + + // flush remain segments + if (offset > 0) + { + output_(buffer_, offset, user_); + offset = 0; + } + + // update ssthresh + if (change > 0) + { + UInt32 inflight = snd_nxt_ - snd_una_; + ssthresh_ = inflight / 2; + if (ssthresh_ < IKCP_THRESH_MIN) + ssthresh_ = IKCP_THRESH_MIN; + cwnd_ = ssthresh_ + resent; + incr_ = cwnd_ * mss_; + } + + if (lost > 0) + { + ssthresh_ = cwnd / 2; + if (ssthresh_ < IKCP_THRESH_MIN) + ssthresh_ = IKCP_THRESH_MIN; + cwnd_ = 1; + incr_ = mss_; + } + + if (cwnd_ < 1) + { + cwnd_ = 1; + incr_ = mss_; + } + } + + // update state (call it repeatedly, every 10ms-100ms), or you can ask + // ikcp_check when to call it again (without ikcp_input/_send calling). + // 'current' - current timestamp in millisec. + public void Update(UInt32 current) + { + current_ = current; + if (updated_ == 0) + { + updated_ = 1; + ts_flush_ = current; + } + + Int32 slap = _itimediff(current_, ts_flush_); + if (slap >= 10000 || slap < -10000) + { + ts_flush_ = current; + slap = 0; + } + + if (slap >= 0) + { + ts_flush_ += interval_; + if (_itimediff(current_, ts_flush_) >= 0) + ts_flush_ = current_ + interval_; + + Flush(); + } + } + + // Determine when should you invoke ikcp_update: + // returns when you should invoke ikcp_update in millisec, if there + // is no ikcp_input/_send calling. you can call ikcp_update in that + // time, instead of call update repeatly. + // Important to reduce unnacessary ikcp_update invoking. use it to + // schedule ikcp_update (eg. implementing an epoll-like mechanism, + // or optimize ikcp_update when handling massive kcp connections) + public UInt32 Check(UInt32 current) + { + UInt32 ts_flush = ts_flush_; + Int32 tm_flush = 0x7fffffff; + Int32 tm_packet = 0x7fffffff; + + if (updated_ == 0) + return current; + + if (_itimediff(current, ts_flush) >= 10000 || + _itimediff(current, ts_flush) < -10000) + { + ts_flush = current; + } + + if (_itimediff(current, ts_flush) >= 0) + return current; + + tm_flush = _itimediff(ts_flush, current); + + for (var node = snd_buf_.First; node != null; node = node.Next) + { + var seg = node.Value; + Int32 diff = _itimediff(seg.resendts, current); + if (diff <= 0) + return current; + + if (diff < tm_packet) + tm_packet = diff; + } + + UInt32 minimal = (UInt32)(tm_packet < tm_flush ? tm_packet : tm_flush); + if (minimal >= interval_) + minimal = interval_; + + return current + minimal; + } + + // change MTU size, default is 1400 + public int SetMTU(int mtu) + { + if (mtu < 50 || mtu < IKCP_OVERHEAD) + return -1; + + var buffer = new byte[(mtu + IKCP_OVERHEAD) * 3]; + mtu_ = (UInt32)mtu; + mss_ = mtu_ - IKCP_OVERHEAD; + buffer_ = buffer; + return 0; + } + + public int Interval(int interval) + { + if (interval > 5000) + interval = 5000; + else if (interval < 10) + interval = 10; + + interval_ = (UInt32)interval; + return 0; + } + + // fastest: ikcp_nodelay(kcp, 1, 20, 2, 1) + // nodelay: 0:disable(default), 1:enable + // interval: internal update timer interval in millisec, default is 100ms + // resend: 0:disable fast resend(default), 1:enable fast resend + // nc: 0:normal congestion control(default), 1:disable congestion control + public int NoDelay(int nodelay, int interval, int resend, int nc) + { + if (nodelay >= 0) + { + nodelay_ = (UInt32)nodelay; + if (nodelay > 0) + { + rx_minrto_ = IKCP_RTO_NDL; + } + else + { + rx_minrto_ = IKCP_RTO_MIN; + } + } + if (interval >= 0) + { + if (interval > 5000) + interval = 5000; + else if (interval < 10) + interval = 10; + + interval_ = (UInt32)interval; + } + + if (resend >= 0) + fastresend_ = resend; + + if (nc >= 0) + nocwnd_ = nc; + + return 0; + } + + // set maximum window size: sndwnd=32, rcvwnd=32 by default + public int WndSize(int sndwnd, int rcvwnd) + { + if (sndwnd > 0) + snd_wnd_ = (UInt32)sndwnd; + if (rcvwnd > 0) + rcv_wnd_ = (UInt32)rcvwnd; + return 0; + } + + // get how many packet is waiting to be sent + public int WaitSnd() + { + return (int)(nsnd_buf_ + nsnd_que_); + } + + // read conv + public UInt32 GetConv() + { + return conv_; + } + + public UInt32 GetState() + { + return state_; + } + + public void SetMinRTO(int minrto) + { + rx_minrto_ = minrto; + } + + public void SetFastResend(int resend) + { + fastresend_ = resend; + } + + void Log(int mask, string format, params object[] args) + { + // Console.WriteLine(mask + String.Format(format, args)); + } + } +} diff --git a/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps/KCP.cs.meta b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps/KCP.cs.meta new file mode 100644 index 00000000..281ac922 --- /dev/null +++ b/Assets/Plugins/kbengine/kbengine_unity3d_plugins/deps/KCP.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 0312ad6e584b78a4e9be39cefd8773c9 +timeCreated: 1531901400 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/readme.md b/Assets/Plugins/readme.md new file mode 100644 index 00000000..67c8653b --- /dev/null +++ b/Assets/Plugins/readme.md @@ -0,0 +1,4 @@ +زο: +References: +https://groups.google.com/forum/#!topic/critterai/IwV77mbj0ds +http://answers.unity3d.com/questions/265793/problem-in-bulding-exe-for-web-player.html diff --git a/Assets/Plugins/readme.md.meta b/Assets/Plugins/readme.md.meta new file mode 100644 index 00000000..e106f734 --- /dev/null +++ b/Assets/Plugins/readme.md.meta @@ -0,0 +1,4 @@ +fileFormatVersion: 2 +guid: 79d1677f575f1b34f91be0aad1e21956 +DefaultImporter: + userData: diff --git a/Assets/Pro Standard Assets/Water/Sources/Daylight Water.mat b/Assets/Pro Standard Assets/Water/Sources/Daylight Water.mat index 364ece99..eed15c26 100644 Binary files a/Assets/Pro Standard Assets/Water/Sources/Daylight Water.mat and b/Assets/Pro Standard Assets/Water/Sources/Daylight Water.mat differ diff --git a/Assets/Standard Assets/Character Controllers.meta b/Assets/Standard Assets/Character Controllers.meta deleted file mode 100644 index 81020fae..00000000 --- a/Assets/Standard Assets/Character Controllers.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 728f0f3e616bea54a97c1edc27dc8286 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/Standard Assets/Character Controllers/Sources.meta b/Assets/Standard Assets/Character Controllers/Sources.meta deleted file mode 100644 index 65d9b6b4..00000000 --- a/Assets/Standard Assets/Character Controllers/Sources.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 9ada83d4047abee4a8fcea64eea422a7 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter.meta b/Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter.meta deleted file mode 100644 index 5473272a..00000000 --- a/Assets/Standard Assets/Character Controllers/Sources/PrototypeCharacter.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 8e7c217727f1ca64cbf120fd2d1762de -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/10001001.unity3d b/Assets/StreamingAssets/10001001.unity3d index 58ce8b83..f3a6ac41 100644 Binary files a/Assets/StreamingAssets/10001001.unity3d and b/Assets/StreamingAssets/10001001.unity3d differ diff --git a/Assets/StreamingAssets/10001001.unity3d.meta b/Assets/StreamingAssets/10001001.unity3d.meta deleted file mode 100644 index 59c200ee..00000000 --- a/Assets/StreamingAssets/10001001.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4dc613880e2ab584795aad11b4b9cf5f -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/20001001.unity3d b/Assets/StreamingAssets/20001001.unity3d index e848dfff..fcf873ad 100644 Binary files a/Assets/StreamingAssets/20001001.unity3d and b/Assets/StreamingAssets/20001001.unity3d differ diff --git a/Assets/StreamingAssets/20001001.unity3d.meta b/Assets/StreamingAssets/20001001.unity3d.meta deleted file mode 100644 index 9b1963a1..00000000 --- a/Assets/StreamingAssets/20001001.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 197763fe4a996864088f242f68093162 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/20002001.unity3d b/Assets/StreamingAssets/20002001.unity3d index 57595a6a..45f42e11 100644 Binary files a/Assets/StreamingAssets/20002001.unity3d and b/Assets/StreamingAssets/20002001.unity3d differ diff --git a/Assets/StreamingAssets/20002001.unity3d.meta b/Assets/StreamingAssets/20002001.unity3d.meta deleted file mode 100644 index 41013c5b..00000000 --- a/Assets/StreamingAssets/20002001.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 38e1b042a12fc6141b45f3fb2c7b374d -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/90000001.unity3d b/Assets/StreamingAssets/90000001.unity3d index 8133df28..dafc4b3a 100644 Binary files a/Assets/StreamingAssets/90000001.unity3d and b/Assets/StreamingAssets/90000001.unity3d differ diff --git a/Assets/StreamingAssets/90000001.unity3d.meta b/Assets/StreamingAssets/90000001.unity3d.meta deleted file mode 100644 index 8ecb1fc4..00000000 --- a/Assets/StreamingAssets/90000001.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: e2e4773315fe5ef42b11f16664e1388f -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/Daylight Water.unity3d b/Assets/StreamingAssets/Daylight Water.unity3d index 0de6fe3a..26b5bc04 100644 Binary files a/Assets/StreamingAssets/Daylight Water.unity3d and b/Assets/StreamingAssets/Daylight Water.unity3d differ diff --git a/Assets/StreamingAssets/Daylight Water.unity3d.meta b/Assets/StreamingAssets/Daylight Water.unity3d.meta deleted file mode 100644 index c1ef31db..00000000 --- a/Assets/StreamingAssets/Daylight Water.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 7a8b7adab05fb314a84fceee1706cdb3 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Cart_03_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Cart_03_LOD0_PF.unity3d index 720b8219..0ecead75 100644 Binary files a/Assets/StreamingAssets/FV01_Cart_03_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Cart_03_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Cart_03_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Cart_03_LOD0_PF.unity3d.meta deleted file mode 100644 index 8725796c..00000000 --- a/Assets/StreamingAssets/FV01_Cart_03_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 29c4b6e7458be47408f0090d18ffd8de -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Crane_01_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Crane_01_LOD0_PF.unity3d index ac1a3de1..cc9e8a3f 100644 Binary files a/Assets/StreamingAssets/FV01_Crane_01_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Crane_01_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Crane_01_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Crane_01_LOD0_PF.unity3d.meta deleted file mode 100644 index 1d503c34..00000000 --- a/Assets/StreamingAssets/FV01_Crane_01_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b699ef6e74cb4ea4783e784127716875 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_HousePart_05_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_HousePart_05_LOD0_PF.unity3d index 54e1d605..7a7dcdc4 100644 Binary files a/Assets/StreamingAssets/FV01_HousePart_05_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_HousePart_05_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_HousePart_05_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_HousePart_05_LOD0_PF.unity3d.meta deleted file mode 100644 index 37270124..00000000 --- a/Assets/StreamingAssets/FV01_HousePart_05_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: c068502d99f0fec43af8243a32c2d3dd -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_House_43_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_House_43_LOD0_PF.unity3d index ca888769..befd124c 100644 Binary files a/Assets/StreamingAssets/FV01_House_43_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_House_43_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_House_43_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_House_43_LOD0_PF.unity3d.meta deleted file mode 100644 index 706eb4f8..00000000 --- a/Assets/StreamingAssets/FV01_House_43_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b4632ba99ca10844bba81f14841f11fb -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_House_43b_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_House_43b_LOD0_PF.unity3d index e597435a..e859997d 100644 Binary files a/Assets/StreamingAssets/FV01_House_43b_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_House_43b_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_House_43b_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_House_43b_LOD0_PF.unity3d.meta deleted file mode 100644 index 47176528..00000000 --- a/Assets/StreamingAssets/FV01_House_43b_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5219ed87b7fb416479aae629dbe5c48f -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_House_45_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_House_45_LOD0_PF.unity3d index 5ad81780..a63f1baf 100644 Binary files a/Assets/StreamingAssets/FV01_House_45_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_House_45_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_House_45_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_House_45_LOD0_PF.unity3d.meta deleted file mode 100644 index 5df1c1f6..00000000 --- a/Assets/StreamingAssets/FV01_House_45_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 773fcf615b0614a428af793352fd4838 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Stairs_01_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Stairs_01_LOD0_PF.unity3d index d132acd9..4f1148f2 100644 Binary files a/Assets/StreamingAssets/FV01_Stairs_01_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Stairs_01_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Stairs_01_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Stairs_01_LOD0_PF.unity3d.meta deleted file mode 100644 index 03b9d518..00000000 --- a/Assets/StreamingAssets/FV01_Stairs_01_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: e867868fa4a063c4386d34111eb62d5e -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Wall_05_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Wall_05_LOD0_PF.unity3d index 18842b87..f9e29796 100644 Binary files a/Assets/StreamingAssets/FV01_Wall_05_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Wall_05_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Wall_05_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Wall_05_LOD0_PF.unity3d.meta deleted file mode 100644 index c8ed1b8d..00000000 --- a/Assets/StreamingAssets/FV01_Wall_05_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: fd78e80b0c73c46469b53d9688f4c197 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Wall_05b_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Wall_05b_LOD0_PF.unity3d index c3814ffe..004b1bf2 100644 Binary files a/Assets/StreamingAssets/FV01_Wall_05b_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Wall_05b_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Wall_05b_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Wall_05b_LOD0_PF.unity3d.meta deleted file mode 100644 index dbfd40ac..00000000 --- a/Assets/StreamingAssets/FV01_Wall_05b_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 17aa1d39db3ad97449655c853d90a172 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Wall_05c_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Wall_05c_LOD0_PF.unity3d index 8c6d64d3..606862a3 100644 Binary files a/Assets/StreamingAssets/FV01_Wall_05c_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Wall_05c_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Wall_05c_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Wall_05c_LOD0_PF.unity3d.meta deleted file mode 100644 index e2423e48..00000000 --- a/Assets/StreamingAssets/FV01_Wall_05c_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ace36e346aa3f4940aa6d21270fe0718 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Wall_06_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Wall_06_LOD0_PF.unity3d index 865130fa..5290d296 100644 Binary files a/Assets/StreamingAssets/FV01_Wall_06_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Wall_06_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Wall_06_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Wall_06_LOD0_PF.unity3d.meta deleted file mode 100644 index 9afc310b..00000000 --- a/Assets/StreamingAssets/FV01_Wall_06_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ccd1b1f24fc7e434face8792aa9c78a6 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Wall_06b_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Wall_06b_LOD0_PF.unity3d index fd24c120..9fe03513 100644 Binary files a/Assets/StreamingAssets/FV01_Wall_06b_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Wall_06b_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Wall_06b_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Wall_06b_LOD0_PF.unity3d.meta deleted file mode 100644 index 0085085b..00000000 --- a/Assets/StreamingAssets/FV01_Wall_06b_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 6e959d88aabe0ef499ee9c58a3bcf260 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_Wall_06c_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_Wall_06c_LOD0_PF.unity3d index 89ec9255..2f345467 100644 Binary files a/Assets/StreamingAssets/FV01_Wall_06c_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_Wall_06c_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_Wall_06c_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_Wall_06c_LOD0_PF.unity3d.meta deleted file mode 100644 index e40d8007..00000000 --- a/Assets/StreamingAssets/FV01_Wall_06c_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 200504598259b6842a9638a806400844 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_bush2_PF_pz.unity3d b/Assets/StreamingAssets/FV01_bush2_PF_pz.unity3d index 8951ca98..6fea710b 100644 Binary files a/Assets/StreamingAssets/FV01_bush2_PF_pz.unity3d and b/Assets/StreamingAssets/FV01_bush2_PF_pz.unity3d differ diff --git a/Assets/StreamingAssets/FV01_cratestack_02_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_cratestack_02_LOD0_PF.unity3d index 02d76af6..fa8e1dd2 100644 Binary files a/Assets/StreamingAssets/FV01_cratestack_02_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_cratestack_02_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_cratestack_02_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_cratestack_02_LOD0_PF.unity3d.meta deleted file mode 100644 index b9fb5a65..00000000 --- a/Assets/StreamingAssets/FV01_cratestack_02_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 7d4fbb8db775dd143bbd5a77d2697a50 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_lightpost_01_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_lightpost_01_LOD0_PF.unity3d index 9565dce4..41f74185 100644 Binary files a/Assets/StreamingAssets/FV01_lightpost_01_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_lightpost_01_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_lightpost_01_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_lightpost_01_LOD0_PF.unity3d.meta deleted file mode 100644 index f2cc15da..00000000 --- a/Assets/StreamingAssets/FV01_lightpost_01_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4019581f9df316e43879190a9257cef4 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_lightpost_03_LOD0_PF.unity3d b/Assets/StreamingAssets/FV01_lightpost_03_LOD0_PF.unity3d index b28d8a54..c5e624b2 100644 Binary files a/Assets/StreamingAssets/FV01_lightpost_03_LOD0_PF.unity3d and b/Assets/StreamingAssets/FV01_lightpost_03_LOD0_PF.unity3d differ diff --git a/Assets/StreamingAssets/FV01_lightpost_03_LOD0_PF.unity3d.meta b/Assets/StreamingAssets/FV01_lightpost_03_LOD0_PF.unity3d.meta deleted file mode 100644 index 3ef8b5af..00000000 --- a/Assets/StreamingAssets/FV01_lightpost_03_LOD0_PF.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b1159321c9ddf3a468516af32a11b070 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/FV01_tree3_pz.unity3d b/Assets/StreamingAssets/FV01_tree3_pz.unity3d index 02241d56..b683398f 100644 Binary files a/Assets/StreamingAssets/FV01_tree3_pz.unity3d and b/Assets/StreamingAssets/FV01_tree3_pz.unity3d differ diff --git a/Assets/StreamingAssets/FV01_tree4_PF_pz.unity3d b/Assets/StreamingAssets/FV01_tree4_PF_pz.unity3d index 7bfb16dc..fdd4bb27 100644 Binary files a/Assets/StreamingAssets/FV01_tree4_PF_pz.unity3d and b/Assets/StreamingAssets/FV01_tree4_PF_pz.unity3d differ diff --git a/Assets/StreamingAssets/Mountain10.unity3d b/Assets/StreamingAssets/Mountain10.unity3d index 948324cb..abe06643 100644 Binary files a/Assets/StreamingAssets/Mountain10.unity3d and b/Assets/StreamingAssets/Mountain10.unity3d differ diff --git a/Assets/StreamingAssets/Mountain10.unity3d.meta b/Assets/StreamingAssets/Mountain10.unity3d.meta deleted file mode 100644 index abc8b7b6..00000000 --- a/Assets/StreamingAssets/Mountain10.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 03acdd651bbea60438bb893c9fb14771 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/PlayerChar.unity3d b/Assets/StreamingAssets/PlayerChar.unity3d index fee5f9ab..4e4ab5ab 100644 Binary files a/Assets/StreamingAssets/PlayerChar.unity3d and b/Assets/StreamingAssets/PlayerChar.unity3d differ diff --git a/Assets/StreamingAssets/PlayerChar.unity3d.meta b/Assets/StreamingAssets/PlayerChar.unity3d.meta deleted file mode 100644 index a31f9067..00000000 --- a/Assets/StreamingAssets/PlayerChar.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 51b19838dd5338f43947411b362e0e3a -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/Sunny2_Skybox.unity3d b/Assets/StreamingAssets/Sunny2_Skybox.unity3d index a021ce62..5d331b00 100644 Binary files a/Assets/StreamingAssets/Sunny2_Skybox.unity3d and b/Assets/StreamingAssets/Sunny2_Skybox.unity3d differ diff --git a/Assets/StreamingAssets/Sunny2_Skybox.unity3d.meta b/Assets/StreamingAssets/Sunny2_Skybox.unity3d.meta deleted file mode 100644 index 14ed2bd6..00000000 --- a/Assets/StreamingAssets/Sunny2_Skybox.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 502ea1b097d33a546a7ad724bf200643 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs.meta b/Assets/StreamingAssets/_prefabs.meta deleted file mode 100644 index d18feb79..00000000 --- a/Assets/StreamingAssets/_prefabs.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 9590628ea1b24c74c8242195276e49ba -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_login_UI_Root_(2D).7.prefab b/Assets/StreamingAssets/_prefabs/streaming_login_UI_Root_(2D).7.prefab deleted file mode 100644 index 4bb49fbd..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_login_UI_Root_(2D).7.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_login_UI_Root_(2D).7.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_login_UI_Root_(2D).7.prefab.meta deleted file mode 100644 index afa02987..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_login_UI_Root_(2D).7.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 404e1e707713a7847a3d6f67c99734d6 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_login_cursor.2.prefab b/Assets/StreamingAssets/_prefabs/streaming_login_cursor.2.prefab deleted file mode 100644 index 7a110856..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_login_cursor.2.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_login_cursor.2.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_login_cursor.2.prefab.meta deleted file mode 100644 index 1f3f614c..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_login_cursor.2.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2f4051400f9805f429884fcf7bf20c2d -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Directional_light.32.prefab b/Assets/StreamingAssets/_prefabs/streaming_selavatar_Directional_light.32.prefab deleted file mode 100644 index 3ae2d18a..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Directional_light.32.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Directional_light.32.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_selavatar_Directional_light.32.prefab.meta deleted file mode 100644 index 2ab6453d..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Directional_light.32.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 369af731e5e0db44b875960cd96b8abb -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Main_Camera.13.prefab b/Assets/StreamingAssets/_prefabs/streaming_selavatar_Main_Camera.13.prefab deleted file mode 100644 index fbd460e2..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Main_Camera.13.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Main_Camera.13.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_selavatar_Main_Camera.13.prefab.meta deleted file mode 100644 index 751b6777..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Main_Camera.13.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 3253c9941daac5d48b48dfac3a476e02 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Particles.16.prefab b/Assets/StreamingAssets/_prefabs/streaming_selavatar_Particles.16.prefab deleted file mode 100644 index 947f1839..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Particles.16.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Particles.16.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_selavatar_Particles.16.prefab.meta deleted file mode 100644 index 218c8724..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_selavatar_Particles.16.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 8dba8651ef31b7c44ac249527ee1fb4d -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_WindZone.30.prefab b/Assets/StreamingAssets/_prefabs/streaming_selavatar_WindZone.30.prefab deleted file mode 100644 index 8bdf8851..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_selavatar_WindZone.30.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_WindZone.30.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_selavatar_WindZone.30.prefab.meta deleted file mode 100644 index ef99c761..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_selavatar_WindZone.30.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d302807979015fa4ca6bc71fb73b112d -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_ui.25.prefab b/Assets/StreamingAssets/_prefabs/streaming_selavatar_ui.25.prefab deleted file mode 100644 index 3ed0649f..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_selavatar_ui.25.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_selavatar_ui.25.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_selavatar_ui.25.prefab.meta deleted file mode 100644 index 44dfcd57..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_selavatar_ui.25.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d5251195186839047a5a11ebf411b56a -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_(0)worldMgr.159.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_(0)worldMgr.159.prefab deleted file mode 100644 index 67a28045..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_(0)worldMgr.159.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_(0)worldMgr.159.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_(0)worldMgr.159.prefab.meta deleted file mode 100644 index 70bcd21a..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_(0)worldMgr.159.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 16effa873c6bc5b439e070f2cf347ae3 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House11.90.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House11.90.prefab deleted file mode 100644 index ee4a1754..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House11.90.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House11.90.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House11.90.prefab.meta deleted file mode 100644 index c6c30cca..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House11.90.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: db89aba593d7df5459ade9eb13a15551 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12.92.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12.92.prefab deleted file mode 100644 index b26f02d2..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12.92.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12.92.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12.92.prefab.meta deleted file mode 100644 index f71e29c0..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12.92.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 674d6a2f3bce9fa4abe0c6cfb9681beb -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12b.94.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12b.94.prefab deleted file mode 100644 index 0933b421..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12b.94.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12b.94.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12b.94.prefab.meta deleted file mode 100644 index ae1fb2cc..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House12b.94.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2924ce7f71c9b344383301fe68db1628 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House13.96.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House13.96.prefab deleted file mode 100644 index 03aaf90b..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House13.96.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House13.96.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House13.96.prefab.meta deleted file mode 100644 index b4a97d4d..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House13.96.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: aa1619ab18498e3498a093fa8f25710e -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14.98.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14.98.prefab deleted file mode 100644 index c710e2ec..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14.98.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14.98.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14.98.prefab.meta deleted file mode 100644 index 79d85ef8..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14.98.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 325bc01ed29796847a2414d1b7b6dba1 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14b.100.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14b.100.prefab deleted file mode 100644 index 0793527d..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14b.100.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14b.100.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14b.100.prefab.meta deleted file mode 100644 index d21c5ff7..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House14b.100.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2656718babad52d45b65e3b8692b5265 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15.102.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15.102.prefab deleted file mode 100644 index d5e79061..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15.102.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15.102.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15.102.prefab.meta deleted file mode 100644 index e8d7c6cb..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15.102.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ca1f4d69a1a642247b13972afb98e83a -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15b.104.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15b.104.prefab deleted file mode 100644 index 4e307bd9..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15b.104.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15b.104.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15b.104.prefab.meta deleted file mode 100644 index 5bb47c5c..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House15b.104.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5023990a3dcc46d4aa1baa34f54bf1f1 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16.106.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16.106.prefab deleted file mode 100644 index 76393cf3..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16.106.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16.106.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16.106.prefab.meta deleted file mode 100644 index 87db76b6..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16.106.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b3f150f4f4eb5fc4fa7e794cb568756c -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16b.108.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16b.108.prefab deleted file mode 100644 index 3c95a658..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16b.108.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16b.108.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16b.108.prefab.meta deleted file mode 100644 index 3b42af37..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House16b.108.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ba644722542037a46b54df56f8b49333 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House17.110.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House17.110.prefab deleted file mode 100644 index 3dd75588..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House17.110.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House17.110.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House17.110.prefab.meta deleted file mode 100644 index e6883b79..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House17.110.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 6f223c755efe9034e9f5c825cd6cf886 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House19.112.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House19.112.prefab deleted file mode 100644 index 4a316517..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House19.112.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House19.112.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House19.112.prefab.meta deleted file mode 100644 index b0a271a6..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House19.112.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 0ca0f21af4ef31e4c9c68925e8a3f780 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20_Gate.114.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20_Gate.114.prefab deleted file mode 100644 index 89a6d292..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20_Gate.114.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20_Gate.114.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20_Gate.114.prefab.meta deleted file mode 100644 index 19ebcfef..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20_Gate.114.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5f97816b27321f6469585096bfb67719 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20b.116.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20b.116.prefab deleted file mode 100644 index 27b8783c..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20b.116.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20b.116.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20b.116.prefab.meta deleted file mode 100644 index b131ce7e..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20b.116.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 134b261a267a4334abd82bde7fc1cfc8 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20c.118.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20c.118.prefab deleted file mode 100644 index f49e19ad..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20c.118.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20c.118.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20c.118.prefab.meta deleted file mode 100644 index 3c19a33f..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House20c.118.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 753221ee626ab054784ee9fbe2495a10 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22.120.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22.120.prefab deleted file mode 100644 index a353a144..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22.120.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22.120.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22.120.prefab.meta deleted file mode 100644 index 09a60bf4..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22.120.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 111bc1b2f105dec4c943706be2d8e5c8 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22b.122.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22b.122.prefab deleted file mode 100644 index 3ded173b..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22b.122.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22b.122.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22b.122.prefab.meta deleted file mode 100644 index 3ef2364e..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House22b.122.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 360697b71dfad344dad04a19fb143ebd -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House23.124.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House23.124.prefab deleted file mode 100644 index cac42ddb..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House23.124.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House23.124.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House23.124.prefab.meta deleted file mode 100644 index 042fc6d2..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House23.124.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: c6239e1c15ab75a4da8a77d9479a0e87 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House24.126.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House24.126.prefab deleted file mode 100644 index b93fbc75..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House24.126.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House24.126.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House24.126.prefab.meta deleted file mode 100644 index 912d22dc..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House24.126.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5e1dd3dc6d910e441bd9e2202c477a45 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26b.128.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26b.128.prefab deleted file mode 100644 index 12c98496..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26b.128.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26b.128.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26b.128.prefab.meta deleted file mode 100644 index 05775fdc..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26b.128.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 0491c642802c2ea4a8f420fd3bc49996 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26c.130.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26c.130.prefab deleted file mode 100644 index 060dbfcf..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26c.130.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26c.130.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26c.130.prefab.meta deleted file mode 100644 index cab28959..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26c.130.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: a0f2e4bfe9b74e9438a301486241ac80 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26d.132.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26d.132.prefab deleted file mode 100644 index 038a0377..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26d.132.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26d.132.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26d.132.prefab.meta deleted file mode 100644 index 3d51708f..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House26d.132.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: f98507fa790a07749a0a7602256cc03e -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40.134.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40.134.prefab deleted file mode 100644 index 18090d8c..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40.134.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40.134.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40.134.prefab.meta deleted file mode 100644 index ccc95e9e..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40.134.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4098f58061ae7be449bf30c63aa5ca7a -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40b.136.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40b.136.prefab deleted file mode 100644 index 77d16ab5..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40b.136.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40b.136.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40b.136.prefab.meta deleted file mode 100644 index 5d700c71..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House40b.136.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 7623f26d778739841802207a6d8d1e20 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House43_platform.138.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House43_platform.138.prefab deleted file mode 100644 index f54661ef..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House43_platform.138.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House43_platform.138.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House43_platform.138.prefab.meta deleted file mode 100644 index a3c34ea2..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House43_platform.138.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: f1499ac186ad07c42ac4aa3d573df756 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44.140.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44.140.prefab deleted file mode 100644 index 684b6d31..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44.140.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44.140.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44.140.prefab.meta deleted file mode 100644 index 4db7282c..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44.140.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 23fe084ccacc27b4dace2aebcc14437a -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44b.142.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44b.142.prefab deleted file mode 100644 index 3c610783..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44b.142.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44b.142.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44b.142.prefab.meta deleted file mode 100644 index 569e2971..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House44b.142.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: be6d4361e57b4c446ac96b994e8b0441 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9.86.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9.86.prefab deleted file mode 100644 index 6493dab6..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9.86.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9.86.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9.86.prefab.meta deleted file mode 100644 index 3ada8ebe..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9.86.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ad3908ff060c3f247a4938d673dbb9cc -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9b.88.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9b.88.prefab deleted file mode 100644 index 1a0bc325..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9b.88.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9b.88.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9b.88.prefab.meta deleted file mode 100644 index c3d1ca0f..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House9b.88.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ee99f5e3d1d56054da7dd5920098f354 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House_25.84.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House_25.84.prefab deleted file mode 100644 index 64f9c23f..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House_25.84.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House_25.84.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House_25.84.prefab.meta deleted file mode 100644 index e9307623..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_House_25.84.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 1bf59867d5529754584f99b0586ad6c4 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MainCamera.163.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MainCamera.163.prefab deleted file mode 100644 index 5e1a7db2..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MainCamera.163.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MainCamera.163.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MainCamera.163.prefab.meta deleted file mode 100644 index 57f83abb..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MainCamera.163.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 98423e21266495f48baf64cfa2fe8688 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MarketPlace.144.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MarketPlace.144.prefab deleted file mode 100644 index 87b4d5cd..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MarketPlace.144.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MarketPlace.144.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MarketPlace.144.prefab.meta deleted file mode 100644 index 4bed79c1..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_MarketPlace.144.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 448e714c7b047804eb724f153cf91ac0 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_SoundManager.148.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_SoundManager.148.prefab deleted file mode 100644 index 49c41248..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_SoundManager.148.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_SoundManager.148.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_SoundManager.148.prefab.meta deleted file mode 100644 index 47fe539b..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_SoundManager.148.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5ede87aaa85a18c41b8e30cb519d23b7 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_Stocks.146.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_Stocks.146.prefab deleted file mode 100644 index e603dc9b..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_Stocks.146.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_Stocks.146.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_Stocks.146.prefab.meta deleted file mode 100644 index 0c7d46ff..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_Stocks.146.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 01a380f9d8d3e5844bc98daa35a26b67 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_showfps.154.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_showfps.154.prefab deleted file mode 100644 index 9a416db9..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_showfps.154.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_showfps.154.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_showfps.154.prefab.meta deleted file mode 100644 index 8ca363ef..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_showfps.154.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 1561fa84c65264f4daccad9cab7f6031 -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_worldManages.151.prefab b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_worldManages.151.prefab deleted file mode 100644 index e7122c62..00000000 Binary files a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_worldManages.151.prefab and /dev/null differ diff --git a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_worldManages.151.prefab.meta b/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_worldManages.151.prefab.meta deleted file mode 100644 index aab6bc7a..00000000 --- a/Assets/StreamingAssets/_prefabs/streaming_xinshoucun_worldManages.151.prefab.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 95896c4700ffa104a800b35b9d936adb -NativeFormatImporter: - userData: diff --git a/Assets/StreamingAssets/avatar1.unity3d b/Assets/StreamingAssets/avatar1.unity3d index 0e7dc956..a09da47c 100644 Binary files a/Assets/StreamingAssets/avatar1.unity3d and b/Assets/StreamingAssets/avatar1.unity3d differ diff --git a/Assets/StreamingAssets/avatar1.unity3d.meta b/Assets/StreamingAssets/avatar1.unity3d.meta deleted file mode 100644 index 732a7934..00000000 --- a/Assets/StreamingAssets/avatar1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: f864f3582ee98424692b9d1574523bb1 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/avatar2.unity3d b/Assets/StreamingAssets/avatar2.unity3d index 0eacd706..d425b9a0 100644 Binary files a/Assets/StreamingAssets/avatar2.unity3d and b/Assets/StreamingAssets/avatar2.unity3d differ diff --git a/Assets/StreamingAssets/avatar2.unity3d.meta b/Assets/StreamingAssets/avatar2.unity3d.meta deleted file mode 100644 index d7267905..00000000 --- a/Assets/StreamingAssets/avatar2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d584571065c01334d8801b85925a36ab -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/avatar3.unity3d b/Assets/StreamingAssets/avatar3.unity3d index 2981df34..f9c95b3e 100644 Binary files a/Assets/StreamingAssets/avatar3.unity3d and b/Assets/StreamingAssets/avatar3.unity3d differ diff --git a/Assets/StreamingAssets/avatar3.unity3d.meta b/Assets/StreamingAssets/avatar3.unity3d.meta deleted file mode 100644 index 855394dc..00000000 --- a/Assets/StreamingAssets/avatar3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: bcf7b324b9d1a4a4dbdfe8271856a56a -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/avatar4.unity3d b/Assets/StreamingAssets/avatar4.unity3d index e231be60..3938d2e7 100644 Binary files a/Assets/StreamingAssets/avatar4.unity3d and b/Assets/StreamingAssets/avatar4.unity3d differ diff --git a/Assets/StreamingAssets/avatar4.unity3d.meta b/Assets/StreamingAssets/avatar4.unity3d.meta deleted file mode 100644 index 8d12a48e..00000000 --- a/Assets/StreamingAssets/avatar4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 9398b295e7b08ac40be9d73a78b004e3 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/avatar_wpgroup.unity3d b/Assets/StreamingAssets/avatar_wpgroup.unity3d index 1267ecfa..90698d6d 100644 Binary files a/Assets/StreamingAssets/avatar_wpgroup.unity3d and b/Assets/StreamingAssets/avatar_wpgroup.unity3d differ diff --git a/Assets/StreamingAssets/avatar_wpgroup.unity3d.meta b/Assets/StreamingAssets/avatar_wpgroup.unity3d.meta deleted file mode 100644 index 860f4b53..00000000 --- a/Assets/StreamingAssets/avatar_wpgroup.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: e2539842ba142ab438e033a814ef6b4c -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/box.unity3d b/Assets/StreamingAssets/box.unity3d deleted file mode 100644 index 83ec7710..00000000 Binary files a/Assets/StreamingAssets/box.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/box.unity3d.meta b/Assets/StreamingAssets/box.unity3d.meta deleted file mode 100644 index ddd1c147..00000000 --- a/Assets/StreamingAssets/box.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ad246ea59d7e53c45bfac69a0d4cf5bb -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/cane2.unity3d b/Assets/StreamingAssets/cane2.unity3d index 75f2f1bf..83e887ef 100644 Binary files a/Assets/StreamingAssets/cane2.unity3d and b/Assets/StreamingAssets/cane2.unity3d differ diff --git a/Assets/StreamingAssets/cliff01.unity3d b/Assets/StreamingAssets/cliff01.unity3d index 7972e113..513e052d 100644 Binary files a/Assets/StreamingAssets/cliff01.unity3d and b/Assets/StreamingAssets/cliff01.unity3d differ diff --git a/Assets/StreamingAssets/defaultEntityMesh.unity3d b/Assets/StreamingAssets/defaultEntityMesh.unity3d index 82fe2389..5fbb367a 100644 Binary files a/Assets/StreamingAssets/defaultEntityMesh.unity3d and b/Assets/StreamingAssets/defaultEntityMesh.unity3d differ diff --git a/Assets/StreamingAssets/defaultEntityMesh.unity3d.meta b/Assets/StreamingAssets/defaultEntityMesh.unity3d.meta deleted file mode 100644 index dacfad16..00000000 --- a/Assets/StreamingAssets/defaultEntityMesh.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: c4605453b42d7f344873dd6f577b5ed9 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/gameui.unity3d b/Assets/StreamingAssets/gameui.unity3d index a704d17c..5581406d 100644 Binary files a/Assets/StreamingAssets/gameui.unity3d and b/Assets/StreamingAssets/gameui.unity3d differ diff --git a/Assets/StreamingAssets/gameui.unity3d.meta b/Assets/StreamingAssets/gameui.unity3d.meta deleted file mode 100644 index 517bc0bd..00000000 --- a/Assets/StreamingAssets/gameui.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 7a36e748b0a46af4ba88475100a53ad6 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/grass01_dark.unity3d b/Assets/StreamingAssets/grass01_dark.unity3d index 940b1dc2..7119bea8 100644 Binary files a/Assets/StreamingAssets/grass01_dark.unity3d and b/Assets/StreamingAssets/grass01_dark.unity3d differ diff --git a/Assets/StreamingAssets/grass01_ivy.unity3d b/Assets/StreamingAssets/grass01_ivy.unity3d index 5cf537f6..f733f32b 100644 Binary files a/Assets/StreamingAssets/grass01_ivy.unity3d and b/Assets/StreamingAssets/grass01_ivy.unity3d differ diff --git a/Assets/StreamingAssets/grass01_shaded.unity3d b/Assets/StreamingAssets/grass01_shaded.unity3d index eb92f31c..b30e50e4 100644 Binary files a/Assets/StreamingAssets/grass01_shaded.unity3d and b/Assets/StreamingAssets/grass01_shaded.unity3d differ diff --git a/Assets/StreamingAssets/grass1.unity3d b/Assets/StreamingAssets/grass1.unity3d index 6aa0c21f..d29b4ef1 100644 Binary files a/Assets/StreamingAssets/grass1.unity3d and b/Assets/StreamingAssets/grass1.unity3d differ diff --git a/Assets/StreamingAssets/gray_box.unity3d b/Assets/StreamingAssets/gray_box.unity3d new file mode 100644 index 00000000..a57649cd Binary files /dev/null and b/Assets/StreamingAssets/gray_box.unity3d differ diff --git a/Assets/StreamingAssets/hud_infos.unity3d b/Assets/StreamingAssets/hud_infos.unity3d index f8361cbc..6079c284 100644 Binary files a/Assets/StreamingAssets/hud_infos.unity3d and b/Assets/StreamingAssets/hud_infos.unity3d differ diff --git a/Assets/StreamingAssets/hud_infos.unity3d.meta b/Assets/StreamingAssets/hud_infos.unity3d.meta deleted file mode 100644 index e9b91a88..00000000 --- a/Assets/StreamingAssets/hud_infos.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: eedd200145730934a86643d67ef79353 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/loadingbar.unity3d b/Assets/StreamingAssets/loadingbar.unity3d index 9e8f2be8..28eca996 100644 Binary files a/Assets/StreamingAssets/loadingbar.unity3d and b/Assets/StreamingAssets/loadingbar.unity3d differ diff --git a/Assets/StreamingAssets/longboat.unity3d b/Assets/StreamingAssets/longboat.unity3d index 6447129b..30dc6a7e 100644 Binary files a/Assets/StreamingAssets/longboat.unity3d and b/Assets/StreamingAssets/longboat.unity3d differ diff --git a/Assets/StreamingAssets/longboat.unity3d.meta b/Assets/StreamingAssets/longboat.unity3d.meta deleted file mode 100644 index e4ff2e84..00000000 --- a/Assets/StreamingAssets/longboat.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d0b2ea9f972e9294db6421771ac6c514 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/minimapCamera.unity3d b/Assets/StreamingAssets/minimapCamera.unity3d index 1c440bf8..8f4b4403 100644 Binary files a/Assets/StreamingAssets/minimapCamera.unity3d and b/Assets/StreamingAssets/minimapCamera.unity3d differ diff --git a/Assets/StreamingAssets/minimapCamera.unity3d.meta b/Assets/StreamingAssets/minimapCamera.unity3d.meta deleted file mode 100644 index c1d560ad..00000000 --- a/Assets/StreamingAssets/minimapCamera.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 7c373d6de9d889a41b2c67882710de02 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/particles.unity3d b/Assets/StreamingAssets/particles.unity3d index 0e0d9179..a7586008 100644 Binary files a/Assets/StreamingAssets/particles.unity3d and b/Assets/StreamingAssets/particles.unity3d differ diff --git a/Assets/StreamingAssets/particles.unity3d.meta b/Assets/StreamingAssets/particles.unity3d.meta deleted file mode 100644 index c255fe3c..00000000 --- a/Assets/StreamingAssets/particles.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5141022e1fa46cf468ce3dc72626bb3d -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/roadtiles01.unity3d b/Assets/StreamingAssets/roadtiles01.unity3d index 03fa91bf..6cdeb432 100644 Binary files a/Assets/StreamingAssets/roadtiles01.unity3d and b/Assets/StreamingAssets/roadtiles01.unity3d differ diff --git a/Assets/StreamingAssets/roadtiles02.unity3d b/Assets/StreamingAssets/roadtiles02.unity3d index 098d75d7..6a188a3d 100644 Binary files a/Assets/StreamingAssets/roadtiles02.unity3d and b/Assets/StreamingAssets/roadtiles02.unity3d differ diff --git a/Assets/StreamingAssets/rock01.unity3d b/Assets/StreamingAssets/rock01.unity3d index f8b37d79..4b877ca0 100644 Binary files a/Assets/StreamingAssets/rock01.unity3d and b/Assets/StreamingAssets/rock01.unity3d differ diff --git a/Assets/StreamingAssets/selavatar.xml b/Assets/StreamingAssets/selavatar.xml index 4bc192b6..26d9de3b 100644 --- a/Assets/StreamingAssets/selavatar.xml +++ b/Assets/StreamingAssets/selavatar.xml @@ -1,5 +1,5 @@ - + @@ -280,9 +280,9 @@ 0 - 0.003490401 - 0.003490401 - 0.003490401 + 0.004166667 + 0.004166667 + 0.004166667 @@ -305,26 +305,7 @@ - - - - 0 - 0 - 0 - - - 0 - 0 - 0 - - - 71.53228 - 71.53228 - 71.53228 - - - - + -159.4792 @@ -343,7 +324,7 @@ - + 0 @@ -362,7 +343,7 @@ - + 6.640692 @@ -381,7 +362,7 @@ - + -52.84608 @@ -400,7 +381,7 @@ - + -52.84608 @@ -419,7 +400,7 @@ - + 38.66455 @@ -438,7 +419,7 @@ - + 243.0087 diff --git a/Assets/StreamingAssets/shader_Terrain_Diffuse.unity3d.meta b/Assets/StreamingAssets/shader_Terrain_Diffuse.unity3d.meta deleted file mode 100644 index 98d40b47..00000000 --- a/Assets/StreamingAssets/shader_Terrain_Diffuse.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 118b584718783c04396db163113709fc -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_login_UI_Root_(2D).7.unity3d b/Assets/StreamingAssets/streaming_login_UI_Root_(2D).7.unity3d index ec679fc7..45ebaa9a 100644 Binary files a/Assets/StreamingAssets/streaming_login_UI_Root_(2D).7.unity3d and b/Assets/StreamingAssets/streaming_login_UI_Root_(2D).7.unity3d differ diff --git a/Assets/StreamingAssets/streaming_login_UI_Root_(2D).7.unity3d.meta b/Assets/StreamingAssets/streaming_login_UI_Root_(2D).7.unity3d.meta deleted file mode 100644 index 0af05024..00000000 --- a/Assets/StreamingAssets/streaming_login_UI_Root_(2D).7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 949107d9375926d418a5ae323fbcf646 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_login_cursor.2.unity3d b/Assets/StreamingAssets/streaming_login_cursor.2.unity3d index 07982c8d..ed27dce4 100644 Binary files a/Assets/StreamingAssets/streaming_login_cursor.2.unity3d and b/Assets/StreamingAssets/streaming_login_cursor.2.unity3d differ diff --git a/Assets/StreamingAssets/streaming_selavatar_Directional_light.31.unity3d b/Assets/StreamingAssets/streaming_selavatar_Directional_light.31.unity3d new file mode 100644 index 00000000..277c5496 Binary files /dev/null and b/Assets/StreamingAssets/streaming_selavatar_Directional_light.31.unity3d differ diff --git a/Assets/StreamingAssets/streaming_selavatar_Directional_light.32.unity3d b/Assets/StreamingAssets/streaming_selavatar_Directional_light.32.unity3d deleted file mode 100644 index bed9c49e..00000000 Binary files a/Assets/StreamingAssets/streaming_selavatar_Directional_light.32.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_selavatar_Directional_light.32.unity3d.meta b/Assets/StreamingAssets/streaming_selavatar_Directional_light.32.unity3d.meta deleted file mode 100644 index e03c0b7b..00000000 --- a/Assets/StreamingAssets/streaming_selavatar_Directional_light.32.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: c62a28b360ab4a24f8dfee92f28595f4 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_selavatar_Main_Camera.13.unity3d b/Assets/StreamingAssets/streaming_selavatar_Main_Camera.13.unity3d index bee1e386..99d12a98 100644 Binary files a/Assets/StreamingAssets/streaming_selavatar_Main_Camera.13.unity3d and b/Assets/StreamingAssets/streaming_selavatar_Main_Camera.13.unity3d differ diff --git a/Assets/StreamingAssets/streaming_selavatar_Main_Camera.13.unity3d.meta b/Assets/StreamingAssets/streaming_selavatar_Main_Camera.13.unity3d.meta deleted file mode 100644 index 18abf7c1..00000000 --- a/Assets/StreamingAssets/streaming_selavatar_Main_Camera.13.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 8e9de764a09c652409cc03f837a588da -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_selavatar_Particles.16.unity3d b/Assets/StreamingAssets/streaming_selavatar_Particles.16.unity3d index a3f3dd43..7bd74cb6 100644 Binary files a/Assets/StreamingAssets/streaming_selavatar_Particles.16.unity3d and b/Assets/StreamingAssets/streaming_selavatar_Particles.16.unity3d differ diff --git a/Assets/StreamingAssets/streaming_selavatar_Particles.16.unity3d.meta b/Assets/StreamingAssets/streaming_selavatar_Particles.16.unity3d.meta deleted file mode 100644 index 6241b1a7..00000000 --- a/Assets/StreamingAssets/streaming_selavatar_Particles.16.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: c7923f6c4ca4f7a45a2d01c81371f11c -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_selavatar_WindZone.29.unity3d b/Assets/StreamingAssets/streaming_selavatar_WindZone.29.unity3d new file mode 100644 index 00000000..6b44d9dc Binary files /dev/null and b/Assets/StreamingAssets/streaming_selavatar_WindZone.29.unity3d differ diff --git a/Assets/StreamingAssets/streaming_selavatar_WindZone.30.unity3d b/Assets/StreamingAssets/streaming_selavatar_WindZone.30.unity3d deleted file mode 100644 index cba89532..00000000 Binary files a/Assets/StreamingAssets/streaming_selavatar_WindZone.30.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_selavatar_WindZone.30.unity3d.meta b/Assets/StreamingAssets/streaming_selavatar_WindZone.30.unity3d.meta deleted file mode 100644 index 8e90494d..00000000 --- a/Assets/StreamingAssets/streaming_selavatar_WindZone.30.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 8f7aa07b7441a7a4b85bbd5047cb6dc9 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_selavatar_ui.25.unity3d b/Assets/StreamingAssets/streaming_selavatar_ui.25.unity3d index ae425e77..47eb1edb 100644 Binary files a/Assets/StreamingAssets/streaming_selavatar_ui.25.unity3d and b/Assets/StreamingAssets/streaming_selavatar_ui.25.unity3d differ diff --git a/Assets/StreamingAssets/streaming_selavatar_ui.25.unity3d.meta b/Assets/StreamingAssets/streaming_selavatar_ui.25.unity3d.meta deleted file mode 100644 index 77b1af51..00000000 --- a/Assets/StreamingAssets/streaming_selavatar_ui.25.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 76c6dfbc87a3b254bbad8bf8f0a06a5b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.158.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.158.unity3d new file mode 100644 index 00000000..1ddd986e Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.158.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.159.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.159.unity3d deleted file mode 100644 index fd1ab91c..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.159.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.159.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.159.unity3d.meta deleted file mode 100644 index 377a1ccc..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_(0)worldMgr.159.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 8c85f3bc96f5e804490421f52797d1f6 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House11.89.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House11.89.unity3d new file mode 100644 index 00000000..eb46d1ec Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House11.89.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House11.90.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House11.90.unity3d deleted file mode 100644 index 4e605df5..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House11.90.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House11.90.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House11.90.unity3d.meta deleted file mode 100644 index 9dae3d18..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House11.90.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4414e55f573143b4ebc56b81dce48aa8 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House12.91.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House12.91.unity3d new file mode 100644 index 00000000..e2ab78ae Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House12.91.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House12.92.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House12.92.unity3d deleted file mode 100644 index 5d04e111..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House12.92.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House12.92.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House12.92.unity3d.meta deleted file mode 100644 index 9ded2377..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House12.92.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 194b3f3a6eaaa3c47b6499938955a1c8 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House12b.93.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House12b.93.unity3d new file mode 100644 index 00000000..f97f363c Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House12b.93.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House12b.94.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House12b.94.unity3d deleted file mode 100644 index 43ee6f90..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House12b.94.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House12b.94.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House12b.94.unity3d.meta deleted file mode 100644 index f2a1586d..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House12b.94.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 0fc60612f2b7c104fafd382658341671 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House13.95.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House13.95.unity3d new file mode 100644 index 00000000..0aa68ac0 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House13.95.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House13.96.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House13.96.unity3d deleted file mode 100644 index 4eca4d00..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House13.96.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House13.96.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House13.96.unity3d.meta deleted file mode 100644 index 04d914b9..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House13.96.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 901ec95d5d3744f439cdbf7c22cfa69c -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House14.97.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House14.97.unity3d new file mode 100644 index 00000000..fa557d5c Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House14.97.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House14.98.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House14.98.unity3d deleted file mode 100644 index 2bde9e54..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House14.98.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House14.98.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House14.98.unity3d.meta deleted file mode 100644 index 4fdb92b6..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House14.98.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 9d3ce14abd646ab46af5ffbbb2348ce4 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House14b.100.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House14b.100.unity3d deleted file mode 100644 index 9dd9eee3..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House14b.100.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House14b.100.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House14b.100.unity3d.meta deleted file mode 100644 index cf60bfb7..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House14b.100.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 0fd2bf81b1b792f41a08757f6665f026 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House14b.99.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House14b.99.unity3d new file mode 100644 index 00000000..7220fc9e Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House14b.99.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House15.101.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House15.101.unity3d new file mode 100644 index 00000000..0a05d864 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House15.101.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House15.102.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House15.102.unity3d deleted file mode 100644 index 4485df3b..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House15.102.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House15.102.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House15.102.unity3d.meta deleted file mode 100644 index 21cf58f8..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House15.102.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 08adb289a1561784a82d60a5888d6787 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House15b.103.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House15b.103.unity3d new file mode 100644 index 00000000..084bb119 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House15b.103.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House15b.104.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House15b.104.unity3d deleted file mode 100644 index a9ff70bb..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House15b.104.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House15b.104.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House15b.104.unity3d.meta deleted file mode 100644 index 22c822f5..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House15b.104.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: e824baad8ffbab94c8890154472c0576 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House16.105.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House16.105.unity3d new file mode 100644 index 00000000..2d6959a7 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House16.105.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House16.106.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House16.106.unity3d deleted file mode 100644 index 8d0eabdc..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House16.106.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House16.106.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House16.106.unity3d.meta deleted file mode 100644 index 7a329046..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House16.106.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: bb418e49a62fca445b08e73f7eedf197 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House16b.107.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House16b.107.unity3d new file mode 100644 index 00000000..5c30dea7 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House16b.107.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House16b.108.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House16b.108.unity3d deleted file mode 100644 index cac4f3d7..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House16b.108.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House16b.108.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House16b.108.unity3d.meta deleted file mode 100644 index be617391..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House16b.108.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 6584bb27f296e714b8452a36b3c7b080 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House17.109.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House17.109.unity3d new file mode 100644 index 00000000..d4d6b185 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House17.109.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House17.110.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House17.110.unity3d deleted file mode 100644 index 49157034..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House17.110.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House17.110.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House17.110.unity3d.meta deleted file mode 100644 index 4e0a7c2a..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House17.110.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: aa294a888c106524190320dd6912171a -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House19.111.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House19.111.unity3d new file mode 100644 index 00000000..9e481747 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House19.111.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House19.112.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House19.112.unity3d deleted file mode 100644 index eb6fae0c..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House19.112.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House19.112.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House19.112.unity3d.meta deleted file mode 100644 index 7217cb26..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House19.112.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5023fd914ac427143810b20c3251bbfa -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.113.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.113.unity3d new file mode 100644 index 00000000..ef19d9e8 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.113.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.114.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.114.unity3d deleted file mode 100644 index 126f011b..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.114.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.114.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.114.unity3d.meta deleted file mode 100644 index f79db046..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House20_Gate.114.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 7cef994c1595eee4ebdb35a4c835d49d -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20b.115.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House20b.115.unity3d new file mode 100644 index 00000000..e2f5c606 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House20b.115.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20b.116.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House20b.116.unity3d deleted file mode 100644 index 392823ca..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House20b.116.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20b.116.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House20b.116.unity3d.meta deleted file mode 100644 index 2de69c79..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House20b.116.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 849cb9eea0ae0f048ac6546e7f423de4 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20c.117.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House20c.117.unity3d new file mode 100644 index 00000000..c50bee20 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House20c.117.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20c.118.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House20c.118.unity3d deleted file mode 100644 index 9b8f3c17..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House20c.118.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House20c.118.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House20c.118.unity3d.meta deleted file mode 100644 index 5d4a988f..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House20c.118.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 177141be9db08674c99d72d2a62298dc -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House22.119.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House22.119.unity3d new file mode 100644 index 00000000..397b24d6 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House22.119.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House22.120.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House22.120.unity3d deleted file mode 100644 index 0f99b1b5..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House22.120.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House22.120.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House22.120.unity3d.meta deleted file mode 100644 index b72b10ca..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House22.120.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 832d7e41b98ea6240a9c9bfd74503c5e -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House22b.121.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House22b.121.unity3d new file mode 100644 index 00000000..7a0baebc Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House22b.121.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House22b.122.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House22b.122.unity3d deleted file mode 100644 index a74ccf55..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House22b.122.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House22b.122.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House22b.122.unity3d.meta deleted file mode 100644 index ecaabe62..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House22b.122.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2891f9789a12db5479d856a240a0d94d -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House23.123.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House23.123.unity3d new file mode 100644 index 00000000..159c2e33 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House23.123.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House23.124.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House23.124.unity3d deleted file mode 100644 index af130388..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House23.124.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House23.124.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House23.124.unity3d.meta deleted file mode 100644 index a65317b2..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House23.124.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 40a1c5e8057863043bef172015940e75 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House24.125.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House24.125.unity3d new file mode 100644 index 00000000..b5ed623f Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House24.125.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House24.126.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House24.126.unity3d deleted file mode 100644 index e5243e61..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House24.126.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House24.126.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House24.126.unity3d.meta deleted file mode 100644 index c6ed0f2d..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House24.126.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 92ced2991f23ea64d8054c5321e767b0 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26b.127.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House26b.127.unity3d new file mode 100644 index 00000000..5e3cf27f Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House26b.127.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26b.128.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House26b.128.unity3d deleted file mode 100644 index 0b0789d1..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House26b.128.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26b.128.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House26b.128.unity3d.meta deleted file mode 100644 index 3d4f0f1c..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House26b.128.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: bef6c2d6c87dd2849a7219d61d4677da -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26c.129.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House26c.129.unity3d new file mode 100644 index 00000000..e3f7c381 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House26c.129.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26c.130.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House26c.130.unity3d deleted file mode 100644 index d1f3f88e..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House26c.130.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26c.130.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House26c.130.unity3d.meta deleted file mode 100644 index e89177ba..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House26c.130.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5d68e9c2bb13bed41836a171bf847b55 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26d.131.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House26d.131.unity3d new file mode 100644 index 00000000..d873c3fa Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House26d.131.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26d.132.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House26d.132.unity3d deleted file mode 100644 index c7e303c6..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House26d.132.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House26d.132.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House26d.132.unity3d.meta deleted file mode 100644 index 8315cc85..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House26d.132.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 48d2d7b36da4c4a44ac94dd64e33fffb -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House40.133.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House40.133.unity3d new file mode 100644 index 00000000..861b27a0 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House40.133.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House40.134.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House40.134.unity3d deleted file mode 100644 index 6f4c4683..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House40.134.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House40.134.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House40.134.unity3d.meta deleted file mode 100644 index bb0f3c6c..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House40.134.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d629d9ba743a5b040b0a53d3fee34911 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House40b.135.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House40b.135.unity3d new file mode 100644 index 00000000..9626f604 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House40b.135.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House40b.136.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House40b.136.unity3d deleted file mode 100644 index 532b4e5f..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House40b.136.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House40b.136.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House40b.136.unity3d.meta deleted file mode 100644 index 991b62d1..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House40b.136.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 1082e177edbc7cf4b80cd89bf4def406 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.137.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.137.unity3d new file mode 100644 index 00000000..a2dc2eed Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.137.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.138.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.138.unity3d deleted file mode 100644 index d7a651e6..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.138.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.138.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.138.unity3d.meta deleted file mode 100644 index 7456a71c..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House43_platform.138.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 03a94c56f0a431848952081e7f115077 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House44.139.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House44.139.unity3d new file mode 100644 index 00000000..e2800640 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House44.139.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House44.140.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House44.140.unity3d deleted file mode 100644 index 9e1d83c8..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House44.140.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House44.140.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House44.140.unity3d.meta deleted file mode 100644 index b6d7df95..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House44.140.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5354f66a26db8c646acfc7da84f8f22b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House44b.141.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House44b.141.unity3d new file mode 100644 index 00000000..428d2a4b Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House44b.141.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House44b.142.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House44b.142.unity3d deleted file mode 100644 index ab2ac364..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House44b.142.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House44b.142.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House44b.142.unity3d.meta deleted file mode 100644 index d5064057..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House44b.142.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 9a4eb46f7ccd45a4f9769024a09ad2e0 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House9.85.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House9.85.unity3d new file mode 100644 index 00000000..4e59f0ae Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House9.85.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House9.86.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House9.86.unity3d deleted file mode 100644 index f3d85f32..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House9.86.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House9.86.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House9.86.unity3d.meta deleted file mode 100644 index 39b29e39..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House9.86.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b93d9fbec0854294c8090cb28238c819 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House9b.87.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House9b.87.unity3d new file mode 100644 index 00000000..d1b52cd0 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House9b.87.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House9b.88.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House9b.88.unity3d deleted file mode 100644 index f00e7448..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House9b.88.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House9b.88.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House9b.88.unity3d.meta deleted file mode 100644 index b17d0a2a..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House9b.88.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 8f62ea870c3b54f4f8ddb2be5e9a3529 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House_25.83.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House_25.83.unity3d new file mode 100644 index 00000000..c42c051a Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_House_25.83.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House_25.84.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_House_25.84.unity3d deleted file mode 100644 index 285bf627..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_House_25.84.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_House_25.84.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_House_25.84.unity3d.meta deleted file mode 100644 index 487771fe..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_House_25.84.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 140ec1354057e3f4a825d2d861eeec5b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.162.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.162.unity3d new file mode 100644 index 00000000..9d9bd2e8 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.162.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.163.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.163.unity3d deleted file mode 100644 index a4cce124..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.163.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.163.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.163.unity3d.meta deleted file mode 100644 index dd65c482..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_MainCamera.163.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 154c08a17332ecc46a6ccf6aea69da78 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.143.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.143.unity3d new file mode 100644 index 00000000..8c7ad96e Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.143.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.144.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.144.unity3d deleted file mode 100644 index 94f7bfc1..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.144.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.144.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.144.unity3d.meta deleted file mode 100644 index 230ad8f1..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_MarketPlace.144.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 16b56215d58e7e84aba81f50775913aa -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.147.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.147.unity3d new file mode 100644 index 00000000..1efc9881 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.147.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.148.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.148.unity3d deleted file mode 100644 index 5eeeee93..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.148.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.148.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.148.unity3d.meta deleted file mode 100644 index 5e734db7..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_SoundManager.148.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2ed5f43d4c290d24c8bd3095b4476a01 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_Stocks.145.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_Stocks.145.unity3d new file mode 100644 index 00000000..4033124f Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_Stocks.145.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_Stocks.146.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_Stocks.146.unity3d deleted file mode 100644 index af91677f..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_Stocks.146.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_Stocks.146.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_Stocks.146.unity3d.meta deleted file mode 100644 index 8a665eab..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_Stocks.146.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: f0e9b5a7d9b9cfc4aafd632c03decd52 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_showfps.153.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_showfps.153.unity3d new file mode 100644 index 00000000..25c467d8 Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_showfps.153.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_showfps.154.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_showfps.154.unity3d deleted file mode 100644 index 82f39229..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_showfps.154.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_showfps.154.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_showfps.154.unity3d.meta deleted file mode 100644 index 4f8baf7f..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_showfps.154.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: f27730028f5d30947bbeebca0d552ce2 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/streaming_xinshoucun_worldManages.150.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_worldManages.150.unity3d new file mode 100644 index 00000000..a48ccd7a Binary files /dev/null and b/Assets/StreamingAssets/streaming_xinshoucun_worldManages.150.unity3d differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_worldManages.151.unity3d b/Assets/StreamingAssets/streaming_xinshoucun_worldManages.151.unity3d deleted file mode 100644 index 4093f7e9..00000000 Binary files a/Assets/StreamingAssets/streaming_xinshoucun_worldManages.151.unity3d and /dev/null differ diff --git a/Assets/StreamingAssets/streaming_xinshoucun_worldManages.151.unity3d.meta b/Assets/StreamingAssets/streaming_xinshoucun_worldManages.151.unity3d.meta deleted file mode 100644 index a26c9de5..00000000 --- a/Assets/StreamingAssets/streaming_xinshoucun_worldManages.151.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 539f7da49d7f7c74cb12331ed41ddacf -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun.xml b/Assets/StreamingAssets/xinshoucun.xml index 0dc4d357..c6759560 100644 --- a/Assets/StreamingAssets/xinshoucun.xml +++ b/Assets/StreamingAssets/xinshoucun.xml @@ -38,7 +38,7 @@ - + 872.772 @@ -57,7 +57,7 @@ - + 911.887 @@ -76,7 +76,7 @@ - + 917.907 @@ -95,7 +95,7 @@ - + 915.172 @@ -114,7 +114,7 @@ - + 917.8994 @@ -133,7 +133,7 @@ - + 870.3024 @@ -152,7 +152,7 @@ - + 894.9361 @@ -171,7 +171,7 @@ - + 864.9362 @@ -190,7 +190,7 @@ - + 977.5881 @@ -209,7 +209,7 @@ - + 969.5251 @@ -228,7 +228,7 @@ - + 918.1738 @@ -247,7 +247,7 @@ - + 993.3222 @@ -266,7 +266,7 @@ - + 612.2628 @@ -285,7 +285,7 @@ - + 872.2171 @@ -304,7 +304,7 @@ - + 876.1762 @@ -323,7 +323,7 @@ - + 684.6646 @@ -342,7 +342,7 @@ - + 715.7559 @@ -361,7 +361,7 @@ - + 892.9082 @@ -380,7 +380,7 @@ - + 915.4021 @@ -399,7 +399,7 @@ - + 911.4019 @@ -418,7 +418,7 @@ - + 896.9084 @@ -437,7 +437,7 @@ - + 976.9819 @@ -456,7 +456,7 @@ - + 985.0449 @@ -475,7 +475,7 @@ - + 896.6414 @@ -494,7 +494,7 @@ - + 917.9052 @@ -513,7 +513,7 @@ - + 931.36 @@ -532,7 +532,7 @@ - + 883.0934 @@ -551,7 +551,7 @@ - + 920.7994 @@ -570,7 +570,7 @@ - + 940.4466 @@ -589,7 +589,7 @@ - + 876.1923 @@ -608,7 +608,7 @@ - + 945.0803 @@ -627,7 +627,7 @@ - + 922.2796 @@ -646,7 +646,7 @@ - + 669.2735 @@ -665,7 +665,7 @@ - + 623.0557 @@ -684,7 +684,7 @@ - + 775.2821 @@ -703,7 +703,7 @@ - + 729.0643 @@ -722,7 +722,7 @@ - + 878.2375 @@ -741,7 +741,7 @@ - + 939.8698 @@ -760,7 +760,7 @@ - + 827.6368 @@ -779,7 +779,7 @@ - + 645.8775 @@ -798,7 +798,7 @@ - + 751.8861 @@ -817,7 +817,7 @@ - + 724.0674 @@ -836,7 +836,7 @@ - + 947.9696 @@ -855,7 +855,7 @@ - + 900.8734 @@ -874,7 +874,7 @@ - + 911.5487 @@ -893,7 +893,7 @@ - + 946.0933 @@ -912,7 +912,7 @@ - + 787.3232 @@ -931,7 +931,7 @@ - + 770.4507 @@ -950,7 +950,7 @@ - + 780.4453 @@ -969,7 +969,7 @@ - + 786.0005 @@ -988,7 +988,7 @@ - + 697.9321 @@ -1007,7 +1007,7 @@ - + 809.8137 @@ -1026,7 +1026,7 @@ - + 697.9321 @@ -1045,7 +1045,7 @@ - + 815.1574 @@ -1064,7 +1064,7 @@ - + 803.2246 @@ -1083,7 +1083,7 @@ - + 807.0703 @@ -1102,7 +1102,7 @@ - + 691.6553 @@ -1121,7 +1121,7 @@ - + 864.0751 @@ -1140,7 +1140,7 @@ - + 769.4612 @@ -1159,7 +1159,7 @@ - + 859.5603 @@ -1178,7 +1178,7 @@ - + 709.9977 @@ -1197,7 +1197,7 @@ - + 739.639 @@ -1216,7 +1216,7 @@ - + 742.4661 @@ -1235,7 +1235,7 @@ - + 742.4661 @@ -1254,7 +1254,7 @@ - + 846.2157 @@ -1273,7 +1273,7 @@ - + 895.7923 @@ -1292,7 +1292,7 @@ - + 816.2485 @@ -1311,7 +1311,7 @@ - + 866.5632 @@ -1330,7 +1330,7 @@ - + 719.3578 @@ -1349,7 +1349,7 @@ - + 728.0051 @@ -1368,7 +1368,7 @@ - + 884.9523 @@ -1387,7 +1387,7 @@ - + 615.0786 @@ -1406,7 +1406,7 @@ - + 884.9523 @@ -1425,7 +1425,7 @@ - + 753.0613 @@ -1444,7 +1444,7 @@ - + 707.6697 @@ -1463,7 +1463,7 @@ - + 707.6697 @@ -1482,7 +1482,7 @@ - + 765.338 @@ -1501,7 +1501,7 @@ - + 819.824 @@ -1521,7 +1521,7 @@ - + 847.2104 @@ -1540,7 +1540,7 @@ - + 1002.744 @@ -1559,7 +1559,7 @@ - + 707.6234 @@ -1578,7 +1578,7 @@ - + 0 @@ -1597,7 +1597,7 @@ - + 816.8759 @@ -1616,7 +1616,7 @@ - + 771.5861 @@ -1635,7 +1635,7 @@ - + 940.357 @@ -1654,7 +1654,7 @@ - + 941.3931 @@ -1673,7 +1673,7 @@ - + 736.5895 @@ -1692,7 +1692,7 @@ - + 0 @@ -1711,7 +1711,7 @@ - + 1265.76 @@ -1730,7 +1730,7 @@ - + 772.2379 diff --git a/Assets/StreamingAssets/xinshoucun_1_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_1.unity3d.meta deleted file mode 100644 index bc8807de..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d53ea1af467af4b4fb7d0b136bb0b51b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_1_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_2.unity3d.meta deleted file mode 100644 index 1ba1df5a..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: f0a100e35ebc21b4c9080d852765c62a -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_1_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_3.unity3d.meta deleted file mode 100644 index f11e6460..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: fcd7cffbe84d5c54c96e523be4918d5f -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_1_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_4.unity3d.meta deleted file mode 100644 index 8d7ab28e..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4e64391ff2a60de4281ff1c605741df7 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_1_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_5.unity3d.meta deleted file mode 100644 index 6f09f3c0..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 568d1bcf35e86c54ea1b98d8efa39c18 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_1_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_6.unity3d.meta deleted file mode 100644 index ab6d6f4a..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: e468861f8e8965644a88b7124fd5ac18 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_1_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_7.unity3d.meta deleted file mode 100644 index 99b1dd1f..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: c2e77f71023f78a4da40ba5145b67cd3 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_1_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_1_8.unity3d.meta deleted file mode 100644 index cc176c7f..00000000 --- a/Assets/StreamingAssets/xinshoucun_1_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 8cc9d84ba9282ee458d18a8a09bb0074 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_1.unity3d.meta deleted file mode 100644 index 42f89f02..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 26492d0fe67281a46b1ab2c8c7cd9cbe -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_2.unity3d.meta deleted file mode 100644 index e11265de..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4b3ab1893b8c7be4d96816fbc44ed83b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_3.unity3d.meta deleted file mode 100644 index 1fbb663b..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4a5704652eced61438570d15e1d8dcf0 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_4.unity3d.meta deleted file mode 100644 index 73b36afa..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b54132fc962fc524c8f8d976f37af551 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_5.unity3d.meta deleted file mode 100644 index a52bd73a..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: af4e8758e9272364f8080cda280b7d3e -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_6.unity3d.meta deleted file mode 100644 index dcc18756..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5a4a18df99cd29944b012b2cfb3fd3ab -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_7.unity3d.meta deleted file mode 100644 index d813cbb7..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2f3feb4586e4acf49b43f2208ff02ac9 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_2_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_2_8.unity3d.meta deleted file mode 100644 index 5582ec63..00000000 --- a/Assets/StreamingAssets/xinshoucun_2_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: bb016aac0e5d3564d9eb965ecadc3ce5 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_1.unity3d.meta deleted file mode 100644 index f369560d..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: e28d33bd66ecdfc4da911912425721ac -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_2.unity3d.meta deleted file mode 100644 index 125cab70..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 06cc5a80fadffea4793b72bf9867e4b7 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_3.unity3d.meta deleted file mode 100644 index 1ec2acc1..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 04337e4dfe40f374aa02c23462d239ac -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_4.unity3d.meta deleted file mode 100644 index 0904f4f3..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 39fbf874768180046a272a22e72bd3c2 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_5.unity3d.meta deleted file mode 100644 index 188288b0..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4bfb397a6bc48fb478638ef8d44af437 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_6.unity3d.meta deleted file mode 100644 index b0c9e65a..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b93c94b033af1184fbf66c554246d0f0 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_7.unity3d.meta deleted file mode 100644 index 6fee4f1e..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 26c80ee1dc74a7b43b0ab46d89d9153c -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_3_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_3_8.unity3d.meta deleted file mode 100644 index e7146b9b..00000000 --- a/Assets/StreamingAssets/xinshoucun_3_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 1889b8bb1333fcf4aa85a8c039c4160b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_1.unity3d.meta deleted file mode 100644 index 4388922f..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5084bfb23c9f86e49a59523631765164 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_2.unity3d.meta deleted file mode 100644 index 6d9b1943..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 802a210e19b099d489f34f60d3db1e5b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_3.unity3d.meta deleted file mode 100644 index 167c02b1..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d20d21f78199c6e4da0cf136ab7f8e58 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_4.unity3d.meta deleted file mode 100644 index e1452788..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 35efd6c614fdc9a46b314749a9044cf3 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_5.unity3d.meta deleted file mode 100644 index bfecc3cd..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 557d5725e5c3c4343a7de2abf50d1bb5 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_6.unity3d.meta deleted file mode 100644 index c214d59f..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: aa3ddfad5dc1f6149b92bb4f6c88cd60 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_7.unity3d.meta deleted file mode 100644 index f60513d8..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 0aaded49d08b79e4cb2e24341e2c1070 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_4_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_4_8.unity3d.meta deleted file mode 100644 index 48c3d1fd..00000000 --- a/Assets/StreamingAssets/xinshoucun_4_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 110c63a5a18484a4db7da8758deb7c54 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_1.unity3d.meta deleted file mode 100644 index ecc0cf78..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d6e21ce4f3d87c743b45a430efb9f9fe -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_2.unity3d.meta deleted file mode 100644 index 57251f31..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 923e2e6b04b5e77488274d19775f5048 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_3.unity3d.meta deleted file mode 100644 index 4135d08c..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2746446e4537427418bcd9e224c5e931 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_4.unity3d.meta deleted file mode 100644 index 49ee5755..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 7584eb73ada8f394d83ed6519ba5c701 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_5.unity3d.meta deleted file mode 100644 index 22fff62d..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 9303e4495e43e794088a4e5e697fbed6 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_6.unity3d.meta deleted file mode 100644 index 539aecc7..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 3dc3cb0166d570e438e51b07b06c90f8 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_7.unity3d.meta deleted file mode 100644 index a0b41de3..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: caaa22f08ce07504fa07049bb24c184a -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_5_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_5_8.unity3d.meta deleted file mode 100644 index ea3648d4..00000000 --- a/Assets/StreamingAssets/xinshoucun_5_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4f04e9776000edc4e89b0582a4039140 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_1.unity3d.meta deleted file mode 100644 index 8550ae00..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 220fdc91eb1636841ae152770926dc56 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_2.unity3d.meta deleted file mode 100644 index 3b7a847d..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 1a688f5dee3c57f41b903356d6b4f79e -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_3.unity3d.meta deleted file mode 100644 index 74596c86..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: fbc7677caf31a1d47981bcced7f427cb -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_4.unity3d.meta deleted file mode 100644 index 7bf9fa82..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 0b80b1233a4934241bf44fc810c9ffa4 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_5.unity3d.meta deleted file mode 100644 index 9a5f272d..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: bceea653e67c73545bce60f3d6e0e184 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_6.unity3d.meta deleted file mode 100644 index 1cfd7f24..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: b5d53a90b1926134eb9e5feed4fc1ef5 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_7.unity3d.meta deleted file mode 100644 index 168584c0..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: a0ae2e746f5ebe8479d5b219c2d0515b -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_6_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_6_8.unity3d.meta deleted file mode 100644 index 7fb517c9..00000000 --- a/Assets/StreamingAssets/xinshoucun_6_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: cee98e7f6a186da48b9683905475e1c0 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_1.unity3d.meta deleted file mode 100644 index be8d4f53..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 22e0f7a813a4c8f4daa321cb03e28424 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_2.unity3d.meta deleted file mode 100644 index f15d9b5e..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4670b1dcf2dcd9544a79335113ad02cd -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_3.unity3d.meta deleted file mode 100644 index a8388ccc..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 351f89cdebb09fb4da9f68453b6efea6 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_4.unity3d.meta deleted file mode 100644 index 17939022..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 8213a90f7e4325d419c44c34be6c0a70 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_5.unity3d.meta deleted file mode 100644 index 5b05d7af..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 148f7f47d57ff4147b4a41367e1d6fb3 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_6.unity3d.meta deleted file mode 100644 index f05b4c9d..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: d475557b12495844ea1e359a120d5b30 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_7.unity3d.meta deleted file mode 100644 index 763d2a16..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2329adb5450837248981d65993fcfb71 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_7_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_7_8.unity3d.meta deleted file mode 100644 index 97503a32..00000000 --- a/Assets/StreamingAssets/xinshoucun_7_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2103dd5c113415742a2dd2745aa7659d -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_1.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_1.unity3d.meta deleted file mode 100644 index f15e9938..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_1.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 2363642217dcce9479356813c5dabbb7 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_2.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_2.unity3d.meta deleted file mode 100644 index ce80fc80..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_2.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 5d6dc0a8f046f9c4a9bf1b0a8f8f4f63 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_3.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_3.unity3d.meta deleted file mode 100644 index 34316f30..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_3.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: ee28987cb54a05e49a2bd785762eb4d2 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_4.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_4.unity3d.meta deleted file mode 100644 index a19bee75..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_4.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 48a05a0fc7566e249b054e0f3a4f934d -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_5.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_5.unity3d.meta deleted file mode 100644 index f66b5aa6..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_5.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: c93096cc2602db540a02774ad20b0975 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_6.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_6.unity3d.meta deleted file mode 100644 index 6fb0e785..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_6.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 97a33013c4ae38c42bfba16df5066092 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_7.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_7.unity3d.meta deleted file mode 100644 index 62fe9237..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_7.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 166faa65e7eddc449a949af30c81f872 -DefaultImporter: - userData: diff --git a/Assets/StreamingAssets/xinshoucun_8_8.unity3d.meta b/Assets/StreamingAssets/xinshoucun_8_8.unity3d.meta deleted file mode 100644 index b767da13..00000000 --- a/Assets/StreamingAssets/xinshoucun_8_8.unity3d.meta +++ /dev/null @@ -1,4 +0,0 @@ -fileFormatVersion: 2 -guid: 4a2d1458f719dc343acb5013801e0d41 -DefaultImporter: - userData: diff --git a/Assets/font/ui_font_source.txt b/Assets/font/ui_font_source.txt index 2316c825..f3f5c572 100644 --- a/Assets/font/ui_font_source.txt +++ b/Assets/font/ui_font_source.txt @@ -93,14 +93,14 @@ STRING - + 204 重新登录 快速与网关建立交互关系(前提是之前已经登录了, 之后断开在服务器判定该前端的Entity未超时销毁的前提下可以快速与服务器建立连接并达到操控该entity的目的) UINT64 INT32 - + 205 diff --git a/Assets/scenes/go.unity b/Assets/scenes/go.unity deleted file mode 100644 index 776a20ba..00000000 Binary files a/Assets/scenes/go.unity and /dev/null differ diff --git a/Assets/scenes/selavatar/selavatar.unity b/Assets/scenes/selavatar/selavatar.unity index 171fe428..84be9503 100644 Binary files a/Assets/scenes/selavatar/selavatar.unity and b/Assets/scenes/selavatar/selavatar.unity differ diff --git a/Assets/scenes/start.unity b/Assets/scenes/start.unity new file mode 100644 index 00000000..2a662672 Binary files /dev/null and b/Assets/scenes/start.unity differ diff --git a/Assets/scenes/go.unity.meta b/Assets/scenes/start.unity.meta similarity index 100% rename from Assets/scenes/go.unity.meta rename to Assets/scenes/start.unity.meta diff --git a/Assets/scripts/common/Common.cs b/Assets/scripts/common/Common.cs index 0cc0c7da..feff85be 100644 Binary files a/Assets/scripts/common/Common.cs and b/Assets/scripts/common/Common.cs differ diff --git a/Assets/scripts/gameui/Hud_Infos.cs b/Assets/scripts/gameui/Hud_Infos.cs index 5adc8acb..a0c85d80 100644 Binary files a/Assets/scripts/gameui/Hud_Infos.cs and b/Assets/scripts/gameui/Hud_Infos.cs differ diff --git a/Assets/scripts/gameui/game_ui_autopos.cs b/Assets/scripts/gameui/game_ui_autopos.cs index f95981cb..1d1e840b 100644 Binary files a/Assets/scripts/gameui/game_ui_autopos.cs and b/Assets/scripts/gameui/game_ui_autopos.cs differ diff --git a/Assets/scripts/go/clientapp.cs b/Assets/scripts/go/clientapp.cs new file mode 100644 index 00000000..0b99af15 Binary files /dev/null and b/Assets/scripts/go/clientapp.cs differ diff --git a/Assets/Plugins/kbengine/clientapp.cs.meta b/Assets/scripts/go/clientapp.cs.meta similarity index 78% rename from Assets/Plugins/kbengine/clientapp.cs.meta rename to Assets/scripts/go/clientapp.cs.meta index c48b7ef2..51747e5c 100644 --- a/Assets/Plugins/kbengine/clientapp.cs.meta +++ b/Assets/scripts/go/clientapp.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 60487746b6443e44797c357a33573215 +guid: 7e1d043ce7b3ec64bacdf2b1b7b9622f MonoImporter: serializedVersion: 2 defaultReferences: [] diff --git a/Assets/scripts/loadingbar/loadingbar.cs b/Assets/scripts/loadingbar/loadingbar.cs index 62f31307..e3e9ed4a 100644 Binary files a/Assets/scripts/loadingbar/loadingbar.cs and b/Assets/scripts/loadingbar/loadingbar.cs differ diff --git a/Assets/scripts/login/ui.cs b/Assets/scripts/login/ui.cs index 4734ea23..0df4184a 100644 Binary files a/Assets/scripts/login/ui.cs and b/Assets/scripts/login/ui.cs differ diff --git a/Assets/scripts/selavatar/selavatar_ui.cs b/Assets/scripts/selavatar/selavatar_ui.cs index e54d8587..db42bae2 100644 Binary files a/Assets/scripts/selavatar/selavatar_ui.cs and b/Assets/scripts/selavatar/selavatar_ui.cs differ diff --git a/Assets/scripts/world/KBEEventProc.cs b/Assets/scripts/world/KBEEventProc.cs index 811a7903..cf40b69f 100644 Binary files a/Assets/scripts/world/KBEEventProc.cs and b/Assets/scripts/world/KBEEventProc.cs differ diff --git a/Assets/scripts/world/Scene.cs b/Assets/scripts/world/Scene.cs index 06e7cdf9..7d974176 100644 Binary files a/Assets/scripts/world/Scene.cs and b/Assets/scripts/world/Scene.cs differ diff --git a/Assets/scripts/world/SceneEntityObject.cs b/Assets/scripts/world/SceneEntityObject.cs index 10ed8ad1..76cb2bcb 100644 Binary files a/Assets/scripts/world/SceneEntityObject.cs and b/Assets/scripts/world/SceneEntityObject.cs differ diff --git a/Assets/scripts/world/TargetManger.cs b/Assets/scripts/world/TargetManger.cs index 4459e24e..983dd833 100644 Binary files a/Assets/scripts/world/TargetManger.cs and b/Assets/scripts/world/TargetManger.cs differ diff --git a/Assets/thirdparty/Fantasy_Village_01/Common/EnvironmentFX/FBX/clouddome.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Common/EnvironmentFX/FBX/clouddome.fbm.meta deleted file mode 100644 index 1a702b2a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Common/EnvironmentFX/FBX/clouddome.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 256c1569194828347b10a5dfa52e82b5 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Common/GUI/objects/RoundPlane.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Common/GUI/objects/RoundPlane.fbm.meta deleted file mode 100644 index 5f22106c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Common/GUI/objects/RoundPlane.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 3da72ab4ea466c14eb23636a6b03462f -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_chair_08.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_chair_08.fbm.meta deleted file mode 100644 index c811065f..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_chair_08.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6b9c068d6d1834a49bba5cda5e2e2c60 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_counter_03.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_counter_03.fbm.meta deleted file mode 100644 index e860d0d4..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_counter_03.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 0c8956263433e1c4596b378c82c0d363 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_cupboard_01.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_cupboard_01.fbm.meta deleted file mode 100644 index 9125569e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_cupboard_01.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 262788bc0366b9b4cb9f015848b6ceb7 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_desk_01.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_desk_01.fbm.meta deleted file mode 100644 index 5fd05e89..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_desk_01.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: fe1856a93851cc444a8b6f74c44bb33a -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_desk_02.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_desk_02.fbm.meta deleted file mode 100644 index 1ea827db..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_desk_02.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 4b6eae02cf659f94cab2cc67215d35b2 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_fireplace_04.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_fireplace_04.fbm.meta deleted file mode 100644 index a8688cce..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_fireplace_04.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 34cf7c5611205714db52eb0f46dd5276 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_furniture_setup_01.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_furniture_setup_01.fbm.meta deleted file mode 100644 index 4d5eafce..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_furniture_setup_01.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 5cd8039d4cb921047b091c8020fae144 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_rug_05.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_rug_05.fbm.meta deleted file mode 100644 index 33b392bd..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_rug_05.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 5dab2f810808ab74c9edc9f5b576159a -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_shelf_03.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_shelf_03.fbm.meta deleted file mode 100644 index 8bec421c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_shelf_03.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 27c822a22a51d2d4f936d9c00f5fba90 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_table_10.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_table_10.fbm.meta deleted file mode 100644 index 493e6658..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Furniture_02/FV01_furniture_02_FBX/FV01_table_10.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e793a660f87597341b86a1d7404547c8 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_01_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_01_LOD0.fbm.meta deleted file mode 100644 index 337529f9..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_01_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 05c65c0212d21e5488b1b592b78a314e -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_01_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_01_LOD1.fbm.meta deleted file mode 100644 index cd2a570d..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_01_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: a56457df2074afd43ba226c1178a4fcf -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_02_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_02_LOD0.fbm.meta deleted file mode 100644 index ea0125c8..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_02_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: dc98b343b621f4e4ab6f263fa8782c09 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_03_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_03_LOD0.fbm.meta deleted file mode 100644 index b61bb9ca..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_03_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 5ac15cbf553cc764abcf020484db931a -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_03b_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_03b_LOD0.fbm.meta deleted file mode 100644 index 3eebf255..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_03b_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e77e4c935472ae54788ce85e45f98a8c -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_04_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_04_LOD0.fbm.meta deleted file mode 100644 index 1f4199d0..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_04_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6b8b2682490213b4fac6eabffb143cba -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_05_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_05_LOD0.fbm.meta deleted file mode 100644 index 7702de15..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_05_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 5564a5e048bac0146b200745b5cae365 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_05b_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_05b_LOD0.fbm.meta deleted file mode 100644 index dfc961b9..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_05b_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 49cdd36c3cf4392428eda8ad175e44c3 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_06_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_06_LOD0.fbm.meta deleted file mode 100644 index 7685d414..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_06_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 245e7a71a59abf844b7ee26a9e103440 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_07_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_07_LOD0.fbm.meta deleted file mode 100644 index fdbc3486..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_07_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f99e0046bedf8f14790ba6eb2072d283 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_08_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_08_LOD0.fbm.meta deleted file mode 100644 index f722e7ed..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_08_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 78c5c96623383bf478af266675a7b1ad -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_09_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_09_LOD0.fbm.meta deleted file mode 100644 index 19a0054a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_HouseAddOns_02/FV01_HouseAddOns_02_FBX/FV01_HousePart_09_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 211afe4cd8125084a8694ae59864af35 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD0.fbm.meta deleted file mode 100644 index 51a909ee..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 0024cf9d88b8b7e4b8b739c6442f7603 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD1.fbm.meta deleted file mode 100644 index 03ffa96c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 72c3694d7cfa24a498601e7ed93cdc3b -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD2.fbm.meta deleted file mode 100644 index 52b304ca..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_09/FV01_House_09_FBX/FV01_House_09_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6ddf5a04326d2ce4a9f5cc5677bd8241 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD0.fbm.meta deleted file mode 100644 index 83b62a16..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: dd51d24a59ab9a64b9de5213bba007c8 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD1.fbm.meta deleted file mode 100644 index 1ce153c7..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f9dbc85d600307e47ad281d51a967d48 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD2.fbm.meta deleted file mode 100644 index 7ab53478..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_11/FV01_House_11_FBX/FV01_House_11_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 467c85cb713ed1248b568d273eecb92e -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD0.fbm.meta deleted file mode 100644 index 6a697a7a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f9c32c19860de3848bc34efd3fdabc4b -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD1.fbm.meta deleted file mode 100644 index 86c9d8da..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 438df715782f90f42816f61a749653e9 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD2.fbm.meta deleted file mode 100644 index 0557dac4..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_12/FV01_House_12_FBX/FV01_House_12_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 4f9b99e984120af4f8e0e65b276f456e -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD0.fbm.meta deleted file mode 100644 index 59b27e12..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 8d8898e49caec3f4eb11c1f8ad7d64be -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD1.fbm.meta deleted file mode 100644 index 0426acf6..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 09c7e79880427964195bb28dc1f1a956 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD2.fbm.meta deleted file mode 100644 index 270d717d..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 615a712929ffd9e489f9dc56945dc7c0 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_Proxy.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_Proxy.fbm.meta deleted file mode 100644 index d37fece9..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_13/FV01_House_13_FBX/FV01_House_13_Proxy.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 450545c6161f4d34b8d6b47455c46e15 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD0.fbm.meta deleted file mode 100644 index 28136aa4..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 0d7fa091a9450374087c2d63f77aa6b9 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD1.fbm.meta deleted file mode 100644 index d10e8931..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: ff4c1dec26f478c4ca58523c05a9eacb -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD2.fbm.meta deleted file mode 100644 index 6c22a331..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_14/FV01_House_14_FBX/FV01_House_14_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 82b277b8ee00baf459258fef12c8f5e7 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD0.fbm.meta deleted file mode 100644 index 32eb7cd2..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 1ce57b82c3337294c9dc50b1efc0aa65 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD1.fbm.meta deleted file mode 100644 index e0af039e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 711b66d5ec7c4494bba428b6931fa894 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD2.fbm.meta deleted file mode 100644 index eb490be5..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_15/FV01_House_15_FBX/FV01_House_15_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 451e489e486ea6f4788a5ba3ede8301f -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD0.fbm.meta deleted file mode 100644 index 0bde3015..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f1b64a02b9b962e47bb99e6665b54d9c -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD1.fbm.meta deleted file mode 100644 index 707f5d6a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 1310e43c779b6ff4cabbd39c198db604 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD2.fbm.meta deleted file mode 100644 index 5f4f3506..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6666d616c967c2f43b8733df32eb2947 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD3.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD3.fbm.meta deleted file mode 100644 index bc24af7a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_16/FV01_House_16_FBX/FV01_House_16_LOD3.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 36c80cca36705eb4b82017ba971b7ad0 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD0.fbm.meta deleted file mode 100644 index ed70c24f..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f287b307d0539204f804f21e345ac054 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD1.fbm.meta deleted file mode 100644 index 7d97b93a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e4b057fa9e782af44a6c98b99fbc9fe8 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD2.fbm.meta deleted file mode 100644 index c3d4b10c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_17/FV01_House_17_FBX/FV01_House_17_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 578a49f87f35f6143a29f70a66ade794 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD0.fbm.meta deleted file mode 100644 index b8122ae7..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e1e57a63a92fa4c4482bebbbcab5092b -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD1.fbm.meta deleted file mode 100644 index 212293c7..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 5197f4847e81c8c479e7f3b376e03457 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD2.fbm.meta deleted file mode 100644 index f2a1373a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_19_FBX/FV01_House_19_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: cd443f12073f35c4dbe892ecf1790854 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD0.fbm.meta deleted file mode 100644 index 99de425b..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 641f441f62562bb4b8d172727ca985f2 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD1.fbm.meta deleted file mode 100644 index 31b92e2d..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: a5ab3b6f996a66849b2509b292e452ed -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD2.fbm.meta deleted file mode 100644 index b191f002..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_19/FV01_House_23/FV01_House_23_FBX/FV01_House_23_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: dabc0004495e69447b9317eedc865078 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD0.fbm.meta deleted file mode 100644 index 90754bd9..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 86e4c25fc20db9c4ba462a6d1e27c172 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD1.fbm.meta deleted file mode 100644 index 9a6ba57a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6724f3cdf5b494a46a4b2c7369bf3cd9 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD2.fbm.meta deleted file mode 100644 index bab1026c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_20/FV01_House_20_FBX/FV01_House_20_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 153e81da0288ea64495883d87f4f9649 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD0.fbm.meta deleted file mode 100644 index eaec088e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6c18262ce776ba444af635587ab3ea8b -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD1.fbm.meta deleted file mode 100644 index 82f27f9a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: d2ce0a6ff0783c443bab5a0b90b95524 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD2.fbm.meta deleted file mode 100644 index 597a830c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_22/FV01_House_22_FBX/FV01_House_22_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e72465a57c7acc041ab0ee7d4cefb795 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD0.fbm.meta deleted file mode 100644 index 5e7afed4..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 67bc7fad5dfbb0f4e8bb8e1a97e80d9e -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD1.fbm.meta deleted file mode 100644 index 009e042e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 68819f8dd02dfde4d8566fb5d06008e7 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD2.fbm.meta deleted file mode 100644 index 430b92ea..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_24/FV01_House_24_FBX/FV01_House_24_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f6e0f35ae76b6dc4aa2c6323057abdb8 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD0.fbm.meta deleted file mode 100644 index 6baa3e91..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e8a8a44f51fdb1e43b71381adb9a3732 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD1.fbm.meta deleted file mode 100644 index ecbc9ece..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 57c14cdd05367794ca17b339f3b15740 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD2.fbm.meta deleted file mode 100644 index 5f69004b..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_25/FV01_House_25_FBX/FV01_House_25_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 695eb2964303a5643a410d5c7d1a58e9 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD0.fbm.meta deleted file mode 100644 index 891379c4..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 7cf340d483d67c244a26fea2dda9bfc9 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD1.fbm.meta deleted file mode 100644 index 074990d2..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 341ca6b7a6e43a24db7fefa3a526c18d -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD2.fbm.meta deleted file mode 100644 index 4c8210d9..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_26/FV01_House_26_FBX/FV01_House_26_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f8c16226535c3c840bc9b6148f10ce03 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD0.fbm.meta deleted file mode 100644 index beb442e8..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e76da43245606bf4db88ff1fa247713f -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD1.fbm.meta deleted file mode 100644 index e7850359..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: d7f56b9a7ea51a243a057bae843ec0b7 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD2.fbm.meta deleted file mode 100644 index d8ca144e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_40/FV01_House_40_FBX/FV01_House_40_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: dfdd52383a4d92044b9194a9112930a3 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_Border_43_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_Border_43_LOD0.fbm.meta deleted file mode 100644 index 6552927e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_Border_43_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: af1af5c76850fa34aa030a63f25efc14 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD0.fbm.meta deleted file mode 100644 index 74bbe1f8..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 88ecbd23bcaab6f44820c1b13d241a83 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD1.fbm.meta deleted file mode 100644 index 10d502cb..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 29abddb26f31a47438bb9aca0eb74620 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD2.fbm.meta deleted file mode 100644 index 50c84865..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f09e306aab692e842ac19709628bab62 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43b_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43b_LOD0.fbm.meta deleted file mode 100644 index 07f41365..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_43/FV01_House_43_FBX/FV01_House_43b_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: a9344497b9989c148804d24c73c0b63e -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD0.fbm.meta deleted file mode 100644 index 27c3e643..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: b672169f1266a674e93feb9c9dc5b1c7 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD1.fbm.meta deleted file mode 100644 index 11db9e30..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f7febe8ca9210674eacb523e9374df42 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD2.fbm.meta deleted file mode 100644 index 3274fb70..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_44/FV01_House_44_FBX/FV01_House_44_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 8674cea10a2f82d49a67d38546afaf28 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_45/FV01_House_45_FBX/FV01_House_45_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_45/FV01_House_45_FBX/FV01_House_45_LOD0.fbm.meta deleted file mode 100644 index f6438e68..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_45/FV01_House_45_FBX/FV01_House_45_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 42683310b236bca4cb7db38387ee76f2 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_45/FV01_House_45_FBX/FV01_House_45_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_45/FV01_House_45_FBX/FV01_House_45_LOD1.fbm.meta deleted file mode 100644 index 96e0b985..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_House_45/FV01_House_45_FBX/FV01_House_45_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 1e71124509c50b64f85cd58ea5133cfc -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_01_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_01_LOD0.fbm.meta deleted file mode 100644 index dfa24b8e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_01_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: bd7ab9c8b7aad9740922b08a0d415d50 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_02_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_02_LOD0.fbm.meta deleted file mode 100644 index e7d0e959..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_02_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6bb63e29420ab19469f4ff059db84464 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_03_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_03_LOD0.fbm.meta deleted file mode 100644 index b4e9f5f1..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_03_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 0803c9a1a1efa6b449f7a57f26f5d1d1 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_04_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_04_LOD0.fbm.meta deleted file mode 100644 index fd1424c4..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_04_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 1db1d66c80a09024c80b96e0edd428a2 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_05_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_05_LOD0.fbm.meta deleted file mode 100644 index 0dda7d0d..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_05_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 4eb5540cf395caf4798c9b00dac51b7a -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD0.fbm.meta deleted file mode 100644 index ce25a9e3..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 6eafd6d24617e274a9793b16cbe8afdc -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD1.fbm.meta deleted file mode 100644 index fd6bdf99..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 5b3d1325ad82aaf4f8e07c156a9e6dc0 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD2.fbm.meta deleted file mode 100644 index 3c2904d5..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_06_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 8076a561129995043a698a236ce4bbb8 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD0.fbm.meta deleted file mode 100644 index eeb475df..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 9995266dbab8f6440ba24d316240e6bb -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD1.fbm.meta deleted file mode 100644 index 635c6892..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 09880065d89871c40997097ca978467b -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD2.fbm.meta deleted file mode 100644 index 759b6674..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_07_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: bc8a3300fe3d3e3459eb3c35cd9a33b0 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD0.fbm.meta deleted file mode 100644 index ee66ad61..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 20284cf0928c02748bb6900ea03adcc1 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD1.fbm.meta deleted file mode 100644 index 0ac1defd..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: c0603d75a5e30f143a3c35eef7099cdd -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD2.fbm.meta deleted file mode 100644 index c1cf49a2..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_08_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 81f9070f9cc7e5f4cbef5b3676b055e9 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD0.fbm.meta deleted file mode 100644 index a6c756dc..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 39de4658e5dbaf442aa8693944c21c34 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD1.fbm.meta deleted file mode 100644 index 5436ef27..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 9daa3522161ab9841a9f8f531afaeb87 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD2.fbm.meta deleted file mode 100644 index 465f631a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_09_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 0c01e9a59be036749bb0d5b3558b9ab3 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD0.fbm.meta deleted file mode 100644 index 59e7c6ca..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: da914a15e0919284991d46ae7926511b -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD1.fbm.meta deleted file mode 100644 index 5d7f5181..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: f3fcefb69cd1f024b905646a6d193dde -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD2.fbm.meta deleted file mode 100644 index e7c7c3d0..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_MarketPlace_01/FV01_MarketPlace_01_FBX/FV01_MarketPlace_10_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: a242012fbcdb2f645a4a8e20d729fa72 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_05_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_05_LOD0.fbm.meta deleted file mode 100644 index 062195ca..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_05_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 2e4af74c0aeef7840a1091710165f1a0 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_05_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_05_LOD1.fbm.meta deleted file mode 100644 index 7cbc57ee..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_05_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 460414c35e29c7f4e94c93708f8bcad6 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_06_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_06_LOD0.fbm.meta deleted file mode 100644 index eb93efd5..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_06_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: bccaf6e6498ac4c46a87737af44f167c -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_06_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_06_LOD1.fbm.meta deleted file mode 100644 index 0306b930..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_06_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 286ede720f4c2ac42a82fa4cf09140aa -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_07_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_07_LOD0.fbm.meta deleted file mode 100644 index cc9b2663..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_07_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: a2518236f9b4c55409f0015da6bcc52f -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_07_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_07_LOD1.fbm.meta deleted file mode 100644 index 7eedd673..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Banner_07_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 761d2fe7032c39a408aa5190c87b0568 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Cart_03_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Cart_03_LOD0.fbm.meta deleted file mode 100644 index 7a074bb6..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Cart_03_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 01d6a4ce7f22bcd4cbe8ab66cc323476 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Cart_03_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Cart_03_LOD1.fbm.meta deleted file mode 100644 index 67302cef..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Cart_03_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: ed2402fe6c8cdd7489c5064870897d9c -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD0.fbm.meta deleted file mode 100644 index fc479c4c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: a669d91b6fab6b04fb72f88428cf14e8 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD1.fbm.meta deleted file mode 100644 index 6dfda53d..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 1f225f10e670a7f47a6d796ed500a81c -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD2.fbm.meta deleted file mode 100644 index 50edfbd8..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Crane_01_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: de5a4d85be317af459da285525d42871 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD0.fbm.meta deleted file mode 100644 index 17a7dc85..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 85cf1c92ef1dfcb4ca42c89a33386a29 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD1.fbm.meta deleted file mode 100644 index e86c971c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 1f16512b6c75d9e419a305cfee102a6b -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD2.fbm.meta deleted file mode 100644 index bdfb17a2..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_FakeDoor_01_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 5ab1aa9750f0f214cbf0f3b32a3a2c0e -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Stairs_01_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Stairs_01_LOD0.fbm.meta deleted file mode 100644 index d1a51d35..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Stairs_01_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: d507d5094a1c1df4b932a6728b780b12 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Stairs_01_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Stairs_01_LOD1.fbm.meta deleted file mode 100644 index 65796c81..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_Stairs_01_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: b2e19c27d495fea469cc6b8320c06263 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_cratestack_02_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_cratestack_02_LOD0.fbm.meta deleted file mode 100644 index 95d7c232..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_cratestack_02_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 729d81513c0eeca4cba8b2e2f464efba -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_cratestack_02_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_cratestack_02_LOD1.fbm.meta deleted file mode 100644 index 9e86a0d3..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_cratestack_02_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 2273514f61e157c40af7281e55bcdc85 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_highfence_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_highfence_LOD0.fbm.meta deleted file mode 100644 index e22d9237..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_highfence_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 1f8cf352a1d21ec409c36f992fd3edad -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_01_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_01_LOD0.fbm.meta deleted file mode 100644 index 3a06e0cc..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_01_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 9a39e063762c5e14e9e50e0263bddd46 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_01_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_01_LOD1.fbm.meta deleted file mode 100644 index c000d148..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_01_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 290a5b8cf6f4260489e8ecfbdb28c0dc -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_03_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_03_LOD0.fbm.meta deleted file mode 100644 index a4a1de2d..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_03_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e575a0d12ebec854389061c5f5363765 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_03_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_03_LOD1.fbm.meta deleted file mode 100644 index 836c8acf..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_lightpost_03_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 49432786569e38a4b97cff637a8c6b93 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD0.fbm.meta deleted file mode 100644 index 41760fbb..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 69d35c711c51a2d4fb66eebcf8406f19 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD1.fbm.meta deleted file mode 100644 index 5dd9d20c..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: a22e852c47a80e64e837d3f48caffcd6 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD2.fbm.meta deleted file mode 100644 index 53fb2a7e..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Scenery_02/FV01_Scenery_02_FBX/FV01_well_02_LOD2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 0c38b7dda694b174cb33488280b86f20 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05_LOD0.fbm.meta deleted file mode 100644 index 1d323448..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: b1cb47dbb42bf6d4ca704eb63eb3bd49 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05b_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05b_LOD0.fbm.meta deleted file mode 100644 index 8c1590e0..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05b_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 020cb56b96f6c7d42b7bd62925f797e6 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05c_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05c_LOD0.fbm.meta deleted file mode 100644 index 4f4cce17..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_05c_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: bdb201a3f4542e84099ee3a224019831 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06_LOD0.fbm.meta deleted file mode 100644 index 46dd22c7..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 646afa9da9ac2d4418baeb11ae862ab5 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06_LOD1.fbm.meta deleted file mode 100644 index 0b51accd..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 4a8c988fdb40a4b46a7c21cf58eb5ef4 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06b_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06b_LOD0.fbm.meta deleted file mode 100644 index f47db340..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06b_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: aabeec726118b394caed2c0dfd608af5 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06b_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06b_LOD1.fbm.meta deleted file mode 100644 index 23a7102a..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06b_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: fc081712e20222a4191181a037255e7d -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06c_LOD0.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06c_LOD0.fbm.meta deleted file mode 100644 index 35e1e412..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06c_LOD0.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: e42abbf6651ab7b43bf7e4ff52880c2d -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06c_LOD1.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06c_LOD1.fbm.meta deleted file mode 100644 index f55d4ff2..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/FV01_Walls_02/FV01_Walls_02_FBX/FV01_Wall_06c_LOD1.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 102e8a55ddbf0bc42a4648b72980cdca -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_Bush_02/FV01_bush2.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_Bush_02/FV01_bush2.fbm.meta deleted file mode 100644 index a9260393..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_Bush_02/FV01_bush2.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: abefb5783db078945972809e2084ccd4 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_tree3/FV01_tree3.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_tree3/FV01_tree3.fbm.meta deleted file mode 100644 index b1c7e164..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_tree3/FV01_tree3.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: c94ff865395371b4590d1f08e1af7b60 -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_tree4/FV01_tree4.fbm.meta b/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_tree4/FV01_tree4.fbm.meta deleted file mode 100644 index 84b910f9..00000000 --- a/Assets/thirdparty/Fantasy_Village_01/Pack2/Trees Ambient-Occlusion/FV01_tree4/FV01_tree4.fbm.meta +++ /dev/null @@ -1,5 +0,0 @@ -fileFormatVersion: 2 -guid: 3a94ebb4e948d9f4e813769ef41a3d3e -folderAsset: yes -DefaultImporter: - userData: diff --git a/Assets/thirdparty/RPG_Camera_Controller/Scripts/RPG_Controller.cs b/Assets/thirdparty/RPG_Camera_Controller/Scripts/RPG_Controller.cs index 1e7cbadc..d7eec455 100644 Binary files a/Assets/thirdparty/RPG_Camera_Controller/Scripts/RPG_Controller.cs and b/Assets/thirdparty/RPG_Camera_Controller/Scripts/RPG_Controller.cs differ diff --git a/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectCombine.shader b/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectCombine.shader index 1a698261..7ad1c481 100644 --- a/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectCombine.shader +++ b/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectCombine.shader @@ -1,87 +1,87 @@ -Shader "Hidden/WallVisionOutlineCombine" { - Properties { - _MainTex ("Base (RGB)", 2D) = "white" {} - _Silhouette ("Silhouette Texture", 2D) = "red" {} - _PatternTex ("Pattern (R)", 2D) = "white" {} - _Occluder ("Occluder Texture", 2D) = "blue" {} - _Color ("Color", Color) = (0.0, 0.5, 1.0, 1.0) - _GlowStrength ("Glow strength", Range (0,1.0)) = 0.2 - _PatternScale ("Pattern scale factor", Range(0,1.0)) = 1.0 - _PatternWeight ("Pattern weight", Range(0,1.0)) = 1.0 - _Aspect ("Aspect Ratio", float) = 1.0 - _RampTex("Ramp Texture", 2D) = "white" {} - } - - // Shader code pasted into all further CGPROGRAM blocks - CGINCLUDE - #include "UnityCG.cginc" - - struct v2f { - float4 pos : POSITION; - float2 uv : TEXCOORD0; - }; - - uniform sampler2D _MainTex; - uniform sampler2D _Silhouette; - uniform sampler2D _Occluder; - uniform sampler2D _PatternTex; - uniform sampler2D _RampTex; - uniform float _GlowStrength; - uniform float _PatternScale; - uniform float _PatternWeight; - uniform half4 _Color; - uniform float _Aspect; - - sampler2D _CameraDepthNormalsTexture; - - v2f vert( appdata_img v ) - { - v2f o; - o.pos = mul(UNITY_MATRIX_MVP, v.vertex); - - float2 uv = v.texcoord.xy; - o.uv = uv; - - return o; - } - - half4 frag(v2f i) : COLOR - { - float outlineDepth, sceneDepth; - float3 outlineNorm, sceneNorm; - - DecodeDepthNormal(tex2D(_Silhouette, i.uv), outlineDepth, outlineNorm); - DecodeDepthNormal(tex2D(_Occluder, i.uv), sceneDepth, sceneNorm); - - float4 scene = tex2D(_MainTex, i.uv); - half4 pattern = tex2D(_PatternTex, float2(i.uv.x/_PatternScale, i.uv.y/(_PatternScale*_Aspect))); - if (sceneDepth > 0 && outlineDepth > 0 && outlineDepth > sceneDepth) { - //float factor = pow(1-dot(float3(0,0,1),outlineNorm), 3); - //float factor = 1-dot(float3(0,0,1),outlineNorm); - float factor = tex2D(_RampTex, float2(dot(float3(0,0,1),outlineNorm), 0.0)).a; - return half4(lerp(scene.rgba, half4(_Color.r ,_Color.g ,_Color.b, _GlowStrength), - lerp(factor, factor*pattern.r, _PatternWeight))); - } - else - return scene; - - - } - - ENDCG - - SubShader { - Pass { - ZTest Always - Cull Off - ZWrite Off - Fog { Mode off } - - CGPROGRAM - #pragma vertex vert - #pragma fragment frag - ENDCG - } - } - FallBack off -} +Shader "Hidden/WallVisionOutlineCombine" { + Properties { + _MainTex ("Base (RGB)", 2D) = "white" {} + _Silhouette ("Silhouette Texture", 2D) = "red" {} + _PatternTex ("Pattern (R)", 2D) = "white" {} + _Occluder ("Occluder Texture", 2D) = "blue" {} + _Color ("Color", Color) = (0.0, 0.5, 1.0, 1.0) + _GlowStrength ("Glow strength", Range (0,1.0)) = 0.2 + _PatternScale ("Pattern scale factor", Range(0,1.0)) = 1.0 + _PatternWeight ("Pattern weight", Range(0,1.0)) = 1.0 + _Aspect ("Aspect Ratio", float) = 1.0 + _RampTex("Ramp Texture", 2D) = "white" {} + } + + // Shader code pasted into all further CGPROGRAM blocks + CGINCLUDE + #include "UnityCG.cginc" + + struct v2f { + float4 pos : POSITION; + float2 uv : TEXCOORD0; + }; + + uniform sampler2D _MainTex; + uniform sampler2D _Silhouette; + uniform sampler2D _Occluder; + uniform sampler2D _PatternTex; + uniform sampler2D _RampTex; + uniform float _GlowStrength; + uniform float _PatternScale; + uniform float _PatternWeight; + uniform half4 _Color; + uniform float _Aspect; + + sampler2D _CameraDepthNormalsTexture; + + v2f vert( appdata_img v ) + { + v2f o; + o.pos = mul(UNITY_MATRIX_MVP, v.vertex); + + float2 uv = v.texcoord.xy; + o.uv = uv; + + return o; + } + + half4 frag(v2f i) : COLOR + { + float outlineDepth, sceneDepth; + float3 outlineNorm, sceneNorm; + + DecodeDepthNormal(tex2D(_Silhouette, i.uv), outlineDepth, outlineNorm); + DecodeDepthNormal(tex2D(_Occluder, i.uv), sceneDepth, sceneNorm); + + float4 scene = tex2D(_MainTex, i.uv); + half4 pattern = tex2D(_PatternTex, float2(i.uv.x/_PatternScale, i.uv.y/(_PatternScale*_Aspect))); + if (sceneDepth > 0 && outlineDepth > 0 && outlineDepth > sceneDepth) { + //float factor = pow(1-dot(float3(0,0,1),outlineNorm), 3); + //float factor = 1-dot(float3(0,0,1),outlineNorm); + float factor = tex2D(_RampTex, float2(dot(float3(0,0,1),outlineNorm), 0.0)).a; + return half4(lerp(scene.rgba, half4(_Color.r ,_Color.g ,_Color.b, _GlowStrength), + lerp(factor, factor*pattern.r, _PatternWeight))); + } + else + return scene; + + + } + + ENDCG + + SubShader { + Pass { + ZTest Always + Cull Off + ZWrite Off + Fog { Mode off } + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + ENDCG + } + } + FallBack off +} diff --git a/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectOccluder.shader b/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectOccluder.shader index 1fa20da9..6952c157 100644 --- a/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectOccluder.shader +++ b/Assets/thirdparty/WallVisionOutlineEffect/WallVisionOutlineEffectOccluder.shader @@ -1,35 +1,35 @@ -Shader "Hidden/WallVisionOutlineOccluder" { - SubShader { - Tags { "RenderType"="Opaque" } - - Pass { - Name "Base" - ZWrite On - ZTest Lequal - Cull Front - - CGPROGRAM - #pragma vertex vert - #pragma fragment frag - #include "UnityCG.cginc" - struct v2f { - float4 pos : POSITION; - float4 nz : TEXCOORD0; - }; - - v2f vert( appdata_base v ) { - v2f o; - o.pos = mul(UNITY_MATRIX_MVP, v.vertex); - o.nz.xyz = COMPUTE_VIEW_NORMAL; - o.nz.w = COMPUTE_DEPTH_01; - return o; - } - - fixed4 frag(v2f i) : COLOR { - return EncodeDepthNormal (i.nz.w, i.nz.xyz); - } - ENDCG - } - } -} - +Shader "Hidden/WallVisionOutlineOccluder" { + SubShader { + Tags { "RenderType"="Opaque" } + + Pass { + Name "Base" + ZWrite On + ZTest Lequal + Cull Front + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #include "UnityCG.cginc" + struct v2f { + float4 pos : POSITION; + float4 nz : TEXCOORD0; + }; + + v2f vert( appdata_base v ) { + v2f o; + o.pos = mul(UNITY_MATRIX_MVP, v.vertex); + o.nz.xyz = COMPUTE_VIEW_NORMAL; + o.nz.w = COMPUTE_DEPTH_01; + return o; + } + + fixed4 frag(v2f i) : COLOR { + return EncodeDepthNormal (i.nz.w, i.nz.xyz); + } + ENDCG + } + } +} + diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index 9e620299..e39a1e05 100644 Binary files a/ProjectSettings/EditorBuildSettings.asset and b/ProjectSettings/EditorBuildSettings.asset differ diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index dee8929a..dcae11dd 100644 Binary files a/ProjectSettings/GraphicsSettings.asset and b/ProjectSettings/GraphicsSettings.asset differ diff --git a/README.md b/README.md index f2701ecc..9498f51e 100644 --- a/README.md +++ b/README.md @@ -1,70 +1,143 @@ kbengine_unity3d_warring ============= -##服务端引擎: +## 本项目作为KBEngine服务端引擎的客户端演示而写,适用于Unity4.x + http://www.kbengine.org +## 官方论坛 + + http://bbs.kbengine.org + + ## QQ交流群 - 群1: 16535321 - 群2: 367555003 + 461368412 + + +## KBE插件文档 + + Assets\Plugins\kbengine\kbengine_unity3d_plugins\README.md + + +## GO! + + 1. 确保已经下载过KBEngine服务端引擎,如果没有下载请先下载 + 下载服务端源码(KBEngine): + https://github.com/kbengine/kbengine/releases/latest + + 编译(KBEngine): + http://kbengine.github.io/docs/build.html + + 安装(KBEngine): + http://kbengine.github.io/docs/installation.html + + 2. 下载KBEngine服务端Demo资产库: + + * 使用git命令行,进入到kbengine_unity3d_warring目录执行: -##GO! + git submodule update --init --remote +![submodule_update1](http://kbengine.github.io/assets/img/screenshots/gitbash_submodule.png) - ##创建AssetBundles + * 或者使用 TortoiseGit(选择菜单): TortoiseGit -> Submodule Update: +![submodule_update2](http://kbengine.github.io/assets/img/screenshots/unity3d_plugins_submodule_update.jpg) - unity3d(菜单上)->Publish->Build Pulish AssetBundles - autoAll + * 也可以手动下载kbengine服务端Demo资产库 - 期间可能一直出现"Moving file failed", 需要点击"try again"让其继续, - 这可能是unity3d在移动文件时文件被占用造成的。 - 执行完毕后检查 Assets->StreamingAssets是否有内容。 + 服务端资产库下载: + https://github.com/kbengine/kbengine_demos_assets/releases/latest + 下载后请将其解压缩,并将目录文件放置于服务端引擎根目录"kbengine/"之下,如下图: - 生成服务端寻路数据: - 选中: Assets->Nav_build->xinshoucun->NavmeshBuild->Build & Bake, 等待生成完成之后 - 选中: Assets->Nav_build->xinshoucun->CAIBakedNavmesh->Save, 将其中srv_xxx.navmesh放到服务端kbengine\demo\res\spaces\xinshoucun中 + 3. 拷贝服务端资产库"kbengine_demos_assets"到服务端引擎根目录"kbengine/"之下,如下图: +![demo_configure](http://kbengine.github.io/assets/img/screenshots/demo_copy_kbengine.jpg) -##Build: + 4. 通过服务端资产库生成KBE客户端插件(可选,默认已经带有一份,除非服务器有相关改动才需要再次生成) + 1: 双击运行 kbengine/kbengine_demos_asset/gensdk.bat + 2: 拷贝kbengine_unity3d_plugins到kbengine_unity3d_warring\Assets\Plugins\kbengine\ - unity3d File->Build Settings->Scenes In Build选择scenes/go.unity->Platform +## 配置Demo(可选): + + 创建AssetBundles(默认已经创建,可以跳过这一步): + unity3d(菜单上)->Publish->Build Publish AssetBundles(打包所有需要动态加载资源) + + 期间可能一直出现"Moving file failed", 需要点击"try again"让其继续, + 这可能是unity3d在移动文件时文件被占用造成的。 + 执行完毕后检查 Assets->StreamingAssets是否有内容。 + + 生成服务端寻路数据(默认已经创建,可以跳过这一步): + 先将Assets\Plugins\cai-nmgen-rcn(generate navmesh).zip解压放当前目录下并重启unity3d编辑器, 然后执行如下步骤: + unity3d资源浏览器中选中(非菜单): Assets->Nav_build->xinshoucun->NavmeshBuild->Build & Bake, 等待生成完成之后 + unity3d资源浏览器中选中(非菜单): Assets->Nav_build->xinshoucun->CAIBakedNavmesh->Save, 将其中srv_xxx.navmesh放到服务端kbengine\kbengine_demos_assets\res\spaces\xinshoucun中 + (注意: 生成完毕后建议删除cai-nmgen-rcn(generate navmesh).zip解压出来的文件,会造成无法导出游戏的错误,原因未知。) + (如果有更多问题请咨询插件作者: http://www.critterai.org/projects/cainav/) + + 改变登录IP地址与端口(注意:关于服务端端口部分参看http://kbengine.github.io/cn/docs/installation.html): +![demo_configure](http://kbengine.github.io/assets/img/screenshots/demo_configure.jpg) + + kbengine_unity3d_warring\Scripts\kbe_scripts\clientapp.cs -> ip + kbengine_unity3d_warring\Scripts\kbe_scripts\clientapp.cs -> port + +## 启动服务器: + + 先开启服务端 + Windows: + kbengine\kbengine_demos_assets\start_server.bat + + Linux: + kbengine\kbengine_demos_assets\start_server.sh + + 检查启动状态: + 如果启动成功将会在日志中找到"Components::process(): Found all the components!"。 + 任何其他情况请在日志中搜索"ERROR"关键字,根据错误描述尝试解决。 + (More: http://kbengine.github.io/cn/docs/startup_shutdown.html) + +## 导出WebPlayer项目: + + Unity3d File->Build Settings->Scenes In Build选择scenes/start.unity->Platform 选择Web Player->Build。 -## Web服务器部署文件夹结构 - ->(服务器根目录) - - StreamingAssets (创建AssetBundles生成的文件夹) - - ui (Assets下的ui文件夹可以直接拷贝过来) - - crossdomain.xml - - initLogo.png - - initProgressBar.PNG - - initProgressFrame.PNG - - index.html - - Unity3d.unity3d (在unity3d编译时生成的文件) - - Unity3d.html (在unity3d编译时生成的文件) +## 在Unity3D编辑器运行游戏 + + Unity3D中选择Assets\scenes\start场景然后点击编辑器运行按钮,如果无意外应该可以登录游戏进入到场景中了。 + (注意:运行游戏前请确保Unity3D控制台“错误暂停”是取消状态,因为一些原因一定会遇到错误,参考:http://bbs.kbengine.org/forum.php?mod=viewthread&tid=20&extra=page%3D1) +![unity_error_pause](http://kbengine.github.io/assets/img/screenshots/unity_error_pause.png) -##运行: - 1. 启动kbengine服务端 +## 在浏览器运行游戏: - 2. 浏览器访问localhost + Web服务器部署文件夹结构: - 如不清楚请下载发布版demo, 并按照其中的文件夹结构放置并看压缩包内文档教程如何启动: + ->(服务器根目录) + - StreamingAssets (创建AssetBundles生成的文件夹) + - ui (Assets下的ui文件夹可以直接拷贝过来) + - crossdomain.xml + - initLogo.png + - initProgressBar.PNG + - initProgressFrame.PNG + - index.html + - Unity3d.unity3d (在unity3d编译时生成的文件) + - Unity3d.html (在unity3d编译时生成的文件) + + 浏览器访问localhost + 如不清楚请下载编译打包好的demo,并按照其中的文件夹结构放置并看压缩包内文档教程如何启动: https://sourceforge.net/projects/kbengine/files/ -##日志: +## WebPlayer日志: Windows XP: C:\Documents and Settings\username\Local Settings\Temp\UnityWebPlayer\log - Windows Vista/7: C:\Users\username\AppData\Local\Temp\UnityWebPlayer\log -##warring截图 -![warring项目运行效果](http://www.kbengine.org/assets/img/screenshots/unity3d_demo1.jpg) -![warring项目运行效果](http://www.kbengine.org/assets/img/screenshots/unity3d_demo2.jpg) -![warring项目运行效果](http://www.kbengine.org/assets/img/screenshots/unity3d_demo3.jpg) -![warring项目运行效果](http://www.kbengine.org/assets/img/screenshots/unity3d_demo4.jpg) -![warring项目运行效果](http://www.kbengine.org/assets/img/screenshots/unity3d_demo5.jpg) -![warring项目运行效果](http://www.kbengine.org/assets/img/screenshots/unity3d_demo6.jpg) -![warring项目运行效果](http://www.kbengine.org/assets/img/screenshots/unity3d_demo33.jpg) +## warring截图 + +![warring项目运行效果](http://kbengine.github.io/assets/img/screenshots/unity3d_demo1.jpg) +![warring项目运行效果](http://kbengine.github.io/assets/img/screenshots/unity3d_demo2.jpg) +![warring项目运行效果](http://kbengine.github.io/assets/img/screenshots/unity3d_demo3.jpg) +![warring项目运行效果](http://kbengine.github.io/assets/img/screenshots/unity3d_demo4.jpg) +![warring项目运行效果](http://kbengine.github.io/assets/img/screenshots/unity3d_demo5.jpg) +![warring项目运行效果](http://kbengine.github.io/assets/img/screenshots/unity3d_demo6.jpg) +![warring项目运行效果](http://kbengine.github.io/assets/img/screenshots/unity3d_demo33.jpg) diff --git a/critterai/.svn/entries b/critterai/.svn/entries deleted file mode 100644 index 48082f72..00000000 --- a/critterai/.svn/entries +++ /dev/null @@ -1 +0,0 @@ -12 diff --git a/critterai/.svn/format b/critterai/.svn/format deleted file mode 100644 index 48082f72..00000000 --- a/critterai/.svn/format +++ /dev/null @@ -1 +0,0 @@ -12 diff --git a/critterai/.svn/pristine/00/00f38757049570a9ae4d1f8cbd3fca3f5e31d28f.svn-base b/critterai/.svn/pristine/00/00f38757049570a9ae4d1f8cbd3fca3f5e31d28f.svn-base deleted file mode 100644 index c9f4c65f..00000000 Binary files a/critterai/.svn/pristine/00/00f38757049570a9ae4d1f8cbd3fca3f5e31d28f.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/01/01ad696b6eda014fa410ea24845182b1f81640da.svn-base b/critterai/.svn/pristine/01/01ad696b6eda014fa410ea24845182b1f81640da.svn-base deleted file mode 100644 index 147505f0..00000000 Binary files a/critterai/.svn/pristine/01/01ad696b6eda014fa410ea24845182b1f81640da.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/01/01b17b71c8e01bb762f74f71b4b0112b59b6a6e2.svn-base b/critterai/.svn/pristine/01/01b17b71c8e01bb762f74f71b4b0112b59b6a6e2.svn-base deleted file mode 100644 index 18d64110..00000000 --- a/critterai/.svn/pristine/01/01b17b71c8e01bb762f74f71b4b0112b59b6a6e2.svn-base +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using System.Collections.Generic; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class ControlContext - { - private Rect mMainArea; - private Rect mButtonArea; - private bool mHideMain; - - private readonly BuildTaskProcessor mTaskProcessor; - private readonly NavmeshBuild mBuild; - private readonly TileSelection mSelection; - - private readonly List mTileTasks = new List(); - private readonly List mNMGenTasks = new List(); - - public Rect MainArea - { - get { return mMainArea; } - set { mMainArea = value; } - } - - public Rect ButtonArea - { - get { return mButtonArea; } - set { mButtonArea = value; } - } - - public bool HideMain - { - get { return mHideMain; } - set { mHideMain = value; } - } - - public List TileTasks { get { return mTileTasks; } } - public List NMGenTasks { get { return mNMGenTasks; } } - public NavmeshBuild Build { get { return mBuild ? mBuild : null; } } - public TileSelection Selection { get { return mSelection; } } - public int TaskCount { get { return mNMGenTasks.Count + mTileTasks.Count; } } - - public ControlContext(NavmeshBuild build, BuildTaskProcessor manager) - { - if (!build || manager == null) - throw new System.ArgumentNullException(); - - mTaskProcessor = manager; - - mBuild = build; - mSelection = new TileSelection(build); - } - - public bool QueueTask(InputBuildTask task) - { - if (task == null || task.TaskState != BuildTaskState.Inactive) - return false; - - return mTaskProcessor.QueueTask(task); - } - - public bool QueueTask(BuildContext context - , int tx, int tz - , PolyMesh polyMesh, PolyMeshDetail detailMesh - , bool bvTreeEnabled - , int priority) - { - TileBuildTask task = TileBuildTask.Create(tx, tz - , polyMesh.GetData(false) - , (detailMesh == null ? null : detailMesh.GetData(true)) - , Build.Connections - , bvTreeEnabled - , true - , priority); - - if (!mTaskProcessor.QueueTask(task)) - { - context.LogError("Task processor rejected task.", this); - return false; - } - - mTileTasks.Add(task); - - return true; - } - - public bool QueueTask(int tx, int tz, int priority, BuildContext logger) - { - // Check for existing task and purge it. - - NavmeshBuild build = Build; - - if (!build) - return false; - - TileBuildData tdata = build.BuildData; - - if (build.TileSetDefinition == null && (tx > 0 || tz > 0)) - { - logger.LogError("Tile build requested, but no tile set found.", this); - return false; - } - - if (AbortRequest(tx, tz, "Overriden by new task.")) - { - tdata.ClearUnbaked(tx, tz); - - logger.LogWarning(string.Format( - "Existing build task overridden by new task. ({0}, {1})" - , tx, tz), this); - } - - IncrementalBuilder builder; - NMGenConfig config = build.Config; - - if (build.TileSetDefinition == null) - { - InputGeometry geom = build.InputGeom; - - if (geom == null) - { - logger.LogError("Input geometry not available.", this); - tdata.SetAsFailed(tx, tz); - return false; - } - - builder = IncrementalBuilder.Create(config.GetConfig() - , config.ResultOptions - , geom - , build.NMGenProcessors); - } - else - { - builder = IncrementalBuilder.Create(tx, tz - , config.ResultOptions - , build.TileSetDefinition - , build.NMGenProcessors); - } - - if (builder == null) - { - logger.LogError(string.Format("Tile set did not produce a builder. Tile: ({0},{1})" - , tx, tz) - , this); - return false; - } - - NMGenTask task = NMGenTask.Create(builder, priority); - - if (!mTaskProcessor.QueueTask(task)) - { - logger.LogError(string.Format("Processor rejected task. Tile: ({0},{1})" - , tx, tz), this); - return false; - } - - mNMGenTasks.Add(task); - tdata.SetAsQueued(tx, tz); - - return true; - } - - private bool AbortRequest(int tx, int tz, string reason) - { - bool result = false; - - // This is a thorough check, taking into account potential errors. - - for (int i = mNMGenTasks.Count - 1; i >= 0; i--) - { - NMGenTask item = mNMGenTasks[i]; - if (item.TileX == tx && item.TileZ == tz) - { - item.Abort(reason); - mNMGenTasks.RemoveAt(i); - mBuild.BuildData.ClearUnbaked(tx, tz); - result = true; - } - } - - for (int i = mTileTasks.Count - 1; i >= 0; i--) - { - TileBuildTask item = mTileTasks[i]; - if (item.TileX == tx && item.TileZ == tz) - { - item.Abort(reason); - mTileTasks.RemoveAt(i); - mBuild.BuildData.ClearUnbaked(tx, tz); - result = true; - } - } - - return result; - } - - public void AbortAllReqests(string reason) - { - - foreach (NMGenTask item in mNMGenTasks) - { - item.Abort(reason); - if (mBuild) // Important: Might be aborting due to lost build component. - mBuild.BuildData.ClearUnbaked(item.TileX, item.TileZ); - } - - mNMGenTasks.Clear(); - - foreach (TileBuildTask item in mTileTasks) - { - item.Abort(reason); - if (mBuild != null) // Important: Might be aborting due to lost build component. - mBuild.BuildData.ClearUnbaked(item.TileX, item.TileZ); - } - - mTileTasks.Clear(); - } - } -} diff --git a/critterai/.svn/pristine/01/01d68510eb9226523f2a013153b2bb720717ed7c.svn-base b/critterai/.svn/pristine/01/01d68510eb9226523f2a013153b2bb720717ed7c.svn-base deleted file mode 100644 index 4cfa6ec4..00000000 --- a/critterai/.svn/pristine/01/01d68510eb9226523f2a013153b2bb720717ed7c.svn-base +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using System.Threading; -using UnityEngine; -using UnityEditor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal class BuildProcessor - { - private const string MaxConcurrKey = "org.critterai.nmbuild.MaxConcurrency"; - - public static int DefaultConcurrency - { - get - { - // Bugs in Unity Editor 3.5 threading causing problems. - return 1; - // return Mathf.Max(1, System.Environment.ProcessorCount - 2); - } - } - - public static int MaxConcurrency - { - get - { - int val = EditorPrefs.GetInt(MaxConcurrKey); - return (val == 0 ? DefaultConcurrency : val); - } - set - { - EditorPrefs.SetInt(MaxConcurrKey - , Mathf.Clamp(value, 1, System.Environment.ProcessorCount)); - } - } - - private readonly List mControllers; - - private BuildTaskProcessor mTaskManager; - - public BuildTaskProcessor TaskManager { get { return mTaskManager; } } - - public int BuildCount { get { return mControllers.Count; } } - - public BuildProcessor() - { - mControllers = new List(3); - - mTaskManager = new BuildTaskProcessor(MaxConcurrency); - Thread t = new Thread(new ThreadStart(mTaskManager.Run)); - t.Start(); - - BuildSelector b = BuildSelector.Instance; - - b.OnSelect += HandleOnSelect; - - NavmeshBuild selected = b.Selected; - if (selected) - HandleOnSelect(selected); - } - - private void HandleOnSelect(NavmeshBuild build) - { - if (!build || Contains(build)) - return; - - BuildController controller = new BuildController(build, mTaskManager); - - if (controller.Enter()) - mControllers.Add(controller); - else - Debug.LogError("Failed to add controller for build: " + build); - } - - private bool Contains(NavmeshBuild build) - { - if (!build) - return false; - - foreach (BuildController controller in mControllers) - { - if (controller.Build == build) - return true; - } - return false; - } - - public void Dispose() - { - if (mTaskManager == null) - return; - - foreach (BuildController controller in mControllers) - { - controller.Exit(); - } - mControllers.Clear(); - - mTaskManager.Abort(); - mTaskManager = null; - - BuildSelector.Instance.OnSelect -= HandleOnSelect; - } - - public void Update() - { - if (mTaskManager == null) - { - // Give an error in this case. - Debug.LogError("Called update on build processor after processor disposal"); - return; - } - - for (int i = mControllers.Count - 1; i >= 0; i--) - { - BuildController controller = mControllers[i]; - NavmeshBuild build = controller.Build; - NavmeshBuild selected = BuildSelector.Instance.Selected; - - if (!build - || build.BuildType != NavmeshBuildType.Advanced - || (build != selected && !controller.BuildIsActive)) - { - // Build component has been destroyed, is no longer advanced, or is - // inactive and not selected. Get rid of it. - controller.Exit(); - mControllers.RemoveAt(i); - } - else - controller.Update(); - } - } - - public void OnGUI(Rect area, bool includeMain) - { - NavmeshBuild build = BuildSelector.Instance.Selected; - - if (!build) - return; - - foreach (BuildController controller in mControllers) - { - if (controller.Build == build) - { - controller.OnGUI(area, includeMain); - return; - } - } - } - - public void OnSceneGUI() - { - NavmeshBuild build = BuildSelector.Instance.Selected; - - if (!build) - return; - - foreach (BuildController controller in mControllers) - { - if (controller.Build == build) - { - controller.OnSceneGUI(); - return; - } - } - } - } -} diff --git a/critterai/.svn/pristine/02/0215ecf546786fd19c039da216243522214dc1fe.svn-base b/critterai/.svn/pristine/02/0215ecf546786fd19c039da216243522214dc1fe.svn-base deleted file mode 100644 index 70ee1ec3..00000000 Binary files a/critterai/.svn/pristine/02/0215ecf546786fd19c039da216243522214dc1fe.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/02/026ff6fe1cf586a7505160de45e15c051c203231.svn-base b/critterai/.svn/pristine/02/026ff6fe1cf586a7505160de45e15c051c203231.svn-base deleted file mode 100644 index b5040a29..00000000 --- a/critterai/.svn/pristine/02/026ff6fe1cf586a7505160de45e15c051c203231.svn-base +++ /dev/null @@ -1,475 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; - -import org.junit.Test; -import org.junit.Before; - -/** - * Test related to the ContourSetBuilder.removeIntersectingSegments() - * operation. - */ -public class RemoveIntersectingSegmentTests -{ - - /* - * Design Notes: - * - * The intersecting quads don't test realistic scenarios. But - * they are useful for testing basic operation of the algorithm - * before the more complex realistic scenarios. - */ - - private static final int REGION_A = 1; - private static final int REGION_B = 2; - private static final int REGION_C = 3; - private static final int REGION_S = 52; - - private final ArrayList mBaseQuad = new ArrayList(16); - - private final ArrayList mIntersectionQuadA = - new ArrayList(12); - - private final ArrayList mIntersectionQuadB = - new ArrayList(12); - - @Before - public void setup() - { - - /* - * - * 1 - 2 - * | | - * 0 - 3 - */ - - mBaseQuad.add(1); - mBaseQuad.add(5); - mBaseQuad.add(2); - mBaseQuad.add(0); - - mBaseQuad.add(1); - mBaseQuad.add(5); - mBaseQuad.add(3); - mBaseQuad.add(0); - - mBaseQuad.add(2); - mBaseQuad.add(5); - mBaseQuad.add(3); - mBaseQuad.add(0); - - mBaseQuad.add(2); - mBaseQuad.add(5); - mBaseQuad.add(2); - mBaseQuad.add(0); - - /* - * - * 3 1 - * | x | - * 0 2 - */ - - mIntersectionQuadA.add(1); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(0); - - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(3); - mIntersectionQuadA.add(0); - - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(0); - - mIntersectionQuadA.add(1); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(3); - mIntersectionQuadA.add(0); - - /* - * - * 1 3 - * | x | - * 0 2 - */ - - mIntersectionQuadB.add(1); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(2); - mIntersectionQuadB.add(0); - - mIntersectionQuadB.add(1); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(0); - - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(2); - mIntersectionQuadB.add(0); - - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(0); - - } - - @Test - public void testBasicQuadOffset0() - { - // No change expected. - mBaseQuad.set(1*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testBasicQuadOffset1() - { - // No change expected. - mBaseQuad.set(2*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testBasicQuadOffset2() - { - // No change expected. - mBaseQuad.set(3*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testBasicQuadOffset3() - { - // No change expected. - mBaseQuad.set(0*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testDisallowedRemovalAll() - { - // No change expected. - - // Make both of the the intersecting segments - // a region portal. - mIntersectionQuadA.set(1*4+3, REGION_A); - mIntersectionQuadA.set(3*4+3, REGION_B); - ContourSetBuilder.removeIntersectingSegments(REGION_S - , mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - - } - - @Test - public void testDisallowedRemovalIndirect() - { - // No change expected. - - // The null edge can't be removed because - // one of its vertices is on a portal edge. - mIntersectionQuadA.set(1*4+3, REGION_A); // <- Tested edge. - mIntersectionQuadA.set(0*4+3, REGION_B); // <- Want's to remove. Can't - ContourSetBuilder.removeIntersectingSegments(REGION_S - , mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - } - - @Test - public void testIntersectingQuadAOffset0() - { - - mIntersectionQuadA.set(1*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 12); - - assertTrue(mIntersectionQuadA.get(0) == 1); - assertTrue(mIntersectionQuadA.get(2) == 2); - - assertTrue(mIntersectionQuadA.get(4) == 2); - assertTrue(mIntersectionQuadA.get(6) == 3); - - assertTrue(mIntersectionQuadA.get(8) == 2); - assertTrue(mIntersectionQuadA.get(10) == 2); - } - - @Test - public void testIntersectingQuadAOffset1() - { - // Expect no change to the quad. - mIntersectionQuadA.set(2*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - } - - @Test - public void testIntersectingQuadAOffset2() - { - mIntersectionQuadA.set(3*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - - assertTrue(mIntersectionQuadA.size() == 12); - - assertTrue(mIntersectionQuadA.get(0) == 1); - assertTrue(mIntersectionQuadA.get(2) == 2); - - assertTrue(mIntersectionQuadA.get(4) == 2); - assertTrue(mIntersectionQuadA.get(6) == 2); - - assertTrue(mIntersectionQuadA.get(8) == 1); - assertTrue(mIntersectionQuadA.get(10) == 3); - } - - @Test - public void testIntersectingQuadAOffset3() - { - // Expect no change to the quad. - mIntersectionQuadA.set(0*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - } - - @Test - public void testIntersectingQuadBOffset0() - { - // Expect no change to the quad. - mIntersectionQuadB.set(1*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 16); - } - - @Test - public void testIntersectingQuadBOffset1() - { - mIntersectionQuadB.set(2*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 12); - - assertTrue(mIntersectionQuadB.get(0) == 1); - assertTrue(mIntersectionQuadB.get(2) == 3); - - assertTrue(mIntersectionQuadB.get(4) == 3); - assertTrue(mIntersectionQuadB.get(6) == 2); - - assertTrue(mIntersectionQuadB.get(8) == 3); - assertTrue(mIntersectionQuadB.get(10) == 3); - } - - @Test - public void testIntersectingQuadBOffset2() - { - // Expect no change to the quad. - mIntersectionQuadB.set(3*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 16); - } - - @Test - public void testIntersectingQuadBOffset3() - { - mIntersectionQuadB.set(0*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 12); - - assertTrue(mIntersectionQuadB.get(0) == 1); - assertTrue(mIntersectionQuadB.get(2) == 2); - - assertTrue(mIntersectionQuadB.get(4) == 1); - assertTrue(mIntersectionQuadB.get(6) == 3); - - assertTrue(mIntersectionQuadB.get(8) == 3); - assertTrue(mIntersectionQuadB.get(10) == 3); - } - - @Test - public void testMultiIntersectA() - { - - ArrayList sourceContour = getMultiIntersectA(); - - for (int sourceOffset = 0; sourceOffset < 10; sourceOffset++) - { - ArrayList contour = new ArrayList(); - contour.addAll(sourceContour); - - ContourSetBuilder.removeIntersectingSegments(REGION_S, contour); - - validateMAIAdjustment(sourceOffset, contour); - - ContourUtil.shiftContour(sourceContour); - } - } - - /** - * Returns the vertex index to use for a MultiIntersectA - * contour after its invalid vertices have been removed, - * taking into account various adjustments. - * @param vertIndex The index to adjust. - * @param sourceOffset The number of shifts performed - * on the source contour. - * @return The index of the vertex in the new contour. - */ - private int getMIAAdjustedIndex(int vertIndex - , int sourceOffset) - { - - final int sourceVertCount = 10; - - int iVert = (vertIndex + sourceOffset) % sourceVertCount; - int iBadVert01 = (3 + sourceOffset) % sourceVertCount; - int iBadVert02 = (4 + sourceOffset) % sourceVertCount; - int iBadVert03 = (5 + sourceOffset) % sourceVertCount; - - int offset = 0; - if (iBadVert01 < iVert) - offset--; - if (iBadVert02 < iVert) - offset--; - if (iBadVert03 < iVert) - offset--; - - return (iVert + offset); - } - - private ArrayList getMultiIntersectA() - { - // When testing against segment 0 -> 1, expect - // vertices 3, 4, and 5 to be removed. - - ArrayList contour = new ArrayList(10*4); - - contour.add(2); - contour.add(5); - contour.add(1); - contour.add(REGION_B); - - contour.add(2); - contour.add(5); - contour.add(10); - contour.add(REGION_A); - - contour.add(3); - contour.add(5); - contour.add(9); - contour.add(0); - - contour.add(2); - contour.add(5); - contour.add(8); - contour.add(0); - - contour.add(1); - contour.add(5); - contour.add(8); - contour.add(0); - - contour.add(1); - contour.add(5); - contour.add(7); - contour.add(0); - - contour.add(4); - contour.add(5); - contour.add(7); - contour.add(0); - - contour.add(6); - contour.add(5); - contour.add(5); - contour.add(REGION_C); - - contour.add(4); - contour.add(5); - contour.add(5); - contour.add(0); - - contour.add(4); - contour.add(5); - contour.add(3); - contour.add(0); - - return contour; - } - - /** - * Checks to make sure a MultiIntersectA contour has been properly - * cleaned up. - * @param sourceOffset The number of shifts performed - * on the source contour. - * @param resultContour The contour after invalid vertices have been - * removed. - * @param startVertIndex The index of the start vertex with the source - * offset already taken into account. - * @param endVertIndex The index of the end vertex with the source - * offset already taken into account. - * @param offset The offset returned by the contour cleanup operation. - */ - private void validateMAIAdjustment(int sourceOffset - , ArrayList resultContour) - { - - final int sourceVertCount = 10; - - // Expect three vertices were removed. - int expectedVertCount = sourceVertCount - 3; - assertTrue("Loop: " + sourceOffset - , resultContour.size() == expectedVertCount * 4); - - int iVert = getMIAAdjustedIndex(0, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 2); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 1); - - iVert = getMIAAdjustedIndex(1, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 2); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 10); - - iVert = getMIAAdjustedIndex(2, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 3); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 9); - - // Removed vertices: 3, 4, 5 - - iVert = getMIAAdjustedIndex(6, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 4); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 7); - - iVert = getMIAAdjustedIndex(7, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 6); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 5); - - iVert = getMIAAdjustedIndex(8, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 4); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 5); - - iVert = getMIAAdjustedIndex(9, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 4); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 3); - } - -} diff --git a/critterai/.svn/pristine/02/02919eebeb3ecfe53eb1e52200a01335b6ddde61.svn-base b/critterai/.svn/pristine/02/02919eebeb3ecfe53eb1e52200a01335b6ddde61.svn-base deleted file mode 100644 index 0353eeb4..00000000 --- a/critterai/.svn/pristine/02/02919eebeb3ecfe53eb1e52200a01335b6ddde61.svn-base +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * A class used to hold intermediate and performance data related to building - * the navigation mesh. - *

The entire build process is represented when this data is combined with - * the source geometry and final navigation mesh.

- */ -public final class IntermediateData -{ - - /* - * Recast Reference: None - */ - - /** - * The data is undefined. (Has not been set.) - */ - public static final long UNDEFINED = -1; - - /** - * The time to perform voxelization. (ns) - */ - public long voxelizationTime; - - /** - * The time to perform region generation. (ns) - */ - public long regionGenTime; - - /** - * The time to perform contour generation. (ns) - */ - public long contourGenTime; - - /** - * The time to perform polygon generation. (ns) - */ - public long polyGenTime; - - /** - * The time to perform the final triangulation. (ns) - */ - public long finalMeshGenTime; - - private SolidHeightfield mSolidHeightfield; - private OpenHeightfield mOpenHeightfield; - private ContourSet mContours; - private PolyMeshField mPolyMesh; - - /** - * The contour set associated with the open heightfield. - * @return The contours associated with the open heightfield. - */ - public ContourSet contours() { return mContours; } - - /** - * Returns the total time to generate the navigation mesh. (ns) - * @return The total time to generate the navigation mesh. (ns) - */ - public long getTotalGenTime() - { - if (finalMeshGenTime == UNDEFINED) - return UNDEFINED; - return voxelizationTime - + regionGenTime - + contourGenTime - + polyGenTime - + finalMeshGenTime; - } - - /** - * The open heightfield associated with the solid heightfield. - * @return The open heightfield associated with the solid heightfield. - */ - public OpenHeightfield openHeightfield() { return mOpenHeightfield; } - - /** - * The polygon mesh associated with the contour set. - * @return The polygon mesh associated with the contour set. - */ - public PolyMeshField polyMesh() { return mPolyMesh; } - - /** - * Resets all data to null. - */ - public void reset() - { - voxelizationTime = UNDEFINED; - regionGenTime = UNDEFINED; - contourGenTime = UNDEFINED; - polyGenTime = UNDEFINED; - finalMeshGenTime = UNDEFINED; - mSolidHeightfield = null; - mOpenHeightfield = null; - mContours = null; - mPolyMesh = null; - } - - /** - * Sets the contour set. - * @param contours The contour set. - */ - public void setContours(ContourSet contours) - { - mContours = contours; - } - - /** - * Sets the open heightfield. - * @param field The open heightfield. - */ - public void setOpenHeightfield(OpenHeightfield field) - { - mOpenHeightfield = field; - } - - /** - * Sets the polygon mesh. - * @param mesh The polygon mesh. - */ - public void setPolyMesh(PolyMeshField mesh) - { - mPolyMesh = mesh; - } - - /** - * Sets the solid height field. - * @param field The solid heightfield. - */ - public void setSolidHeightfield(SolidHeightfield field) - { - mSolidHeightfield = field; - } - - /** - * The solid heightfield associated with the source geometry. - * @return The solid heightfield derived from the source geometry. - */ - public SolidHeightfield solidHeightfield() { return mSolidHeightfield; } -} diff --git a/critterai/.svn/pristine/02/02b7afa7d51cc45ef69ef8dd985fbdd5212b6490.svn-base b/critterai/.svn/pristine/02/02b7afa7d51cc45ef69ef8dd985fbdd5212b6490.svn-base deleted file mode 100644 index 8a1471b9..00000000 Binary files a/critterai/.svn/pristine/02/02b7afa7d51cc45ef69ef8dd985fbdd5212b6490.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/03/037457f2042214a43ed008b7a6c9239cf5a0c743.svn-base b/critterai/.svn/pristine/03/037457f2042214a43ed008b7a6c9239cf5a0c743.svn-base deleted file mode 100644 index f54baeea..00000000 Binary files a/critterai/.svn/pristine/03/037457f2042214a43ed008b7a6c9239cf5a0c743.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/03/037969bdf191c905229bc525b6c5ffdcb7d0cbe8.svn-base b/critterai/.svn/pristine/03/037969bdf191c905229bc525b6c5ffdcb7d0cbe8.svn-base deleted file mode 100644 index 30ad7245..00000000 --- a/critterai/.svn/pristine/03/037969bdf191c905229bc525b6c5ffdcb7d0cbe8.svn-base +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Navigation mesh configuration parameters. - /// - /// - /// - /// Implemented as a class with public fields in order to support Unity serialization. - /// Care must be taken not to set the fields to invalid values. - /// - /// - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public sealed class NavmeshParams - { - /// - /// The minimumn allowed tile size. - /// - public const float MinTileSize = 0.1f; - - /// - /// The world-space origin of the navigation mesh. - /// - public Vector3 origin; - - /// - /// The width of each tile. (Along the x-axis.) - /// - public float tileWidth = 0; - - /// - /// The depth of each tile. (Along the z-axis.) - /// - public float tileDepth = 0; - - /// - /// The maximum number of tiles the navigation mesh can contain. - /// - public int maxTiles = 0; - - /// - /// The maximum number of polygons each tile can contain. - /// - public int maxPolysPerTile = 0; - - /// - /// Constructs and initializes the structure. - /// - /// The tile space origin. - /// The width of each tile. (Along the x-axis.) - /// The depth of each tile. (Along the z-axis.) - /// - /// The maximum number of tiles the navigation mesh can contain. - /// - /// - /// The maximum number of polygons each tile can contain. - /// - public NavmeshParams(Vector3 origin - , float tileWidth, float tileDepth - , int maxTiles, int maxPolysPerTile) - { - this.origin = origin; - this.tileWidth = Math.Max(MinTileSize, tileWidth); - this.tileDepth = Math.Max(MinTileSize, tileDepth); - this.maxTiles = Math.Max(1, maxTiles); - this.maxPolysPerTile = Math.Max(1, maxPolysPerTile); - } - - internal NavmeshParams() { } - - /// - /// A clone of the parameters. - /// - /// A clone of the parameters. - public NavmeshParams Clone() - { - return new NavmeshParams(origin, tileWidth, tileDepth, maxTiles, maxPolysPerTile); - } - } -} diff --git a/critterai/.svn/pristine/03/039796ee9a7dfef28305c0730d7798d79d2fbdda.svn-base b/critterai/.svn/pristine/03/039796ee9a7dfef28305c0730d7798d79d2fbdda.svn-base deleted file mode 100644 index fc974af7..00000000 --- a/critterai/.svn/pristine/03/039796ee9a7dfef28305c0730d7798d79d2fbdda.svn-base +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// An NMGen build context. - /// - /// - /// - /// Holds objects related to an NMGen build during the build process. The builder - /// defines which assets are available at which point in the build. - /// - /// - public class NMGenContext - : BuildContext - { - private readonly int mTileX; - private readonly int mTileZ; - - private readonly NMGenParams mConfig; - - private bool mNoResult; - - private Heightfield mHeightfield; - private CompactHeightfield mCompactField; - private ContourSet mContours; - private PolyMesh mPolyMesh; - private PolyMeshDetail mDetailMesh; - - /// - /// The associated build configuation. - /// - public NMGenParams Config { get { return mConfig; } } - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int TileX { get { return mTileX; } } - - /// - /// The z-index of the tile within the tile grid. (x, z) - /// - public int TileZ { get { return mTileZ; } } - - /// - /// The build has not produced a result. - /// - public bool NoResult - { - get { return mNoResult; } - set { mNoResult = true; } - } - - /// - /// The heightfield. - /// - public Heightfield Heightfield - { - get { return mHeightfield; } - set { mHeightfield = value; } - } - - /// - /// The compact field. - /// - public CompactHeightfield CompactField - { - get { return mCompactField; } - set { mCompactField = value; } - } - - /// - /// The contour set. - /// - public ContourSet Contours - { - get { return mContours; } - set { mContours = value; } - } - - /// - /// The polygon mesh. - /// - public PolyMesh PolyMesh - { - get { return mPolyMesh; } - set { mPolyMesh = value; } - } - - /// - /// The detail mesh. - /// - public PolyMeshDetail DetailMesh - { - get { return mDetailMesh; } - set { mDetailMesh = value; } - } - - /// - /// Constructor. - /// - /// The x-index of the tile within the tile grid. (tx, tz) - /// The z-index of the tile within the tile grid. (tx, tz) - /// The build configuration. - public NMGenContext(int tx, int tz, NMGenParams config) - { - mTileX = tx; - mTileZ = tz; - - mConfig = config; - } - - /// - /// Sets the context as having produced no result. - /// - public void SetAsNoResult() - { - mHeightfield = null; - mCompactField = null; - mContours = null; - mPolyMesh = null; - mDetailMesh = null; - mNoResult = true; - } - } -} diff --git a/critterai/.svn/pristine/04/04622d663fb2fd93fa6c9ff79f2b96b2335ae1e7.svn-base b/critterai/.svn/pristine/04/04622d663fb2fd93fa6c9ff79f2b96b2335ae1e7.svn-base deleted file mode 100644 index 7704f3f8..00000000 --- a/critterai/.svn/pristine/04/04622d663fb2fd93fa6c9ff79f2b96b2335ae1e7.svn-base +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.interop -{ - /// - /// Base class for objects that contain references to unmanaged resources. - /// - public abstract class ManagedObject - : IManagedObject - { - private readonly AllocType mResourceType; - - /// - /// The type of unmanaged resources held by the object. - /// - public AllocType ResourceType { get { return mResourceType; } } - - /// - /// Constructor - /// - /// The type of unmanaged resource. - public ManagedObject(AllocType resourceType) - { - this.mResourceType = resourceType; - } - - /// - /// Request all unmanaged resources controlled by the object be immediately freed and - /// the object marked as disposed. - /// - /// - /// - /// Whether or not unmanaged resources are actually freed depends on whether the - /// resources are owned by the object. In some cases the only action is to mark the - /// object as disposed. - /// - /// - public abstract void RequestDisposal(); - - /// - /// True if the object has been disposed and should no longer be used. - /// - public abstract bool IsDisposed { get; } - } -} diff --git a/critterai/.svn/pristine/04/0477988231beedb3ba2667d1e540322c5ab725cf.svn-base b/critterai/.svn/pristine/04/0477988231beedb3ba2667d1e540322c5ab725cf.svn-base deleted file mode 100644 index 05a5c03e..00000000 --- a/critterai/.svn/pristine/04/0477988231beedb3ba2667d1e540322c5ab725cf.svn-base +++ /dev/null @@ -1,173 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; -import static org.critterai.nmgen.OpenHeightFieldUtil.*; -import org.junit.Test; - -/** - * Test the detection and resolution of a special case - * where a region only touches a null region at the tip - * of an outer corner. This can result in failure to detect - * a contour connection to the null region. - * - * Governing pattern: - * - * b a - * a x - */ -public class NullRegionOuterCornerTipTests -{ - - /** - * Tests a outer corner tip scenario: - * - * b b a a - * b b a a - * a a x x - * a a x x - */ - @Test - public void testQuadrantA() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(0, 4).setRegionID(2); - field.getData(0, 5).setRegionID(2); - field.getData(1, 4).setRegionID(2); - field.getData(1, 5).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(0, 5).regionID() == 2); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(1, 5).regionID() == 2); - assertTrue(field.getData(0, 3).regionID() == 1); - assertTrue(field.getData(2, 5).regionID() == 1); - - assertTrue((field.getData(1, 3).regionID() == 1 - && field.getData(2, 4).regionID() == 2) - || (field.getData(1, 3).regionID() == 2 - && field.getData(2, 4).regionID() == 1)); - } - - /** - * Tests a outer corner tip scenario: - * - * a b b b - * a a b a - * x x a a - * x x a a - */ - @Test - public void testQuadrantB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(3, 5).setRegionID(2); - field.getData(4, 4).setRegionID(2); - field.getData(4, 5).setRegionID(2); - field.getData(5, 5).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(3, 5).regionID() == 2); - assertTrue(field.getData(4, 4).regionID() == 2); - assertTrue(field.getData(4, 5).regionID() == 2); - assertTrue(field.getData(5, 5).regionID() == 2); - assertTrue(field.getData(5, 4).regionID() == 1); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(5, 3).regionID() == 1); - assertTrue(field.getData(3, 4).regionID() == 2); - } - - /** - * Tests a outer corner tip scenario: - * - * x x a a - * x x a b - * a a b b - * a b b b - */ - @Test - public void testQuadrantC() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(3, 0).setRegionID(2); - field.getData(4, 0).setRegionID(2); - field.getData(4, 1).setRegionID(2); - field.getData(5, 0).setRegionID(2); - field.getData(5, 1).setRegionID(2); - field.getData(5, 2).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(3, 0).regionID() == 2); - assertTrue(field.getData(4, 0).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == 2); - assertTrue(field.getData(5, 0).regionID() == 2); - assertTrue(field.getData(5, 1).regionID() == 2); - assertTrue(field.getData(5, 2).regionID() == 2); - - assertTrue((field.getData(3, 1).regionID() == 1 - && field.getData(4, 2).regionID() == 2) - || (field.getData(3, 1).regionID() == 2 - && field.getData(4, 2).regionID() == 1)); - } - - /** - * Tests a outer corner tip scenario: - * - * a a x x - * b a x x - * b b a a - * b a a a - */ - @Test - public void testQuadrantD() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(0, 0).setRegionID(2); - field.getData(0, 1).setRegionID(2); - field.getData(0, 2).setRegionID(2); - field.getData(1, 1).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 0).regionID() == 1); - assertTrue(field.getData(2, 0).regionID() == 1); - assertTrue(field.getData(2, 1).regionID() == 1); - assertTrue(field.getData(1, 2).regionID() == 2); - } - -} diff --git a/critterai/.svn/pristine/04/04a1f0f15856f7638cf0e814aa9f8582c5f81ffd.svn-base b/critterai/.svn/pristine/04/04a1f0f15856f7638cf0e814aa9f8582c5f81ffd.svn-base deleted file mode 100644 index 781b4bfe..00000000 Binary files a/critterai/.svn/pristine/04/04a1f0f15856f7638cf0e814aa9f8582c5f81ffd.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/05/0531078f1eea865337e7c098a0c1dc9540d876de.svn-base b/critterai/.svn/pristine/05/0531078f1eea865337e7c098a0c1dc9540d876de.svn-base deleted file mode 100644 index 21ab5c06..00000000 --- a/critterai/.svn/pristine/05/0531078f1eea865337e7c098a0c1dc9540d876de.svn-base +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "DetourEx.h" -#include "DetourCommon.h" - -extern "C" -{ - // The purpose of these functions is to allow checking that - // the Vector3 structure can be auto-cast by .NET interop to a - // float[3] pointer. The tests are needed to allow validation across - // various OS's and platforms. - - EXPORT_API void dtvlVectorTest(const float* vector3in, float* vector3out) - { - dtVcopy(vector3out, vector3in); - } - - EXPORT_API void dtvlVectorArrayTest(const float* vector3in - , const int vectorCount - , float* vector3out) - { - for (int i = 0; i < vectorCount; i++) - { - dtVcopy(&vector3out[i * 3], &vector3in[i * 3]); - } - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/08/0808919192b1f142828aac40a6b69d9fca956f1f.svn-base b/critterai/.svn/pristine/08/0808919192b1f142828aac40a6b69d9fca956f1f.svn-base deleted file mode 100644 index 700250c5..00000000 --- a/critterai/.svn/pristine/08/0808919192b1f142828aac40a6b69d9fca956f1f.svn-base +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Filters out all components that are not marked as static. (Editor Only) -/// -public sealed class StaticFilter - : ScriptableObject, IInputBuildProcessor -{ - /// - /// The priority of the processor. - /// - public int Priority { get { return NMBuild.MinPriority - 1; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// The priority of the processor. - /// - public bool DuplicatesAllowed { get { return false; } } - - /// - /// Processes the context. - /// - /// - /// - /// Applied during the state. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (state != InputBuildState.FilterComponents || context == null) - return true; - - context.info.filterCount++; - - List items = context.components; - - int count = 0; - - for (int i = items.Count - 1; i >= 0; i--) - { - if (!items[i].gameObject.isStatic) - { - items.RemoveAt(i); - count++; - } - } - - context.Log(string.Format("{0}: Applied static filter. Removed {1} components." - , name, count) - , this); - - return true; - } -} diff --git a/critterai/.svn/pristine/08/088ad41ef24b39007fe5def13414c91737853896.svn-base b/critterai/.svn/pristine/08/088ad41ef24b39007fe5def13414c91737853896.svn-base deleted file mode 100644 index aac59411..00000000 --- a/critterai/.svn/pristine/08/088ad41ef24b39007fe5def13414c91737853896.svn-base +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// Asset types created during the NMGen build process. - /// - [System.Flags] - public enum NMGenAssetFlag - { - /// - /// The intermediate asset. - /// - Heightfield = 0x01, - - /// - /// The intermediate asset. - /// - CompactField = 0x02, - - /// - /// The intermediate asset. - /// - ContourSet = 0x04, - - /// - /// The final asset. - /// - PolyMesh = 0x08, - - /// - /// The final asset. - /// - DetailMesh = 0x10 - } -} diff --git a/critterai/.svn/pristine/09/095484e2da52b9f21e7545938a3a690f4dfc7155.svn-base b/critterai/.svn/pristine/09/095484e2da52b9f21e7545938a3a690f4dfc7155.svn-base deleted file mode 100644 index bf6adce2..00000000 --- a/critterai/.svn/pristine/09/095484e2da52b9f21e7545938a3a690f4dfc7155.svn-base +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using System.Text; - -namespace org.critterai.nav -{ - /// - /// Navigation mesh polygon type. - /// - public enum NavmeshPolyType - { - /// - /// The polygon is a standard convex polygon that is part of the surface of the navigation - /// mesh. - /// - Standard = 0, - - /// - /// The polygon is an off-mesh connection. - /// - OffMeshConnection = 1 - } -} diff --git a/critterai/.svn/pristine/09/09a9ac637c050442c5d99241df3a6b821d600a7b.svn-base b/critterai/.svn/pristine/09/09a9ac637c050442c5d99241df3a6b821d600a7b.svn-base deleted file mode 100644 index fc83bc30..00000000 --- a/critterai/.svn/pristine/09/09a9ac637c050442c5d99241df3a6b821d600a7b.svn-base +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - The first thing to understand about CAINav is that it is - not a plug-and-play solution. Well, NMGen in Unity is plug-and-play. But creating the - navigation mesh is just the starting point. To use the navigation mesh you'll need to implement your own - code. And to do that you'll need to understand CAINav's structure. - - - - All core features of CAINav can be used in .NET-only applications. But there are many - ease-of use extensions available for use only in Unity Pro. Any library or namespace containing 'u3d' are Unity-only. - - - - - - Definitions - - - Core features: Elements (classes, interfaces, etc.) that provide the core features. They are part of the .NET API - and are available for use by all users. - - - Common extensions: Elements that provide ease-of-use features for all users. - - Unity extensions: Elements that provide ease-of-use features specific to Unity users. - - - - - -
- - The 10,000 Meter View - - - - - The below diagram shows the relationships of the core components from a construction/build - perspective. - - - - - - - - -
- -
- - 1 - Input Data - - - - - As a minimum you have to have some sort of source - geometry from which you can obtain vertex and triangle data. In Unity, the source geometry is - usually obtained from MeshFilters and Terrain objects. But anything that provides vertices and - triangles can be used. - - - - For more complex builds you may also need to provide other data such as off-mesh connections and - custom build processors. - - - - Common Extensions: - T:org.critterai.nmbuild.InputGeometry, - T:org.critterai.nmbuild.ProcessorSet - - - - The Unity extensions implement a flexible and extensible input build process that helps - gather everyting together for you. - - - - Triangle wrap direction on the xz-plane is used for the detection of which face of the triangle is - considered up. The y-axis is up/down. A picture is worth a thousand words. If your source geometry is wrapped differently - than shown, then it will need to be translated into this format before use in the NMGen - build process. - - - - - - CAINav uses the OpenGL coordinate system. - - - - - - - - - -
- -
- - 2 - NMGen Configuration - - - - - Source geometry may represent exterior natural geography or interior environments in any number - of different styles. The navigation clients may be human-type agents, vehicles, - wheeled robots, etc.; each with its own locomotion restrictions. For these reasons NMGen supports a large variety of - configuration settings that adjust how the navigation mesh data is generated. - - - - Core Classes: - T:org.critterai.nmgen.NMGenParams, - T:org.critterai.nmgen.NMGenTileParams - - - - -
- -
- - 3 - Polygon and Detail Meshes - - - - - The input data and NMGen configuration are used to create two types of meshes. The - polygon mesh provides the data needed for pathfinding operations. The optional detail mesh provides extra - height detail helpful for certain position queries. (Better height position at a higher memory cost.) - Together, these meshes provide the core structural data for the navigation mesh. - - - - Core Classes: - T:org.critterai.nmgen.PolyMesh, - T:org.critterai.nmgen.PolyMeshDetail - - - - - - - - -
- -
- - 4 - Off-Mesh Connections - - - - - In some cases there are special travel routes not based on the surface of the source geometry. For example, - an agent may be able to vault over a railing. Off-mesh connections can be used to represent - these routes and are connected to the navigation mesh as a single edge. - - - - Common Extensions: - T:org.critterai.nmbuild.ConnectionSet - - - - - - - - -
- -
- - 5 - Navigation Mesh Tiles - - - - - Tiles contain the data that makes up the navigation mesh. A navigation mesh - cannot exist without at least one tile. The ability to have multiple - tiles in a navigation mesh opens up a huge variety of options. Think: Navigation meshes that - cover large or complex areas, swapping tiles in and out at runtime. - - - - As a minimum, each tile contains a polygon mesh. It can also contain optional data such as - a detail mesh and off-mesh connections. - - - - Core Classes: - T:org.critterai.nav.NavmeshTileBuildData, - T:org.critterai.nav.NavmeshTileData, - T:org.critterai.nav.NavmeshTile - - - - -
- -
- - 6 - Navigation Mesh - - - - - A navigation mesh may contain a single rectangle tile, or a grid of square tiles. It is compact - and efficient with various methods of serializing, de-serializing, and swapping data in and out at - runtime. - - - Core Class: - T:org.critterai.nav.Navmesh - - - Unity Extensions: - T:CAIBakedNavmesh, - T:org.critterai.nav.u3d.INavmeshData - - - - -
- -
- - 7 - Navigation Mesh Query - - - - - The navigation mesh query is what all clients use to perform pathfinding and related - queries against the navigation mesh. Even if you use the crowd manager for steering, you'll - need to use a navigation mesh query for non-local pathfinding and other higher level planning. - - - - Core Class: - T:org.critterai.nav.NavmeshQuery - - - - - - - - -
- -
- - 8 - Query Filter - - - - - Filters allow pathfinding behavior to be altered at runtime without changing the structure of - the navigation mesh. They are used in most query methods to indicate which navigation mesh polygons - are considered accessible and which aren't. They also define the traversal cost of different types - of polygons. - - - Filters can be specific to individual agents or shared between groups of agents. - - - Core Class: - T:org.critterai.nav.NavmeshQueryFilter - - - - -
- -
- - 9 - Crowd Manger - - - - - The crowd manager implements local steering. You provide it with agents - to manage and local targets for the agents to move to, and it handles steering the agents in - order to avoid collisions with other agents. - - - - - - The use of the term "local" is important. CrowdManager can't do long distance path planning. - - - - Core Class: - T:org.critterai.nav.CrowdManager - - - - -
- -
- - Dependencies and Layers - - - - CAINav consists of multiple libraries, some optional. - - - - The plug-in and core libraries are required. The rest are technically optional. - Duplicate dependencies are not shown. - Some optional 'extras' available for Unity are not shown. - - - - - - - - -
- -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/09/09c5efb6c60de563cf311e8d70b55e31c87197b8.svn-base b/critterai/.svn/pristine/09/09c5efb6c60de563cf311e8d70b55e31c87197b8.svn-base deleted file mode 100644 index 62ce659b..00000000 --- a/critterai/.svn/pristine/09/09c5efb6c60de563cf311e8d70b55e31c87197b8.svn-base +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.nav.rcn; - -namespace org.critterai.nav -{ - /// - /// Represents the data buffer for a navigation mesh tile. - /// - /// - /// - /// Represents a fully built tile, ready to be add to a tiled . This is - /// the unabstracted tile. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class NavmeshTileData - { - /* - * Design notes: - * - * It is critical that the data always be allocated by the - * external library. This is because, in the vast majority of - * cases, ownership of the data will be transferred to a navmesh. - * The navmesh will then be responble for freeing the memory, which - * can't be done if the data was allocated on this side of the interop - * boundary. - * - */ - - private IntPtr mData = IntPtr.Zero; - private int mDataLength = 0; - private bool mIsOwned = false; - - /// - /// The size of the data buffer. - /// - public int Size { get { return mDataLength; } } - - /// - /// True if the memory for the buffer is managed by another object. - /// - public bool IsOwned { get { return mIsOwned; } } - - /// - /// Destructor - /// - ~NavmeshTileData() - { - if (!mIsOwned && mData != IntPtr.Zero) - NavmeshTileEx.dtnmFreeTileData(this); - mData = IntPtr.Zero; - } - - /// - /// Gets a serialized copy of the tile's data buffer. - /// - /// A serialized copy of the tile's data buffer. - public byte[] GetData() - { - if (mData == IntPtr.Zero) - return null; - - byte[] result = new byte[mDataLength]; - Marshal.Copy(mData, result, 0, mDataLength); - return result; - } - - /// - /// Gets the tile header. - /// - /// The tile header. - public NavmeshTileHeader GetHeader() - { - NavmeshTileHeader result = new NavmeshTileHeader(); - - if (mData == IntPtr.Zero) - return new NavmeshTileHeader(); - - NavmeshTileEx.dtnmGetTileDataHeaderAlt(mData, mDataLength, ref result); - - return result; - } - - /// - /// Create tile data from the provided build data. - /// - /// The build data. - /// A new tile data object, or null on error. - public static NavmeshTileData Create(NavmeshTileBuildData buildData) - { - if (buildData == null || buildData.IsDisposed) - return null; - - NavmeshTileData result = new NavmeshTileData(); - - if (NavmeshTileEx.dtnmBuildTileData(buildData, result)) - return result; - - return null; - } - - /// - /// Creates tile data from a serialized data created by . - /// - /// The serialized tile data. - /// A new tile data object, or null on error. - public static NavmeshTileData Create(byte[] rawTileData) - { - if (rawTileData == null) - return null; - - NavmeshTileData result = new NavmeshTileData(); - - if (NavmeshTileEx.dtnmBuildTileDataRaw(rawTileData, rawTileData.Length, result)) - return result; - - return null; - } - - /// - /// Gets the tile header from the raw tile data. - /// - /// The raw tile data. - /// The header. - /// The status of the request. - public static NavStatus GetHeader(byte[] rawTileData, out NavmeshTileHeader header) - { - header = new NavmeshTileHeader(); - - if (rawTileData == null) - return NavStatus.Failure | NavStatus.InvalidParam; - - return NavmeshTileEx.dtnmGetTileDataHeader(rawTileData, rawTileData.Length, ref header); - } - } -} diff --git a/critterai/.svn/pristine/0a/0a8d1cd2f9d2d8966472c082c2303d306ae61b64.svn-base b/critterai/.svn/pristine/0a/0a8d1cd2f9d2d8966472c082c2303d306ae61b64.svn-base deleted file mode 100644 index c7a6e9b0..00000000 --- a/critterai/.svn/pristine/0a/0a8d1cd2f9d2d8966472c082c2303d306ae61b64.svn-base +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nav -{ - /// - /// The type of navmesh polygon an agent is currently traversing. - /// - public enum CrowdAgentState : byte - { - /* - * Source: DetourCrowd.h CrowdAgentState - * - * The source does not explicitly assign values. - * - */ - - /// - /// The agent is not in a valid state. - /// - /// - /// - /// An agent will enter this state if its navigation mesh position cannot be determined. - /// If the cause is a temporary modification to the navigation mesh, then the problem may - /// auto-resolve itself. Otherwise, error handling will be needed. - /// - /// - Invalid, - - /// - /// The agent is traversing a normal navmesh polygon. - /// - OnMesh, - - /// - /// The agent is traversing an off-mesh connection. - /// - OffMesh - } -} diff --git a/critterai/.svn/pristine/0b/0b7446859d13f718376ea6c76089984e34952120.svn-base b/critterai/.svn/pristine/0b/0b7446859d13f718376ea6c76089984e34952120.svn-base deleted file mode 100644 index de1862ab..00000000 --- a/critterai/.svn/pristine/0b/0b7446859d13f718376ea6c76089984e34952120.svn-base +++ /dev/null @@ -1,199 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include "DetourPathQueue.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" -#include "DetourAlloc.h" -#include "DetourCommon.h" - - -dtPathQueue::dtPathQueue() : - m_nextHandle(1), - m_maxPathSize(0), - m_queueHead(0), - m_navquery(0) -{ - for (int i = 0; i < MAX_QUEUE; ++i) - m_queue[i].path = 0; -} - -dtPathQueue::~dtPathQueue() -{ - purge(); -} - -void dtPathQueue::purge() -{ - dtFreeNavMeshQuery(m_navquery); - m_navquery = 0; - for (int i = 0; i < MAX_QUEUE; ++i) - { - dtFree(m_queue[i].path); - m_queue[i].path = 0; - } -} - -bool dtPathQueue::init(const int maxPathSize, const int maxSearchNodeCount, dtNavMesh* nav) -{ - purge(); - - m_navquery = dtAllocNavMeshQuery(); - if (!m_navquery) - return false; - if (dtStatusFailed(m_navquery->init(nav, maxSearchNodeCount))) - return false; - - m_maxPathSize = maxPathSize; - for (int i = 0; i < MAX_QUEUE; ++i) - { - m_queue[i].ref = DT_PATHQ_INVALID; - m_queue[i].path = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*m_maxPathSize, DT_ALLOC_PERM); - if (!m_queue[i].path) - return false; - } - - m_queueHead = 0; - - return true; -} - -void dtPathQueue::update(const int maxIters) -{ - static const int MAX_KEEP_ALIVE = 2; // in update ticks. - - // Update path request until there is nothing to update - // or upto maxIters pathfinder iterations has been consumed. - int iterCount = maxIters; - - for (int i = 0; i < MAX_QUEUE; ++i) - { - PathQuery& q = m_queue[m_queueHead % MAX_QUEUE]; - - // Skip inactive requests. - if (q.ref == DT_PATHQ_INVALID) - { - m_queueHead++; - continue; - } - - // Handle completed request. - if (dtStatusSucceed(q.status) || dtStatusFailed(q.status)) - { - // If the path result has not been read in few frames, free the slot. - q.keepAlive++; - if (q.keepAlive > MAX_KEEP_ALIVE) - { - q.ref = DT_PATHQ_INVALID; - q.status = 0; - } - - m_queueHead++; - continue; - } - - // Handle query start. - if (q.status == 0) - { - q.status = m_navquery->initSlicedFindPath(q.startRef, q.endRef, q.startPos, q.endPos, q.filter); - } - // Handle query in progress. - if (dtStatusInProgress(q.status)) - { - int iters = 0; - q.status = m_navquery->updateSlicedFindPath(iterCount, &iters); - iterCount -= iters; - } - if (dtStatusSucceed(q.status)) - { - q.status = m_navquery->finalizeSlicedFindPath(q.path, &q.npath, m_maxPathSize); - } - - if (iterCount <= 0) - break; - - m_queueHead++; - } -} - -dtPathQueueRef dtPathQueue::request(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter) -{ - // Find empty slot - int slot = -1; - for (int i = 0; i < MAX_QUEUE; ++i) - { - if (m_queue[i].ref == DT_PATHQ_INVALID) - { - slot = i; - break; - } - } - // Could not find slot. - if (slot == -1) - return DT_PATHQ_INVALID; - - dtPathQueueRef ref = m_nextHandle++; - if (m_nextHandle == DT_PATHQ_INVALID) m_nextHandle++; - - PathQuery& q = m_queue[slot]; - q.ref = ref; - dtVcopy(q.startPos, startPos); - q.startRef = startRef; - dtVcopy(q.endPos, endPos); - q.endRef = endRef; - - q.status = 0; - q.npath = 0; - q.filter = filter; - q.keepAlive = 0; - - return ref; -} - -dtStatus dtPathQueue::getRequestStatus(dtPathQueueRef ref) const -{ - for (int i = 0; i < MAX_QUEUE; ++i) - { - if (m_queue[i].ref == ref) - return m_queue[i].status; - } - return DT_FAILURE; -} - -dtStatus dtPathQueue::getPathResult(dtPathQueueRef ref, dtPolyRef* path, int* pathSize, const int maxPath) -{ - for (int i = 0; i < MAX_QUEUE; ++i) - { - if (m_queue[i].ref == ref) - { - PathQuery& q = m_queue[i]; - // Free request for reuse. - q.ref = DT_PATHQ_INVALID; - q.status = 0; - // Copy path - int n = dtMin(q.npath, maxPath); - memcpy(path, q.path, sizeof(dtPolyRef)*n); - *pathSize = n; - return DT_SUCCESS; - } - } - return DT_FAILURE; -} diff --git a/critterai/.svn/pristine/0b/0ba7de1709b77e396782e48e1a5d65147dbc294f.svn-base b/critterai/.svn/pristine/0b/0ba7de1709b77e396782e48e1a5d65147dbc294f.svn-base deleted file mode 100644 index 30ea97bc..00000000 --- a/critterai/.svn/pristine/0b/0ba7de1709b77e396782e48e1a5d65147dbc294f.svn-base +++ /dev/null @@ -1,567 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include "DetourPathCorridor.h" -#include "DetourNavMeshQuery.h" -#include "DetourCommon.h" -#include "DetourAssert.h" -#include "DetourAlloc.h" - - -int dtMergeCorridorStartMoved(dtPolyRef* path, const int npath, const int maxPath, - const dtPolyRef* visited, const int nvisited) -{ - int furthestPath = -1; - int furthestVisited = -1; - - // Find furthest common polygon. - for (int i = npath-1; i >= 0; --i) - { - bool found = false; - for (int j = nvisited-1; j >= 0; --j) - { - if (path[i] == visited[j]) - { - furthestPath = i; - furthestVisited = j; - found = true; - } - } - if (found) - break; - } - - // If no intersection found just return current path. - if (furthestPath == -1 || furthestVisited == -1) - return npath; - - // Concatenate paths. - - // Adjust beginning of the buffer to include the visited. - const int req = nvisited - furthestVisited; - const int orig = dtMin(furthestPath+1, npath); - int size = dtMax(0, npath-orig); - if (req+size > maxPath) - size = maxPath-req; - if (size) - memmove(path+req, path+orig, size*sizeof(dtPolyRef)); - - // Store visited - for (int i = 0; i < req; ++i) - path[i] = visited[(nvisited-1)-i]; - - return req+size; -} - -int dtMergeCorridorEndMoved(dtPolyRef* path, const int npath, const int maxPath, - const dtPolyRef* visited, const int nvisited) -{ - int furthestPath = -1; - int furthestVisited = -1; - - // Find furthest common polygon. - for (int i = 0; i < npath; ++i) - { - bool found = false; - for (int j = nvisited-1; j >= 0; --j) - { - if (path[i] == visited[j]) - { - furthestPath = i; - furthestVisited = j; - found = true; - } - } - if (found) - break; - } - - // If no intersection found just return current path. - if (furthestPath == -1 || furthestVisited == -1) - return npath; - - // Concatenate paths. - const int ppos = furthestPath+1; - const int vpos = furthestVisited+1; - const int count = dtMin(nvisited-vpos, maxPath-ppos); - dtAssert(ppos+count <= maxPath); - if (count) - memcpy(path+ppos, visited+vpos, sizeof(dtPolyRef)*count); - - return ppos+count; -} - -int dtMergeCorridorStartShortcut(dtPolyRef* path, const int npath, const int maxPath, - const dtPolyRef* visited, const int nvisited) -{ - int furthestPath = -1; - int furthestVisited = -1; - - // Find furthest common polygon. - for (int i = npath-1; i >= 0; --i) - { - bool found = false; - for (int j = nvisited-1; j >= 0; --j) - { - if (path[i] == visited[j]) - { - furthestPath = i; - furthestVisited = j; - found = true; - } - } - if (found) - break; - } - - // If no intersection found just return current path. - if (furthestPath == -1 || furthestVisited == -1) - return npath; - - // Concatenate paths. - - // Adjust beginning of the buffer to include the visited. - const int req = furthestVisited; - if (req <= 0) - return npath; - - const int orig = furthestPath; - int size = dtMax(0, npath-orig); - if (req+size > maxPath) - size = maxPath-req; - if (size) - memmove(path+req, path+orig, size*sizeof(dtPolyRef)); - - // Store visited - for (int i = 0; i < req; ++i) - path[i] = visited[i]; - - return req+size; -} - -/** -@class dtPathCorridor -@par - -The corridor is loaded with a path, usually obtained from a #dtNavMeshQuery::findPath() query. The corridor -is then used to plan local movement, with the corridor automatically updating as needed to deal with inaccurate -agent locomotion. - -Example of a common use case: - --# Construct the corridor object and call #init() to allocate its path buffer. --# Obtain a path from a #dtNavMeshQuery object. --# Use #reset() to set the agent's current position. (At the beginning of the path.) --# Use #setCorridor() to load the path and target. --# Use #findCorners() to plan movement. (This handles dynamic path straightening.) --# Use #movePosition() to feed agent movement back into the corridor. (The corridor will automatically adjust as needed.) --# If the target is moving, use #moveTargetPosition() to update the end of the corridor. - (The corridor will automatically adjust as needed.) --# Repeat the previous 3 steps to continue to move the agent. - -The corridor position and target are always constrained to the navigation mesh. - -One of the difficulties in maintaining a path is that floating point errors, locomotion inaccuracies, and/or local -steering can result in the agent crossing the boundary of the path corridor, temporarily invalidating the path. -This class uses local mesh queries to detect and update the corridor as needed to handle these types of issues. - -The fact that local mesh queries are used to move the position and target locations results in two beahviors that -need to be considered: - -Every time a move function is used there is a chance that the path will become non-optimial. Basically, the further -the target is moved from its original location, and the further the position is moved outside the original corridor, -the more likely the path will become non-optimal. This issue can be addressed by periodically running the -#optimizePathTopology() and #optimizePathVisibility() methods. - -All local mesh queries have distance limitations. (Review the #dtNavMeshQuery methods for details.) So the most accurate -use case is to move the position and target in small increments. If a large increment is used, then the corridor -may not be able to accurately find the new location. Because of this limiation, if a position is moved in a large -increment, then compare the desired and resulting polygon references. If the two do not match, then path replanning -may be needed. E.g. If you move the target, check #getLastPoly() to see if it is the expected polygon. - -*/ - -dtPathCorridor::dtPathCorridor() : - m_path(0), - m_npath(0), - m_maxPath(0) -{ -} - -dtPathCorridor::~dtPathCorridor() -{ - dtFree(m_path); -} - -/// @par -/// -/// @warning Cannot be called more than once. -bool dtPathCorridor::init(const int maxPath) -{ - dtAssert(!m_path); - m_path = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*maxPath, DT_ALLOC_PERM); - if (!m_path) - return false; - m_npath = 0; - m_maxPath = maxPath; - return true; -} - -/// @par -/// -/// Essentially, the corridor is set of one polygon in size with the target -/// equal to the position. -void dtPathCorridor::reset(dtPolyRef ref, const float* pos) -{ - dtAssert(m_path); - dtVcopy(m_pos, pos); - dtVcopy(m_target, pos); - m_path[0] = ref; - m_npath = 1; -} - -/** -@par - -This is the function used to plan local movement within the corridor. One or more corners can be -detected in order to plan movement. It performs essentially the same function as #dtNavMeshQuery::findStraightPath. - -Due to internal optimizations, the maximum number of corners returned will be (@p maxCorners - 1) -For example: If the buffers are sized to hold 10 corners, the function will never return more than 9 corners. -So if 10 corners are needed, the buffers should be sized for 11 corners. - -If the target is within range, it will be the last corner and have a polygon reference id of zero. -*/ -int dtPathCorridor::findCorners(float* cornerVerts, unsigned char* cornerFlags, - dtPolyRef* cornerPolys, const int maxCorners, - dtNavMeshQuery* navquery, const dtQueryFilter* /*filter*/) -{ - dtAssert(m_path); - dtAssert(m_npath); - - static const float MIN_TARGET_DIST = 0.01f; - - int ncorners = 0; - navquery->findStraightPath(m_pos, m_target, m_path, m_npath, - cornerVerts, cornerFlags, cornerPolys, &ncorners, maxCorners); - - // Prune points in the beginning of the path which are too close. - while (ncorners) - { - if ((cornerFlags[0] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - dtVdist2DSqr(&cornerVerts[0], m_pos) > dtSqr(MIN_TARGET_DIST)) - break; - ncorners--; - if (ncorners) - { - memmove(cornerFlags, cornerFlags+1, sizeof(unsigned char)*ncorners); - memmove(cornerPolys, cornerPolys+1, sizeof(dtPolyRef)*ncorners); - memmove(cornerVerts, cornerVerts+3, sizeof(float)*3*ncorners); - } - } - - // Prune points after an off-mesh connection. - for (int i = 0; i < ncorners; ++i) - { - if (cornerFlags[i] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) - { - ncorners = i+1; - break; - } - } - - return ncorners; -} - -/** -@par - -Inaccurate locomotion or dynamic obstacle avoidance can force the argent position significantly outside the -original corridor. Over time this can result in the formation of a non-optimal corridor. Non-optimal paths can -also form near the corners of tiles. - -This function uses an efficient local visibility search to try to optimize the corridor -between the current position and @p next. - -The corridor will change only if @p next is visible from the current position and moving directly toward the point -is better than following the existing path. - -The more inaccurate the agent movement, the more beneficial this function becomes. Simply adjust the frequency -of the call to match the needs to the agent. - -This function is not suitable for long distance searches. -*/ -void dtPathCorridor::optimizePathVisibility(const float* next, const float pathOptimizationRange, - dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - dtAssert(m_path); - - // Clamp the ray to max distance. - float goal[3]; - dtVcopy(goal, next); - float dist = dtVdist2D(m_pos, goal); - - // If too close to the goal, do not try to optimize. - if (dist < 0.01f) - return; - - // Overshoot a little. This helps to optimize open fields in tiled meshes. - dist = dtMin(dist+0.01f, pathOptimizationRange); - - // Adjust ray length. - float delta[3]; - dtVsub(delta, goal, m_pos); - dtVmad(goal, m_pos, delta, pathOptimizationRange/dist); - - static const int MAX_RES = 32; - dtPolyRef res[MAX_RES]; - float t, norm[3]; - int nres = 0; - navquery->raycast(m_path[0], m_pos, goal, filter, &t, norm, res, &nres, MAX_RES); - if (nres > 1 && t > 0.99f) - { - m_npath = dtMergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, nres); - } -} - -/** -@par - -Inaccurate locomotion or dynamic obstacle avoidance can force the agent position significantly outside the -original corridor. Over time this can result in the formation of a non-optimal corridor. This function will use a -local area path search to try to re-optimize the corridor. - -The more inaccurate the agent movement, the more beneficial this function becomes. Simply adjust the frequency of -the call to match the needs to the agent. -*/ -bool dtPathCorridor::optimizePathTopology(dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - dtAssert(navquery); - dtAssert(filter); - dtAssert(m_path); - - if (m_npath < 3) - return false; - - static const int MAX_ITER = 32; - static const int MAX_RES = 32; - - dtPolyRef res[MAX_RES]; - int nres = 0; - navquery->initSlicedFindPath(m_path[0], m_path[m_npath-1], m_pos, m_target, filter); - navquery->updateSlicedFindPath(MAX_ITER, 0); - dtStatus status = navquery->finalizeSlicedFindPathPartial(m_path, m_npath, res, &nres, MAX_RES); - - if (status == DT_SUCCESS && nres > 0) - { - m_npath = dtMergeCorridorStartShortcut(m_path, m_npath, m_maxPath, res, nres); - return true; - } - - return false; -} - -bool dtPathCorridor::moveOverOffmeshConnection(dtPolyRef offMeshConRef, dtPolyRef* refs, - float* startPos, float* endPos, - dtNavMeshQuery* navquery) -{ - dtAssert(navquery); - dtAssert(m_path); - dtAssert(m_npath); - - // Advance the path up to and over the off-mesh connection. - dtPolyRef prevRef = 0, polyRef = m_path[0]; - int npos = 0; - while (npos < m_npath && polyRef != offMeshConRef) - { - prevRef = polyRef; - polyRef = m_path[npos]; - npos++; - } - if (npos == m_npath) - { - // Could not find offMeshConRef - return false; - } - - // Prune path - for (int i = npos; i < m_npath; ++i) - m_path[i-npos] = m_path[i]; - m_npath -= npos; - - refs[0] = prevRef; - refs[1] = polyRef; - - const dtNavMesh* nav = navquery->getAttachedNavMesh(); - dtAssert(nav); - - dtStatus status = nav->getOffMeshConnectionPolyEndPoints(refs[0], refs[1], startPos, endPos); - if (dtStatusSucceed(status)) - { - dtVcopy(m_pos, endPos); - return true; - } - - return false; -} - -/** -@par - -Behavior: - -- The movement is constrained to the surface of the navigation mesh. -- The corridor is automatically adjusted (shorted or lengthened) in order to remain valid. -- The new position will be located in the adjusted corridor's first polygon. - -The expected use case is that the desired position will be 'near' the current corridor. What is considered 'near' -depends on local polygon density, query search extents, etc. - -The resulting position will differ from the desired position if the desired position is not on the navigation mesh, -or it can't be reached using a local search. -*/ -void dtPathCorridor::movePosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - dtAssert(m_path); - dtAssert(m_npath); - - // Move along navmesh and update new position. - float result[3]; - static const int MAX_VISITED = 16; - dtPolyRef visited[MAX_VISITED]; - int nvisited = 0; - navquery->moveAlongSurface(m_path[0], m_pos, npos, filter, - result, visited, &nvisited, MAX_VISITED); - m_npath = dtMergeCorridorStartMoved(m_path, m_npath, m_maxPath, visited, nvisited); - - // Adjust the position to stay on top of the navmesh. - float h = m_pos[1]; - navquery->getPolyHeight(m_path[0], result, &h); - result[1] = h; - dtVcopy(m_pos, result); -} - -/** -@par - -Behavior: - -- The movement is constrained to the surface of the navigation mesh. -- The corridor is automatically adjusted (shorted or lengthened) in order to remain valid. -- The new target will be located in the adjusted corridor's last polygon. - -The expected use case is that the desired target will be 'near' the current corridor. What is considered 'near' depends on local polygon density, query search extents, etc. - -The resulting target will differ from the desired target if the desired target is not on the navigation mesh, or it can't be reached using a local search. -*/ -void dtPathCorridor::moveTargetPosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - dtAssert(m_path); - dtAssert(m_npath); - - // Move along navmesh and update new position. - float result[3]; - static const int MAX_VISITED = 16; - dtPolyRef visited[MAX_VISITED]; - int nvisited = 0; - navquery->moveAlongSurface(m_path[m_npath-1], m_target, npos, filter, - result, visited, &nvisited, MAX_VISITED); - m_npath = dtMergeCorridorEndMoved(m_path, m_npath, m_maxPath, visited, nvisited); - - // TODO: should we do that? - // Adjust the position to stay on top of the navmesh. - /* float h = m_target[1]; - navquery->getPolyHeight(m_path[m_npath-1], result, &h); - result[1] = h;*/ - - dtVcopy(m_target, result); -} - -/// @par -/// -/// The current corridor position is expected to be within the first polygon in the path. The target -/// is expected to be in the last polygon. -/// -/// @warning The size of the path must not exceed the size of corridor's path buffer set during #init(). -void dtPathCorridor::setCorridor(const float* target, const dtPolyRef* path, const int npath) -{ - dtAssert(m_path); - dtAssert(npath > 0); - dtAssert(npath < m_maxPath); - - dtVcopy(m_target, target); - memcpy(m_path, path, sizeof(dtPolyRef)*npath); - m_npath = npath; -} - -bool dtPathCorridor::trimInvalidPath(dtPolyRef safeRef, const float* safePos, - dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - dtAssert(navquery); - dtAssert(filter); - dtAssert(m_path); - - // Keep valid path as far as possible. - int n = 0; - while (n < m_npath && navquery->isValidPolyRef(m_path[n], filter)) { - n++; - } - - if (n == m_npath) - { - // All valid, no need to fix. - return true; - } - else if (n == 0) - { - // The first polyref is bad, use current safe values. - dtVcopy(m_pos, safePos); - m_path[0] = safeRef; - m_npath = 1; - } - else - { - // The path is partially usable. - m_npath = n; - } - - // Clamp target pos to last poly - float tgt[3]; - dtVcopy(tgt, m_target); - navquery->closestPointOnPolyBoundary(m_path[m_npath-1], tgt, m_target); - - return true; -} - -/// @par -/// -/// The path can be invalidated if there are structural changes to the underlying navigation mesh, or the state of -/// a polygon within the path changes resulting in it being filtered out. (E.g. An exclusion or inclusion flag changes.) -bool dtPathCorridor::isValid(const int maxLookAhead, dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - // Check that all polygons still pass query filter. - const int n = dtMin(m_npath, maxLookAhead); - for (int i = 0; i < n; ++i) - { - if (!navquery->isValidPolyRef(m_path[i], filter)) - return false; - } - - return true; -} diff --git a/critterai/.svn/pristine/0b/0baa58bfccb62a649f94edaccc45efd70288076b.svn-base b/critterai/.svn/pristine/0b/0baa58bfccb62a649f94edaccc45efd70288076b.svn-base deleted file mode 100644 index 93caf08e..00000000 Binary files a/critterai/.svn/pristine/0b/0baa58bfccb62a649f94edaccc45efd70288076b.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/0b/0bce216b4aa7ce71726a87c8277901ed5270808a.svn-base b/critterai/.svn/pristine/0b/0bce216b4aa7ce71726a87c8277901ed5270808a.svn-base deleted file mode 100644 index aca8c3f3..00000000 --- a/critterai/.svn/pristine/0b/0bce216b4aa7ce71726a87c8277901ed5270808a.svn-base +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010-2011 Stephen A. Pratt - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/critterai/.svn/pristine/0c/0c2ee76a27bb64ad476cc2955657ac27414f0f4e.svn-base b/critterai/.svn/pristine/0c/0c2ee76a27bb64ad476cc2955657ac27414f0f4e.svn-base deleted file mode 100644 index 2793b001..00000000 --- a/critterai/.svn/pristine/0c/0c2ee76a27bb64ad476cc2955657ac27414f0f4e.svn-base +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.u3d; -using org.critterai.u3d.editor; -using UnityEngine; -using UnityEditor; - -/// -/// compiler. -/// -/// -[CustomEditor(typeof(OFMConnection))] -public sealed class OFMConnectionEditor - : Editor -{ - private static Vector3 markerSize = new Vector3(0.3f, 0.05f, 0.3f); - - private string[] mFlagNames; - private CAINavEditorSettingsEditor.AreaGUIControl mAreaControl; - - void OnEnable() - { - ((NMGenComponent)target).debugEnabledLocal = true; - - mAreaControl = CAINavEditorSettingsEditor.CreateAreaControl("Area"); - mFlagNames = CAINavEditorSettingsEditor.GetFlagNames(); - } - - void OnDisable() - { - if (target) - ((NMGenComponent)target).debugEnabledLocal = false; - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - OFMConnection targ = (OFMConnection)target; - - EditorGUILayout.Separator(); - - bool changed = GUI.changed; - - NMGenComponent.debugEnabled = - EditorGUILayout.Toggle("Show All", NMGenComponent.debugEnabled); - - if (GUI.changed) - SceneView.RepaintAll(); - - GUI.changed = changed; - - // EditorGUILayout.Separator(); - // targ.End = (Transform)EditorGUILayout.ObjectField("Endpoint", targ.End, typeof(Transform), true); - - EditorGUILayout.Separator(); - - targ.Radius = EditorGUILayout.FloatField("Radius", targ.Radius); - targ.UserId = EditorGUILayout.IntField("User Id", targ.UserId); - - targ.Flags = (ushort)EditorGUILayout.MaskField("Flags", targ.Flags, mFlagNames); - - targ.IsBidirectional = EditorGUILayout.Toggle("Bidirectional", targ.IsBidirectional); - - EditorGUILayout.Separator(); - - targ.OverrideArea = EditorGUILayout.Toggle("Override Area", targ.OverrideArea); - - GUI.enabled = targ.OverrideArea; - - if (GUI.enabled) - targ.Area = mAreaControl.OnGUI(targ.Area); - else - EditorGUILayout.LabelField("Area", "Build Default"); - - GUI.enabled = true; - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - void OnSceneGUI() - { - OFMConnection targ = (OFMConnection)target; - - Undo.SetSnapshotTarget(target, "Endpoint move."); - - targ.EndPoint = Handles.PositionHandle(targ.EndPoint, Quaternion.identity); - - if (Input.GetMouseButtonDown(0)) - { - Undo.CreateSnapshot(); - Undo.RegisterSnapshot(); - } - - if (GUI.changed) - EditorUtility.SetDirty(targ); - } - - [DrawGizmo(GizmoType.NotSelected | GizmoType.SelectedOrChild | GizmoType.Pickable)] - static void DrawGizmo(OFMConnection marker, GizmoType type) - { - if (!NMGenComponent.debugEnabled && (type & GizmoType.SelectedOrChild) == 0) - return; - - Gizmos.color = ColorUtil.IntToColor(marker.Area, 0.6f); - - Gizmos.DrawCube(marker.transform.position, markerSize); - Gizmos.DrawCube(marker.EndPoint, markerSize); - } - - [MenuItem(EditorUtil.NMGenGameObjectMenu + "Off-Mesh Connection" - , false - , EditorUtil.GameObjectGroup + 1)] - static void CreateGameObject() - { - GameObject go = new GameObject("OffMeshConn"); - go.transform.position = EditorUtil.GetCreatePosition(); - - OFMConnection comp = go.AddComponent(); - comp.EndPoint = go.transform.position + Vector3.up + Vector3.right + Vector3.forward; - - Selection.activeGameObject = go; - } -} diff --git a/critterai/.svn/pristine/0c/0c6c79ece11eeb825282d77b9b29da8360297805.svn-base b/critterai/.svn/pristine/0c/0c6c79ece11eeb825282d77b9b29da8360297805.svn-base deleted file mode 100644 index d7e2d37a..00000000 --- a/critterai/.svn/pristine/0c/0c6c79ece11eeb825282d77b9b29da8360297805.svn-base +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai -{ - /// - /// Provides various 3D vector utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Vector3Util - { - /// - /// The zero vector. (0, 0, 0) - /// - public static Vector3 Zero - { - get { return new Vector3(0, 0, 0); } - } - - /// - /// Performs a "right-handed" vector - /// cross product. - /// (u x v) - /// - /// - /// - /// The resulting vector will be perpendicular to the plane containing the two - /// vectors. - /// - /// - /// Special Case: The result will be zero if the two vectors are parallel. - /// - /// - /// Vector u. - /// Vector v. - /// The cross product of the vectors. - public static Vector3 Cross(Vector3 u, Vector3 v) - { - return new Vector3(u.y * v.z - u.z * v.y - , -u.x * v.z + u.z * v.x - , u.x * v.y - u.y * v.x); - } - - /// - /// Returns the square of the distance between two points. - /// - /// Point A. - /// Point B. - /// The square of the distance between the points. - public static float GetDistanceSq(Vector3 a, Vector3 b) - { - Vector3 d = a - b; - return (d.x * d.x + d.y * d.y + d.z * d.z); - } - - /// - /// Normalizes the specified vector such that its length is equal to one. (Costly method!) - /// - /// The vector. - /// A normalized vector. - public static Vector3 Normalize(Vector3 v) - { - float m = (float)Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - if (m < MathUtil.Tolerance) - m = 1; - - v.x /= m; - v.y /= m; - v.z /= m; - - if (Math.Abs(v.x) < MathUtil.Tolerance) - v.x = 0; - if (Math.Abs(v.y) < MathUtil.Tolerance) - v.y = 0; - if (Math.Abs(v.z) < MathUtil.Tolerance) - v.z = 0; - - return v; - } - - /// - /// Gets the distance between the specified points on the xz-plane. (Ignores y-axis.) - /// - /// Vector u. - /// Vector v. - /// The distance between the specified points on the xz-plane. - public static float GetDistance2D(Vector3 u, Vector3 v) - { - float dx = v.x - u.x; - float dz = v.z - u.z; - return (float)Math.Sqrt(dx * dx + dz * dz); - } - - /// - /// Returns the square of the length of the vector. - /// - /// The vector. - /// The square of the length of the vector. - public static float GetLengthSq(Vector3 v) - { - return (v.x * v.x + v.y * v.y + v.z * v.z); - } - - /// - /// Returns the vector - /// dot product - /// of the specified vectors. (u . v) - /// - /// Vector u. - /// Vector v. - /// The dot product of the vectors. - public static float Dot(Vector3 u, Vector3 v) - { - return (u.x * v.x) + (u.y * v.y) + (u.z * v.z); - } - - /// - /// Determines whether or not the specified vectors are equal within the specified - /// tolerance. - /// - /// - /// - /// Change in beahvior: Prior to version 0.4, the area of equality for this method was - /// an axis-aligned bounding box at the tip of the vector. As of version 0.4 the area of - /// equality is a sphere. This change improves performance. - /// - /// - /// Vector u. - /// Vector v. - /// The allowed tolerance. [Limit: >= 0] - /// - /// True if the specified vectors are close enough to be considered equal. - /// - public static bool SloppyEquals(Vector3 u, Vector3 v, float tolerance) - { - Vector3 d = u - v; - return (d.x * d.x + d.y * d.y + d.z * d.z) <= tolerance * tolerance; - } - - /// - /// Determines whether or not the two points are within range of each other based on a - /// xz-plane radius and a y-axis height. - /// - /// - /// - /// Essentially, one point defines the centroid of the cylinder and the other is - /// tested for inclusion. The height test is (Math.Abs(deltaY) < height) - /// - /// - /// Point A. - /// Point B. - /// The allowed radius on the xz-plane. - /// The allowed y-axis delta. - /// - /// True if the two vectors are within the xz-radius and y-height of each other. - /// - public static bool IsInRange(Vector3 a, Vector3 b, float radius, float height) - { - Vector3 d = b - a; - return (d.x * d.x + d.z * d.z) < radius * radius - && Math.Abs(d.y) < height; - } - - /// - /// Translates point A toward point B by the specified factor of the distance between them. - /// - /// - /// - /// Examples: - /// - /// - /// If the factor is 0.0, then the result will equal A.
- /// If the factor is 0.5, then the result will be the midpoint between A and B.
- /// If the factor is 1.0, then the result will equal B.
- ///
- ///
- /// Point A. - /// Point B. - /// - /// The factor that governs the distance the point is translated from A toward B. - /// - /// The point translated toward point B from point A. - public static Vector3 TranslateToward(Vector3 a, Vector3 b, float factor) - { - return new Vector3(a.x + (b.x - a.x) * factor - , a.y + (b.y - a.y) * factor - , a.z + (b.z - a.z) * factor); - } - - /// - /// Flattens the vector array into a float array in the form (x, y, z) * vertCount. - /// - /// An array of vectors. - /// The number of vectors. - /// An array of flattened vectors. - public static float[] Flatten(Vector3[] vectors, int count) - { - float[] result = new float[count * 3]; - for (int i = 0; i < count; i++) - { - result[i * 3] = vectors[i].x; - result[i * 3 + 1] = vectors[i].y; - result[i * 3 + 2] = vectors[i].z; - } - return result; - } - - /// - /// Creates an array of vectors from a flattend array of vectors. - /// - /// An array of vectors. [(x, y, z) * vertCount] - /// An array of vectors. - public static Vector3[] GetVectors(float[] flatVectors) - { - int count = flatVectors.Length / 3; - Vector3[] result = new Vector3[count]; - for (int i = 0; i < count; i++) - { - int p = i * 3; - result[i] = new Vector3(flatVectors[p + 0] - , flatVectors[p + 1] - , flatVectors[p + 2]); - } - return result; - } - - /// - /// Copies a range of vectors from a flattend array to a vector array. - /// - /// - /// - /// If a target buffer is provided is must be large enough to contain the results. - /// - /// - /// If the target buffer is null a new array will be created with a length of - /// + - /// - /// - /// An array of vectors in the form (x, y, z) * vertCount. - /// The index of the start vector in the source array. - /// The target vector buffer. (Or null.) - /// The index within the target buffer to start the copy. - /// The number of vectors to copy. - /// - /// The reference to the buffer, or a new array if no buffer - /// was provided. - /// - public static Vector3[] GetVectors(float[] source - , int sourceIndex - , Vector3[] target - , int targetIndex - , int count) - { - if (target == null) - target = new Vector3[count + targetIndex]; - - for (int i = 0; i < count; i++) - { - int p = (sourceIndex + i) * 3; - target[targetIndex + i] = new Vector3(source[p + 0], source[p + 1], source[p + 2]); - } - - return target; - } - - /// - /// Gets the minimum and maximum bounds of the AABB which contains the array of points. - /// - /// An array of points. - /// The number of points in the array. - /// The mimimum bounds of the AABB. - /// The maximum bounds of the AABB. - public static void GetBounds(Vector3[] vectors - , int count - , out Vector3 boundsMin - , out Vector3 boundsMax) - { - boundsMin = vectors[0]; - boundsMax = vectors[0]; - - for (int i = 1; i < count; i++) - { - boundsMin.x = Math.Min(boundsMin.x, vectors[i].x); - boundsMin.y = Math.Min(boundsMin.y, vectors[i].y); - boundsMin.z = Math.Min(boundsMin.z, vectors[i].z); - boundsMax.x = Math.Max(boundsMax.x, vectors[i].x); - boundsMax.y = Math.Max(boundsMax.y, vectors[i].y); - boundsMax.z = Math.Max(boundsMax.z, vectors[i].z); - } - } - - /// - /// Returns a standard string representation of the specified vector. - /// - /// A vector. - /// A string representing the vector. - public static string ToString(Vector3 vector) - { - return string.Format("[{0:F3}, {1:F3}, {2:F3}]" - , vector.x, vector.y, vector.z); - } - } -} diff --git a/critterai/.svn/pristine/0c/0cb9cc0cb59ef3341e19642954df0c0a30dfd2f2.svn-base b/critterai/.svn/pristine/0c/0cb9cc0cb59ef3341e19642954df0c0a30dfd2f2.svn-base deleted file mode 100644 index 5db540bf..00000000 Binary files a/critterai/.svn/pristine/0c/0cb9cc0cb59ef3341e19642954df0c0a30dfd2f2.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/0c/0cd61858f8e4be9f6107e168475d4a3f00086570.svn-base b/critterai/.svn/pristine/0c/0cd61858f8e4be9f6107e168475d4a3f00086570.svn-base deleted file mode 100644 index a7efd634..00000000 --- a/critterai/.svn/pristine/0c/0cd61858f8e4be9f6107e168475d4a3f00086570.svn-base +++ /dev/null @@ -1 +0,0 @@ -The files in this directory are governed by their own individual licenses. diff --git a/critterai/.svn/pristine/0d/0d0a108e880a89e34e81336346fe9a9be9b9081f.svn-base b/critterai/.svn/pristine/0d/0d0a108e880a89e34e81336346fe9a9be9b9081f.svn-base deleted file mode 100644 index b77cfad8..00000000 Binary files a/critterai/.svn/pristine/0d/0d0a108e880a89e34e81336346fe9a9be9b9081f.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/0d/0dada17fde9354aaf374c3e34254a6deeffd0ee6.svn-base b/critterai/.svn/pristine/0d/0dada17fde9354aaf374c3e34254a6deeffd0ee6.svn-base deleted file mode 100644 index b5ed66ec..00000000 --- a/critterai/.svn/pristine/0d/0dada17fde9354aaf374c3e34254a6deeffd0ee6.svn-base +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.critterai.math.MathUtil; -import org.critterai.math.Vector2; - -/** - * Provides operations related to 2-dimensional lines and line segments. - *

This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, divide by zero checks only when needed by the algorithm, etc.

- *

Static operations are thread safe.

- */ -public final class Line2 -{ - - private Line2() { } - - /** - * Indicates whether or not line AB intersects line BC. - * @param ax The x-value for point A on line AB. - * @param ay The y-value for point A on line AB. - * @param bx The x-value for point B on line AB. - * @param by The y-value for point B on line AB. - * @param cx The x-value for point C on line CD. - * @param cy The y-value for point C on line CD. - * @param dx The x-value for point D on line CD. - * @param dy The y-value for point D on line CD. - * @return TRUE if the two lines are either collinear or intersect at one point. - * Otherwise FALSE. - */ - public static boolean linesIntersect(int ax, int ay - , int bx, int by - , int cx, int cy - , int dx, int dy) - { - int numerator = ((ay - cy) * (dx - cx)) - ((ax - cx) * (dy - cy)); - int denominator = ((bx - ax) * (dy - cy)) - ((by - ay) * (dx - cx)); - if (denominator == 0 && numerator != 0) - // Lines are parallel. - return false; - // Lines are collinear or intersect at a single point. - return true; - } - - /** - * Indicates whether or not line AB intersects line BC. - * @param ax The x-value for point A on line AB. - * @param ay The y-value for point A on line AB. - * @param bx The x-value for point B on line AB. - * @param by The y-value for point B on line AB. - * @param cx The x-value for point C on line CD. - * @param cy The y-value for point C on line CD. - * @param dx The x-value for point D on line CD. - * @param dy The y-value for point D on line CD. - * @return TRUE if the two lines are either collinear or intersect at one point. - * Otherwise FALSE. - */ - public static boolean linesIntersect(float ax, float ay - , float bx, float by - , float cx, float cy - , float dx, float dy) - { - float numerator = ((ay - cy) * (dx - cx)) - ((ax - cx) * (dy - cy)); - float denominator = ((bx - ax) * (dy - cy)) - ((by - ay) * (dx - cx)); - if (denominator == 0 && numerator != 0) - // Lines are parallel. - return false; - // Lines are collinear or intersect at a single point. - return true; - } - - /** - * Returns the distance squared from point P to line segment AB. - * @param px The x-value of point P. - * @param py The y-value of point P. - * @param ax The x-value of point A of line segment AB. - * @param ay The y-value of point A of line segment AB. - * @param bx The x-value of point B of line segment AB. - * @param by The y-value of point B of line segment AB. - * @return The distance squared from point B to line segment AB. - */ - public static float getPointSegmentDistanceSq(float px, float py - , float ax, float ay - , float bx, float by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line AB that is - * closest to P and then calculate the distance between P and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = deltaABx * deltaABx + deltaABy * deltaABy; - - if (segmentABLengthSq < MathUtil.EPSILON_STD) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = (deltaAPx * deltaABx + deltaAPy * deltaABy) / segmentABLengthSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and closer to A. - // So return distanceSq from P to A. - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) + (py - by)*(py - by); - - // Closest point on lineAB is inside segment AB. So find the exact point on AB - // and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - /** - * Returns the distance squared from point P to line AB. - * @param px The x-value of point P. - * @param py The y-value of point P. - * @param ax The x-value of point A of line AB. - * @param ay The y-value of point A of line AB. - * @param bx The x-value of point B of line AB. - * @param by The y-value of point B of line AB. - * @return The distance squared from point B to line AB. - */ - public static float getPointLineDistanceSq(float px, float py, float ax, float ay, float bx, float by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line AB that is - * closest to P and then calculate the distance between P and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = deltaABx * deltaABx + deltaABy * deltaABy; - - if (segmentABLengthSq < MathUtil.EPSILON_STD) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = (deltaAPx * deltaABx + deltaAPy * deltaABy) / segmentABLengthSq; - - // The calculation in parenthesis is the location of the point on the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - /** - * Returns the normalized vector that is perpendicular to line AB, or a zero - * length vector if points A and B do not form a line. - *

The direction of the vector will be to the right when viewed from point A to point B - * along the line.

- *

WARNING: This is an expensive operation.

- * @param ax The x-value of point A on line AB. - * @param ay The y-value of point A on line AB. - * @param bx The x-value of point B on line AB. - * @param by The y-value of point B on line AB. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 getNormalAB(float ax, float ay - , float bx, float by - , Vector2 out) - { - if (ax == bx && ay == by) - { - // Points do not form a line. - out.set(0, 0); - } - else - { - Vector2.getDirectionAB(ax, ay, bx, by, out); - out.set(out.y, -out.x); - } - return out; - } - - /** - * Determines the relationship between lines AB and CD. - *

While this check is technically inclusive of the segment end points, floating point - * errors can result in end point intersection being missed. If this matters, - * a {@link Vector2#sloppyEquals(float, float, float)} or similar test of the intersection point can - * be performed to check for this issue.

- * @param ax The x-value for point A on line AB. - * @param ay The y-value for point A on line AB. - * @param bx The x-value for point B on line AB. - * @param by The y-value for point B on line AB. - * @param cx The x-value for point C on line CD. - * @param cy The y-value for point C on line CD. - * @param dx The x-value for point D on line CD. - * @param dy The y-value for point D on line CD. - * @param outIntersectionPoint If provided and the lines intersect at - * a single point, the vector will be updated with the point of intersection. - * (This argument may be null.) - * @return The relationship between lines AB and CD. - */ - public static LineRelType getRelationship(float ax, float ay - , float bx, float by - , float cx, float cy - , float dx, float dy - , Vector2 outIntersectionPoint) - { - - float deltaAxBx = bx - ax; - float deltaAyBy = by - ay; - - float deltaCxDx = dx - cx; - float deltaCyDy = dy - cy; - - float deltaCyAy = ay - cy; - float deltaCxAx = ax - cx; - - float numerator = (deltaCyAy * deltaCxDx) - (deltaCxAx * deltaCyDy); - float denominator = (deltaAxBx * deltaCyDy) - (deltaAyBy * deltaCxDx); - - // Exit early if the lines do not intersect at a single point. - if (denominator == 0) - { - if (numerator == 0) - return LineRelType.COLLINEAR; - return LineRelType.PARALLEL; - } - - // Lines definitely intersect at a single point. - - float factorAB = numerator / denominator; - float factorCD = ((deltaCyAy * deltaAxBx) - (deltaCxAx * deltaAyBy)) / denominator; - - if (outIntersectionPoint != null) - outIntersectionPoint.set(ax + (factorAB * deltaAxBx) - , ay + (factorAB * deltaAyBy)); - - // Determine the type of intersection - if ((factorAB >= 0.0f) && (factorAB <= 1.0f) && (factorCD >= 0.0f) && (factorCD <= 1.0f)) - { - return LineRelType.SEGMENTS_INTERSECT; - } - else if ((factorCD >= 0.0f) && (factorCD <= 1.0f)) - { - return LineRelType.ALINE_CROSSES_BSEG; - } - else if ((factorAB >= 0.0f) && (factorAB <= 1.0f)) - { - return LineRelType.BLINE_CROSSES_ASEG; - } - - return LineRelType.LINES_INTERSECT; - - } - -} diff --git a/critterai/.svn/pristine/0d/0dccbf71302c35545984e6ce1efb9b9b01430058.svn-base b/critterai/.svn/pristine/0d/0dccbf71302c35545984e6ce1efb9b9b01430058.svn-base deleted file mode 100644 index 7e0cf685..00000000 --- a/critterai/.svn/pristine/0d/0dccbf71302c35545984e6ce1efb9b9b01430058.svn-base +++ /dev/null @@ -1,1440 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include -#include "DetourCrowd.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" -#include "DetourObstacleAvoidance.h" -#include "DetourCommon.h" -#include "DetourAssert.h" -#include "DetourAlloc.h" - - -dtCrowd* dtAllocCrowd() -{ - void* mem = dtAlloc(sizeof(dtCrowd), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtCrowd; -} - -void dtFreeCrowd(dtCrowd* ptr) -{ - if (!ptr) return; - ptr->~dtCrowd(); - dtFree(ptr); -} - - -static const int MAX_ITERS_PER_UPDATE = 10; - -static const int MAX_PATHQUEUE_NODES = 4096; -static const int MAX_COMMON_NODES = 512; - -inline float tween(const float t, const float t0, const float t1) -{ - return dtClamp((t-t0) / (t1-t0), 0.0f, 1.0f); -} - -static void integrate(dtCrowdAgent* ag, const float dt) -{ - // Fake dynamic constraint. - const float maxDelta = ag->params.maxAcceleration * dt; - float dv[3]; - dtVsub(dv, ag->nvel, ag->vel); - float ds = dtVlen(dv); - if (ds > maxDelta) - dtVscale(dv, dv, maxDelta/ds); - dtVadd(ag->vel, ag->vel, dv); - - // Integrate - if (dtVlen(ag->vel) > 0.0001f) - dtVmad(ag->npos, ag->npos, ag->vel, dt); - else - dtVset(ag->vel,0,0,0); -} - -static bool overOffmeshConnection(const dtCrowdAgent* ag, const float radius) -{ - if (!ag->ncorners) - return false; - - const bool offMeshConnection = (ag->cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) ? true : false; - if (offMeshConnection) - { - const float distSq = dtVdist2DSqr(ag->npos, &ag->cornerVerts[(ag->ncorners-1)*3]); - if (distSq < radius*radius) - return true; - } - - return false; -} - -static float getDistanceToGoal(const dtCrowdAgent* ag, const float range) -{ - if (!ag->ncorners) - return range; - - const bool endOfPath = (ag->cornerFlags[ag->ncorners-1] & DT_STRAIGHTPATH_END) ? true : false; - if (endOfPath) - return dtMin(dtVdist2D(ag->npos, &ag->cornerVerts[(ag->ncorners-1)*3]), range); - - return range; -} - -static void calcSmoothSteerDirection(const dtCrowdAgent* ag, float* dir) -{ - if (!ag->ncorners) - { - dtVset(dir, 0,0,0); - return; - } - - const int ip0 = 0; - const int ip1 = dtMin(1, ag->ncorners-1); - const float* p0 = &ag->cornerVerts[ip0*3]; - const float* p1 = &ag->cornerVerts[ip1*3]; - - float dir0[3], dir1[3]; - dtVsub(dir0, p0, ag->npos); - dtVsub(dir1, p1, ag->npos); - dir0[1] = 0; - dir1[1] = 0; - - float len0 = dtVlen(dir0); - float len1 = dtVlen(dir1); - if (len1 > 0.001f) - dtVscale(dir1,dir1,1.0f/len1); - - dir[0] = dir0[0] - dir1[0]*len0*0.5f; - dir[1] = 0; - dir[2] = dir0[2] - dir1[2]*len0*0.5f; - - dtVnormalize(dir); -} - -static void calcStraightSteerDirection(const dtCrowdAgent* ag, float* dir) -{ - if (!ag->ncorners) - { - dtVset(dir, 0,0,0); - return; - } - dtVsub(dir, &ag->cornerVerts[0], ag->npos); - dir[1] = 0; - dtVnormalize(dir); -} - -static int addNeighbour(const int idx, const float dist, - dtCrowdNeighbour* neis, const int nneis, const int maxNeis) -{ - // Insert neighbour based on the distance. - dtCrowdNeighbour* nei = 0; - if (!nneis) - { - nei = &neis[nneis]; - } - else if (dist >= neis[nneis-1].dist) - { - if (nneis >= maxNeis) - return nneis; - nei = &neis[nneis]; - } - else - { - int i; - for (i = 0; i < nneis; ++i) - if (dist <= neis[i].dist) - break; - - const int tgt = i+1; - const int n = dtMin(nneis-i, maxNeis-tgt); - - dtAssert(tgt+n <= maxNeis); - - if (n > 0) - memmove(&neis[tgt], &neis[i], sizeof(dtCrowdNeighbour)*n); - nei = &neis[i]; - } - - memset(nei, 0, sizeof(dtCrowdNeighbour)); - - nei->idx = idx; - nei->dist = dist; - - return dtMin(nneis+1, maxNeis); -} - -static int getNeighbours(const float* pos, const float height, const float range, - const dtCrowdAgent* skip, dtCrowdNeighbour* result, const int maxResult, - dtCrowdAgent** agents, const int /*nagents*/, dtProximityGrid* grid) -{ - int n = 0; - - static const int MAX_NEIS = 32; - unsigned short ids[MAX_NEIS]; - int nids = grid->queryItems(pos[0]-range, pos[2]-range, - pos[0]+range, pos[2]+range, - ids, MAX_NEIS); - - for (int i = 0; i < nids; ++i) - { - const dtCrowdAgent* ag = agents[ids[i]]; - - if (ag == skip) continue; - - // Check for overlap. - float diff[3]; - dtVsub(diff, pos, ag->npos); - if (fabsf(diff[1]) >= (height+ag->params.height)/2.0f) - continue; - diff[1] = 0; - const float distSqr = dtVlenSqr(diff); - if (distSqr > dtSqr(range)) - continue; - - n = addNeighbour(ids[i], distSqr, result, n, maxResult); - } - return n; -} - -/** -@class dtCrowd -@par - -This is the core class of the @ref crowd module. See the @ref crowd documentation for a summary -of the crowd features. - -A common method for setting up the crowd is as follows: - --# Allocate the crowd using #dtAllocCrowd. --# Initialize the crowd using #init(). --# Set the avoidance configurations using #setObstacleAvoidanceParams(). --# Add agents using #addAgent() and make an initial movement request using #requestMoveTarget(). - -A common process for managing the crowd is as follows: - --# Call #update() to allow the crowd to manage its agents. --# Retrieve agent information using #getActiveAgents(). --# Make movement requests using #requestMoveTarget() and #adjustMoveTarget(). --# Repeat every frame. - -Some agent configuration settings can be updated using #updateAgentParameters(). But the crowd owns the -agent position. So it is not possible to update an active agent's position. If agent position -must be fed back into the crowd, the agent must be removed and re-added. - -Notes: - -- Path related information is available for newly added agents only after an #update() has been - performed. -- Agent objects are kept in a pool and re-used. So it is important when using agent objects to check the value of - #dtCrowdAgent::active to determine if the agent is actually in use or not. -- This class is meant to provide 'local' movement. There is a limit of 256 polygons in the path corridor. - So it is not meant to provide automatic pathfinding services over long distances. - -@see dtAllocCrowd(), dtFreeCrowd(), init(), dtCrowdAgent - -*/ - -dtCrowd::dtCrowd() : - m_maxAgents(0), - m_agents(0), - m_activeAgents(0), - m_agentAnims(0), - m_obstacleQuery(0), - m_grid(0), - m_pathResult(0), - m_maxPathResult(0), - m_maxAgentRadius(0), - m_velocitySampleCount(0), - m_moveRequests(0), - m_moveRequestCount(0), - m_navquery(0) -{ -} - -dtCrowd::~dtCrowd() -{ - purge(); -} - -void dtCrowd::purge() -{ - for (int i = 0; i < m_maxAgents; ++i) - m_agents[i].~dtCrowdAgent(); - dtFree(m_agents); - m_agents = 0; - m_maxAgents = 0; - - dtFree(m_activeAgents); - m_activeAgents = 0; - - dtFree(m_agentAnims); - m_agentAnims = 0; - - dtFree(m_pathResult); - m_pathResult = 0; - - dtFree(m_moveRequests); - m_moveRequests = 0; - m_moveRequestCount = 0; - - dtFreeProximityGrid(m_grid); - m_grid = 0; - - dtFreeObstacleAvoidanceQuery(m_obstacleQuery); - m_obstacleQuery = 0; - - dtFreeNavMeshQuery(m_navquery); - m_navquery = 0; -} - -/// @par -/// -/// May be called more than once to purge and re-initialize the crowd. -bool dtCrowd::init(const int maxAgents, const float maxAgentRadius, dtNavMesh* nav) -{ - purge(); - - m_maxAgents = maxAgents; - m_maxAgentRadius = maxAgentRadius; - - dtVset(m_ext, m_maxAgentRadius*2.0f,m_maxAgentRadius*1.5f,m_maxAgentRadius*2.0f); - - m_grid = dtAllocProximityGrid(); - if (!m_grid) - return false; - if (!m_grid->init(m_maxAgents*4, maxAgentRadius*3)) - return false; - - m_obstacleQuery = dtAllocObstacleAvoidanceQuery(); - if (!m_obstacleQuery) - return false; - if (!m_obstacleQuery->init(6, 8)) - return false; - - // Init obstacle query params. - memset(m_obstacleQueryParams, 0, sizeof(m_obstacleQueryParams)); - for (int i = 0; i < DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS; ++i) - { - dtObstacleAvoidanceParams* params = &m_obstacleQueryParams[i]; - params->velBias = 0.4f; - params->weightDesVel = 2.0f; - params->weightCurVel = 0.75f; - params->weightSide = 0.75f; - params->weightToi = 2.5f; - params->horizTime = 2.5f; - params->gridSize = 33; - params->adaptiveDivs = 7; - params->adaptiveRings = 2; - params->adaptiveDepth = 5; - } - - // Allocate temp buffer for merging paths. - m_maxPathResult = 256; - m_pathResult = (dtPolyRef*)dtAlloc(sizeof(dtPolyRef)*m_maxPathResult, DT_ALLOC_PERM); - if (!m_pathResult) - return false; - - m_moveRequests = (MoveRequest*)dtAlloc(sizeof(MoveRequest)*m_maxAgents, DT_ALLOC_PERM); - if (!m_moveRequests) - return false; - m_moveRequestCount = 0; - - if (!m_pathq.init(m_maxPathResult, MAX_PATHQUEUE_NODES, nav)) - return false; - - m_agents = (dtCrowdAgent*)dtAlloc(sizeof(dtCrowdAgent)*m_maxAgents, DT_ALLOC_PERM); - if (!m_agents) - return false; - - m_activeAgents = (dtCrowdAgent**)dtAlloc(sizeof(dtCrowdAgent*)*m_maxAgents, DT_ALLOC_PERM); - if (!m_activeAgents) - return false; - - m_agentAnims = (dtCrowdAgentAnimation*)dtAlloc(sizeof(dtCrowdAgentAnimation)*m_maxAgents, DT_ALLOC_PERM); - if (!m_agentAnims) - return false; - - for (int i = 0; i < m_maxAgents; ++i) - { - new(&m_agents[i]) dtCrowdAgent(); - m_agents[i].active = 0; - if (!m_agents[i].corridor.init(m_maxPathResult)) - return false; - } - - for (int i = 0; i < m_maxAgents; ++i) - { - m_agentAnims[i].active = 0; - } - - // The navquery is mostly used for local searches, no need for large node pool. - m_navquery = dtAllocNavMeshQuery(); - if (!m_navquery) - return false; - if (dtStatusFailed(m_navquery->init(nav, MAX_COMMON_NODES))) - return false; - - return true; -} - -void dtCrowd::setObstacleAvoidanceParams(const int idx, const dtObstacleAvoidanceParams* params) -{ - if (idx >= 0 && idx < DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS) - memcpy(&m_obstacleQueryParams[idx], params, sizeof(dtObstacleAvoidanceParams)); -} - -const dtObstacleAvoidanceParams* dtCrowd::getObstacleAvoidanceParams(const int idx) const -{ - if (idx >= 0 && idx < DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS) - return &m_obstacleQueryParams[idx]; - return 0; -} - -const int dtCrowd::getAgentCount() const -{ - return m_maxAgents; -} - -/// @par -/// -/// Agents in the pool may not be in use. Check #dtCrowdAgent.active before using the returned object. -const dtCrowdAgent* dtCrowd::getAgent(const int idx) -{ - return &m_agents[idx]; -} - -void dtCrowd::updateAgentParameters(const int idx, const dtCrowdAgentParams* params) -{ - if (idx < 0 || idx > m_maxAgents) - return; - memcpy(&m_agents[idx].params, params, sizeof(dtCrowdAgentParams)); -} - -/// @par -/// -/// The agent's position will be constrained to the surface of the navigation mesh. -int dtCrowd::addAgent(const float* pos, const dtCrowdAgentParams* params) -{ - // Find empty slot. - int idx = -1; - for (int i = 0; i < m_maxAgents; ++i) - { - if (!m_agents[i].active) - { - idx = i; - break; - } - } - if (idx == -1) - return -1; - - dtCrowdAgent* ag = &m_agents[idx]; - - // Find nearest position on navmesh and place the agent there. - float nearest[3]; - dtPolyRef ref; - m_navquery->findNearestPoly(pos, m_ext, &m_filter, &ref, nearest); - - ag->corridor.reset(ref, nearest); - ag->boundary.reset(); - - updateAgentParameters(idx, params); - - ag->topologyOptTime = 0; - ag->nneis = 0; - - dtVset(ag->dvel, 0,0,0); - dtVset(ag->nvel, 0,0,0); - dtVset(ag->vel, 0,0,0); - dtVcopy(ag->npos, nearest); - - ag->desiredSpeed = 0; - ag->t = 0; - ag->var = (rand() % 10) / 9.0f; - - if (ref) - ag->state = DT_CROWDAGENT_STATE_WALKING; - else - ag->state = DT_CROWDAGENT_STATE_INVALID; - - ag->active = 1; - - return idx; -} - -/// @par -/// -/// The agent is deactivated and will no longer be processed. Its #dtCrowdAgent object -/// is not removed from the pool. It is marked as inactive so that it is available for reuse. -void dtCrowd::removeAgent(const int idx) -{ - if (idx >= 0 && idx < m_maxAgents) - { - m_agents[idx].active = 0; - } -} - -const dtCrowd::MoveRequest* dtCrowd::getActiveMoveTarget(const int idx) const -{ - if (idx < 0 || idx > m_maxAgents) - return 0; - - MoveRequest* req = 0; - // Check if there is existing request and update that instead. - for (int i = 0; i < m_moveRequestCount; ++i) - { - if (m_moveRequests[i].idx == idx) - { - req = &m_moveRequests[i]; - break; - } - } - - return req; -} - -bool dtCrowd::requestMoveTargetReplan(const int idx, dtPolyRef ref, const float* pos) -{ - if (idx < 0 || idx > m_maxAgents) - return false; - if (!ref) - return false; - - MoveRequest* req = 0; - // Check if there is existing request and update that instead. - for (int i = 0; i < m_moveRequestCount; ++i) - { - if (m_moveRequests[i].idx == idx) - { - req = &m_moveRequests[i]; - break; - } - } - if (!req) - { - if (m_moveRequestCount >= m_maxAgents) - return false; - req = &m_moveRequests[m_moveRequestCount++]; - memset(req, 0, sizeof(MoveRequest)); - } - - // Initialize request. - req->idx = idx; - req->ref = ref; - dtVcopy(req->pos, pos); - req->pathqRef = DT_PATHQ_INVALID; - req->state = MR_TARGET_REQUESTING; - req->replan = true; - - req->temp[0] = ref; - req->ntemp = 1; - - return true; -} - -/// @par -/// -/// This method is used when a new target is set. Use #adjustMoveTarget() when -/// only small local adjustments are needed. (Such as happens when following a -/// moving target.) -/// -/// The position will be constrained to the surface of the navigation mesh. -/// -/// The request will be processed during the next #update(). -bool dtCrowd::requestMoveTarget(const int idx, dtPolyRef ref, const float* pos) -{ - if (idx < 0 || idx > m_maxAgents) - return false; - if (!ref) - return false; - - MoveRequest* req = 0; - // Check if there is existing request and update that instead. - for (int i = 0; i < m_moveRequestCount; ++i) - { - if (m_moveRequests[i].idx == idx) - { - req = &m_moveRequests[i]; - break; - } - } - if (!req) - { - if (m_moveRequestCount >= m_maxAgents) - return false; - req = &m_moveRequests[m_moveRequestCount++]; - memset(req, 0, sizeof(MoveRequest)); - } - - // Initialize request. - req->idx = idx; - req->ref = ref; - dtVcopy(req->pos, pos); - req->pathqRef = DT_PATHQ_INVALID; - req->state = MR_TARGET_REQUESTING; - req->replan = false; - - req->temp[0] = ref; - req->ntemp = 1; - - return true; -} - -/// @par -/// -/// This method is used when to make small local adjustments to the current -/// target. (Such as happens when following a moving target.) Use -/// #requestMoveTarget() when a new target is needed. -/// -/// The position will be constrained to the surface of the navigation mesh. -/// -/// The request will be processed during the next #update(). -bool dtCrowd::adjustMoveTarget(const int idx, dtPolyRef ref, const float* pos) -{ - if (idx < 0 || idx > m_maxAgents) - return false; - if (!ref) - return false; - - MoveRequest* req = 0; - // Check if there is existing request and update that instead. - for (int i = 0; i < m_moveRequestCount; ++i) - { - if (m_moveRequests[i].idx == idx) - { - req = &m_moveRequests[i]; - break; - } - } - if (!req) - { - if (m_moveRequestCount >= m_maxAgents) - return false; - req = &m_moveRequests[m_moveRequestCount++]; - memset(req, 0, sizeof(MoveRequest)); - - // New adjust request - req->state = MR_TARGET_ADJUST; - req->idx = idx; - } - - // Set adjustment request. - req->aref = ref; - dtVcopy(req->apos, pos); - - return true; -} - -int dtCrowd::getActiveAgents(dtCrowdAgent** agents, const int maxAgents) -{ - int n = 0; - for (int i = 0; i < m_maxAgents; ++i) - { - if (!m_agents[i].active) continue; - if (n < maxAgents) - agents[n++] = &m_agents[i]; - } - return n; -} - - -void dtCrowd::updateMoveRequest(const float /*dt*/) -{ - // Fire off new requests. - for (int i = 0; i < m_moveRequestCount; ++i) - { - MoveRequest* req = &m_moveRequests[i]; - dtCrowdAgent* ag = &m_agents[req->idx]; - - // Agent not active anymore, kill request. - if (!ag->active) - req->state = MR_TARGET_FAILED; - - // Adjust target - if (req->aref) - { - if (req->state == MR_TARGET_ADJUST) - { - // Adjust existing path. - ag->corridor.moveTargetPosition(req->apos, m_navquery, &m_filter); - req->state = MR_TARGET_VALID; - } - else - { - // Adjust on the flight request. - float result[3]; - static const int MAX_VISITED = 16; - dtPolyRef visited[MAX_VISITED]; - int nvisited = 0; - m_navquery->moveAlongSurface(req->temp[req->ntemp-1], req->pos, req->apos, &m_filter, - result, visited, &nvisited, MAX_VISITED); - req->ntemp = dtMergeCorridorEndMoved(req->temp, req->ntemp, MAX_TEMP_PATH, visited, nvisited); - dtVcopy(req->pos, result); - - // Reset adjustment. - dtVset(req->apos, 0,0,0); - req->aref = 0; - } - } - - - if (req->state == MR_TARGET_REQUESTING) - { - // If agent location is invalid, try to recover. - if (ag->state == DT_CROWDAGENT_STATE_INVALID) - { - float agentPos[3]; - dtVcopy(agentPos, ag->npos); - dtPolyRef agentRef = ag->corridor.getFirstPoly(); - if (!m_navquery->isValidPolyRef(agentRef, &m_filter)) - { - // Current location is not valid, try to reposition. - // TODO: this can snap agents, how to handle that? - float nearest[3]; - agentRef = 0; - m_navquery->findNearestPoly(ag->npos, m_ext, &m_filter, &agentRef, nearest); - dtVcopy(agentPos, nearest); - } - if (!agentRef) - { - // Current location still outside navmesh, fail the request. - req->state = MR_TARGET_FAILED; - continue; - } - - // Could relocation agent on navmesh again. - ag->state = DT_CROWDAGENT_STATE_WALKING; - ag->corridor.reset(agentRef, agentPos); - } - - // Calculate request position. - - if (req->replan) - { - // Replan from the end of the current path. - dtPolyRef reqRef = ag->corridor.getLastPoly(); - float reqPos[3]; - dtVcopy(reqPos, ag->corridor.getTarget()); - req->pathqRef = m_pathq.request(reqRef, req->ref, reqPos, req->pos, &m_filter); - if (req->pathqRef != DT_PATHQ_INVALID) - { - req->state = MR_TARGET_WAITING_FOR_PATH; - } - } - else - { - // If there is a lot of latency between requests, it is possible to - // project the current position ahead and use raycast to find the actual - // location and path. - const dtPolyRef* path = ag->corridor.getPath(); - const int npath = ag->corridor.getPathCount(); - dtAssert(npath); - // Here we take the simple approach and set the path to be just the current location. - float reqPos[3]; - dtVcopy(reqPos, ag->corridor.getPos()); // The location of the request - dtPolyRef reqPath[8]; // The path to the request location - reqPath[0] = path[0]; - int reqPathCount = 1; - - req->pathqRef = m_pathq.request(reqPath[reqPathCount-1], req->ref, reqPos, req->pos, &m_filter); - if (req->pathqRef != DT_PATHQ_INVALID) - { - ag->corridor.setCorridor(reqPos, reqPath, reqPathCount); - req->state = MR_TARGET_WAITING_FOR_PATH; - } - } - } - } - - - // Update requests. - m_pathq.update(MAX_ITERS_PER_UPDATE); - - dtStatus status; - - // Process path results. - for (int i = 0; i < m_moveRequestCount; ++i) - { - MoveRequest* req = &m_moveRequests[i]; - dtCrowdAgent* ag = &m_agents[req->idx]; - - if (req->state == MR_TARGET_WAITING_FOR_PATH) - { - // Poll path queue. - status = m_pathq.getRequestStatus(req->pathqRef); - if (dtStatusFailed(status)) - { - req->pathqRef = DT_PATHQ_INVALID; - req->state = MR_TARGET_FAILED; - } - else if (dtStatusSucceed(status)) - { - const dtPolyRef* path = ag->corridor.getPath(); - const int npath = ag->corridor.getPathCount(); - dtAssert(npath); - - // Apply results. - float targetPos[3]; - dtVcopy(targetPos, req->pos); - - dtPolyRef* res = m_pathResult; - bool valid = true; - int nres = 0; - status = m_pathq.getPathResult(req->pathqRef, res, &nres, m_maxPathResult); - if (dtStatusFailed(status) || !nres) - valid = false; - - // Merge with any target adjustment that happened during the search. - if (req->ntemp > 1) - { - nres = dtMergeCorridorEndMoved(res, nres, m_maxPathResult, req->temp, req->ntemp); - } - - // Merge result and existing path. - // The agent might have moved whilst the request is - // being processed, so the path may have changed. - // We assume that the end of the path is at the same location - // where the request was issued. - - // The last ref in the old path should be the same as - // the location where the request was issued.. - if (valid && path[npath-1] != res[0]) - valid = false; - - if (valid) - { - // Put the old path infront of the old path. - if (npath > 1) - { - // Make space for the old path. - if ((npath-1)+nres > m_maxPathResult) - nres = m_maxPathResult - (npath-1); - - memmove(res+npath-1, res, sizeof(dtPolyRef)*nres); - // Copy old path in the beginning. - memcpy(res, path, sizeof(dtPolyRef)*(npath-1)); - nres += npath-1; - - // Remove trackbacks - for (int j = 0; j < nres; ++j) - { - if (j-1 >= 0 && j+1 < nres) - { - if (res[j-1] == res[j+1]) - { - memmove(res+(j-1), res+(j+1), sizeof(dtPolyRef)*(nres-(j+1))); - nres -= 2; - j -= 2; - } - } - } - - } - - // Check for partial path. - if (res[nres-1] != req->ref) - { - // Partial path, constrain target position inside the last polygon. - float nearest[3]; - if (m_navquery->closestPointOnPoly(res[nres-1], targetPos, nearest) == DT_SUCCESS) - dtVcopy(targetPos, nearest); - else - valid = false; - } - } - - if (valid) - { - // Set current corridor. - ag->corridor.setCorridor(targetPos, res, nres); - // Force to update boundary. - ag->boundary.reset(); - req->state = MR_TARGET_VALID; - } - else - { - // Something went wrong. - req->state = MR_TARGET_FAILED; - } - } - } - - // Remove request when done with it. - if (req->state == MR_TARGET_VALID || req->state == MR_TARGET_FAILED) - { - m_moveRequestCount--; - if (i != m_moveRequestCount) - memcpy(&m_moveRequests[i], &m_moveRequests[m_moveRequestCount], sizeof(MoveRequest)); - --i; - } - } - -} - - - -static int addToOptQueue(dtCrowdAgent* newag, dtCrowdAgent** agents, const int nagents, const int maxAgents) -{ - // Insert neighbour based on greatest time. - int slot = 0; - if (!nagents) - { - slot = nagents; - } - else if (newag->topologyOptTime <= agents[nagents-1]->topologyOptTime) - { - if (nagents >= maxAgents) - return nagents; - slot = nagents; - } - else - { - int i; - for (i = 0; i < nagents; ++i) - if (newag->topologyOptTime >= agents[i]->topologyOptTime) - break; - - const int tgt = i+1; - const int n = dtMin(nagents-i, maxAgents-tgt); - - dtAssert(tgt+n <= maxAgents); - - if (n > 0) - memmove(&agents[tgt], &agents[i], sizeof(dtCrowdAgent*)*n); - slot = i; - } - - agents[slot] = newag; - - return dtMin(nagents+1, maxAgents); -} - -void dtCrowd::updateTopologyOptimization(dtCrowdAgent** agents, const int nagents, const float dt) -{ - if (!nagents) - return; - - const float OPT_TIME_THR = 0.5f; // seconds - const int OPT_MAX_AGENTS = 1; - dtCrowdAgent* queue[OPT_MAX_AGENTS]; - int nqueue = 0; - - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - if ((ag->params.updateFlags & DT_CROWD_OPTIMIZE_TOPO) == 0) - continue; - ag->topologyOptTime += dt; - if (ag->topologyOptTime >= OPT_TIME_THR) - nqueue = addToOptQueue(ag, queue, nqueue, OPT_MAX_AGENTS); - } - - for (int i = 0; i < nqueue; ++i) - { - dtCrowdAgent* ag = queue[i]; - ag->corridor.optimizePathTopology(m_navquery, &m_filter); - ag->topologyOptTime = 0; - } - -} - -void dtCrowd::checkPathValidty(dtCrowdAgent** agents, const int nagents, const float dt) -{ - static const int CHECK_LOOKAHEAD = 10; - - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - // Skip if the corridor is valid - if (ag->corridor.isValid(CHECK_LOOKAHEAD, m_navquery, &m_filter)) - continue; - - // The current path is bad, try to recover. - - // Store current state. - float agentPos[3]; - dtPolyRef agentRef = 0; - dtVcopy(agentPos, ag->npos); - agentRef = ag->corridor.getFirstPoly(); - - float targetPos[3]; - dtPolyRef targetRef = 0; - dtVcopy(targetPos, ag->corridor.getTarget()); - targetRef = ag->corridor.getLastPoly(); - // If has active move target, get target location from that instead. - const int idx = getAgentIndex(ag); - const MoveRequest* req = getActiveMoveTarget(idx); - if (req) - { - if (req->state == MR_TARGET_REQUESTING || - req->state == MR_TARGET_WAITING_FOR_PATH || - req->state == MR_TARGET_VALID) - { - targetRef = req->ref; - dtVcopy(targetPos, req->pos); - } - else if (req->state == MR_TARGET_ADJUST) - { - targetRef = req->aref; - dtVcopy(targetPos, req->apos); - } - } - - // First check that the current location is valid. - if (!m_navquery->isValidPolyRef(agentRef, &m_filter)) - { - // Current location is not valid, try to reposition. - // TODO: this can snap agents, how to handle that? - float nearest[3]; - agentRef = 0; - m_navquery->findNearestPoly(ag->npos, m_ext, &m_filter, &agentRef, nearest); - dtVcopy(agentPos, nearest); - } - - if (!agentRef) - { - // Count not find location in navmesh, set state to invalid. - ag->corridor.reset(0, agentPos); - ag->boundary.reset(); - ag->state = DT_CROWDAGENT_STATE_INVALID; - continue; - } - - // TODO: make temp path by raycasting towards current velocity. - - ag->corridor.trimInvalidPath(agentRef, agentPos, m_navquery, &m_filter); - ag->boundary.reset(); - dtVcopy(ag->npos, agentPos); - - - // Check that target is still reachable. - if (!m_navquery->isValidPolyRef(targetRef, &m_filter)) - { - // Current target is not valid, try to reposition. - float nearest[3]; - targetRef = 0; - m_navquery->findNearestPoly(targetPos, m_ext, &m_filter, &targetRef, nearest); - dtVcopy(targetPos, nearest); - } - - if (!targetRef) - { - // Target not reachable anymore, cannot replan. - // TODO: indicate failure! - continue; - } - - // Try to replan path to goal. - requestMoveTargetReplan(idx, targetRef, targetPos); - } -} - -void dtCrowd::update(const float dt, dtCrowdAgentDebugInfo* debug) -{ - m_velocitySampleCount = 0; - - const int debugIdx = debug ? debug->idx : -1; - - dtCrowdAgent** agents = m_activeAgents; - int nagents = getActiveAgents(agents, m_maxAgents); - - // Check that all agents still have valid paths. - checkPathValidty(agents, nagents, dt); - - // Update async move request and path finder. - updateMoveRequest(dt); - - // Optimize path topology. - updateTopologyOptimization(agents, nagents, dt); - - // Register agents to proximity grid. - m_grid->clear(); - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - const float* p = ag->npos; - const float r = ag->params.radius; - m_grid->addItem((unsigned short)i, p[0]-r, p[2]-r, p[0]+r, p[2]+r); - } - - // Get nearby navmesh segments and agents to collide with. - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - // Update the collision boundary after certain distance has been passed or - // if it has become invalid. - const float updateThr = ag->params.collisionQueryRange*0.25f; - if (dtVdist2DSqr(ag->npos, ag->boundary.getCenter()) > dtSqr(updateThr) || - !ag->boundary.isValid(m_navquery, &m_filter)) - { - ag->boundary.update(ag->corridor.getFirstPoly(), ag->npos, ag->params.collisionQueryRange, - m_navquery, &m_filter); - } - // Query neighbour agents - ag->nneis = getNeighbours(ag->npos, ag->params.height, ag->params.collisionQueryRange, - ag, ag->neis, DT_CROWDAGENT_MAX_NEIGHBOURS, - agents, nagents, m_grid); - } - - // Find next corner to steer to. - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - // Find corners for steering - ag->ncorners = ag->corridor.findCorners(ag->cornerVerts, ag->cornerFlags, ag->cornerPolys, - DT_CROWDAGENT_MAX_CORNERS, m_navquery, &m_filter); - - // Check to see if the corner after the next corner is directly visible, - // and short cut to there. - if ((ag->params.updateFlags & DT_CROWD_OPTIMIZE_VIS) && ag->ncorners > 0) - { - const float* target = &ag->cornerVerts[dtMin(1,ag->ncorners-1)*3]; - ag->corridor.optimizePathVisibility(target, ag->params.pathOptimizationRange, m_navquery, &m_filter); - - // Copy data for debug purposes. - if (debugIdx == i) - { - dtVcopy(debug->optStart, ag->corridor.getPos()); - dtVcopy(debug->optEnd, target); - } - } - else - { - // Copy data for debug purposes. - if (debugIdx == i) - { - dtVset(debug->optStart, 0,0,0); - dtVset(debug->optEnd, 0,0,0); - } - } - } - - // Trigger off-mesh connections (depends on corners). - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - // Check - const float triggerRadius = ag->params.radius*2.25f; - if (overOffmeshConnection(ag, triggerRadius)) - { - // Prepare to off-mesh connection. - const int idx = ag - m_agents; - dtCrowdAgentAnimation* anim = &m_agentAnims[idx]; - - // Adjust the path over the off-mesh connection. - dtPolyRef refs[2]; - if (ag->corridor.moveOverOffmeshConnection(ag->cornerPolys[ag->ncorners-1], refs, - anim->startPos, anim->endPos, m_navquery)) - { - dtVcopy(anim->initPos, ag->npos); - anim->polyRef = refs[1]; - anim->active = 1; - anim->t = 0.0f; - anim->tmax = (dtVdist2D(anim->startPos, anim->endPos) / ag->params.maxSpeed) * 0.5f; - - ag->state = DT_CROWDAGENT_STATE_OFFMESH; - ag->ncorners = 0; - ag->nneis = 0; - continue; - } - else - { - // TODO: Off-mesh connection failed, replan. - } - - } - } - - // Calculate steering. - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - float dvel[3] = {0,0,0}; - - // Calculate steering direction. - if (ag->params.updateFlags & DT_CROWD_ANTICIPATE_TURNS) - calcSmoothSteerDirection(ag, dvel); - else - calcStraightSteerDirection(ag, dvel); - - // Calculate speed scale, which tells the agent to slowdown at the end of the path. - const float slowDownRadius = ag->params.radius*2; // TODO: make less hacky. - const float speedScale = getDistanceToGoal(ag, slowDownRadius) / slowDownRadius; - - ag->desiredSpeed = ag->params.maxSpeed; - dtVscale(dvel, dvel, ag->desiredSpeed * speedScale); - - // Separation - if (ag->params.updateFlags & DT_CROWD_SEPARATION) - { - const float separationDist = ag->params.collisionQueryRange; - const float invSeparationDist = 1.0f / separationDist; - const float separationWeight = ag->params.separationWeight; - - float w = 0; - float disp[3] = {0,0,0}; - - for (int j = 0; j < ag->nneis; ++j) - { - const dtCrowdAgent* nei = &m_agents[ag->neis[j].idx]; - - float diff[3]; - dtVsub(diff, ag->npos, nei->npos); - diff[1] = 0; - - const float distSqr = dtVlenSqr(diff); - if (distSqr < 0.00001f) - continue; - if (distSqr > dtSqr(separationDist)) - continue; - const float dist = sqrtf(distSqr); - const float weight = separationWeight * (1.0f - dtSqr(dist*invSeparationDist)); - - dtVmad(disp, disp, diff, weight/dist); - w += 1.0f; - } - - if (w > 0.0001f) - { - // Adjust desired velocity. - dtVmad(dvel, dvel, disp, 1.0f/w); - // Clamp desired velocity to desired speed. - const float speedSqr = dtVlenSqr(dvel); - const float desiredSqr = dtSqr(ag->desiredSpeed); - if (speedSqr > desiredSqr) - dtVscale(dvel, dvel, desiredSqr/speedSqr); - } - } - - // Set the desired velocity. - dtVcopy(ag->dvel, dvel); - } - - // Velocity planning. - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - if (ag->params.updateFlags & DT_CROWD_OBSTACLE_AVOIDANCE) - { - m_obstacleQuery->reset(); - - // Add neighbours as obstacles. - for (int j = 0; j < ag->nneis; ++j) - { - const dtCrowdAgent* nei = agents[ag->neis[j].idx]; - m_obstacleQuery->addCircle(nei->npos, nei->params.radius, nei->vel, nei->dvel); - } - - // Append neighbour segments as obstacles. - for (int j = 0; j < ag->boundary.getSegmentCount(); ++j) - { - const float* s = ag->boundary.getSegment(j); - if (dtTriArea2D(ag->npos, s, s+3) < 0.0f) - continue; - m_obstacleQuery->addSegment(s, s+3); - } - - dtObstacleAvoidanceDebugData* vod = 0; - if (debugIdx == i) - vod = debug->vod; - - // Sample new safe velocity. - bool adaptive = true; - int ns = 0; - - const dtObstacleAvoidanceParams* params = &m_obstacleQueryParams[ag->params.obstacleAvoidanceType]; - - if (adaptive) - { - ns = m_obstacleQuery->sampleVelocityAdaptive(ag->npos, ag->params.radius, ag->desiredSpeed, - ag->vel, ag->dvel, ag->nvel, params, vod); - } - else - { - ns = m_obstacleQuery->sampleVelocityGrid(ag->npos, ag->params.radius, ag->desiredSpeed, - ag->vel, ag->dvel, ag->nvel, params, vod); - } - m_velocitySampleCount += ns; - } - else - { - // If not using velocity planning, new velocity is directly the desired velocity. - dtVcopy(ag->nvel, ag->dvel); - } - } - - // Integrate. - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - integrate(ag, dt); - } - - // Handle collisions. - static const float COLLISION_RESOLVE_FACTOR = 0.7f; - - for (int iter = 0; iter < 4; ++iter) - { - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - const int idx0 = getAgentIndex(ag); - - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - dtVset(ag->disp, 0,0,0); - - float w = 0; - - for (int j = 0; j < ag->nneis; ++j) - { - const dtCrowdAgent* nei = agents[ag->neis[j].idx]; - const int idx1 = getAgentIndex(nei); - - float diff[3]; - dtVsub(diff, ag->npos, nei->npos); - diff[1] = 0; - - float dist = dtVlenSqr(diff); - if (dist > dtSqr(ag->params.radius + nei->params.radius)) - continue; - dist = sqrtf(dist); - float pen = (ag->params.radius + nei->params.radius) - dist; - if (dist < 0.0001f) - { - // Agents on top of each other, try to choose diverging separation directions. - if (idx0 > idx1) - dtVset(diff, -ag->dvel[2],0,ag->dvel[0]); - else - dtVset(diff, ag->dvel[2],0,-ag->dvel[0]); - pen = 0.01f; - } - else - { - pen = (1.0f/dist) * (pen*0.5f) * COLLISION_RESOLVE_FACTOR; - } - - dtVmad(ag->disp, ag->disp, diff, pen); - - w += 1.0f; - } - - if (w > 0.0001f) - { - const float iw = 1.0f / w; - dtVscale(ag->disp, ag->disp, iw); - } - } - - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - dtVadd(ag->npos, ag->npos, ag->disp); - } - } - - for (int i = 0; i < nagents; ++i) - { - dtCrowdAgent* ag = agents[i]; - if (ag->state != DT_CROWDAGENT_STATE_WALKING) - continue; - - // Move along navmesh. - ag->corridor.movePosition(ag->npos, m_navquery, &m_filter); - // Get valid constrained position back. - dtVcopy(ag->npos, ag->corridor.getPos()); - } - - // Update agents using off-mesh connection. - for (int i = 0; i < m_maxAgents; ++i) - { - dtCrowdAgentAnimation* anim = &m_agentAnims[i]; - if (!anim->active) - continue; - dtCrowdAgent* ag = agents[i]; - - anim->t += dt; - if (anim->t > anim->tmax) - { - // Reset animation - anim->active = 0; - // Prepare agent for walking. - ag->state = DT_CROWDAGENT_STATE_WALKING; - continue; - } - - // Update position - const float ta = anim->tmax*0.15f; - const float tb = anim->tmax; - if (anim->t < ta) - { - const float u = tween(anim->t, 0.0, ta); - dtVlerp(ag->npos, anim->initPos, anim->startPos, u); - } - else - { - const float u = tween(anim->t, ta, tb); - dtVlerp(ag->npos, anim->startPos, anim->endPos, u); - } - - // Update velocity. - dtVset(ag->vel, 0,0,0); - dtVset(ag->dvel, 0,0,0); - } - -} - - diff --git a/critterai/.svn/pristine/0d/0dd024066f73732a13db3ad6d2a85621f335f80a.svn-base b/critterai/.svn/pristine/0d/0dd024066f73732a13db3ad6d2a85621f335f80a.svn-base deleted file mode 100644 index 5f671df5..00000000 --- a/critterai/.svn/pristine/0d/0dd024066f73732a13db3ad6d2a85621f335f80a.svn-base +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include "DetourAlloc.h" - -static void *dtAllocDefault(int size, dtAllocHint) -{ - return malloc(size); -} - -static void dtFreeDefault(void *ptr) -{ - free(ptr); -} - -static dtAllocFunc* sAllocFunc = dtAllocDefault; -static dtFreeFunc* sFreeFunc = dtFreeDefault; - -void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc) -{ - sAllocFunc = allocFunc ? allocFunc : dtAllocDefault; - sFreeFunc = freeFunc ? freeFunc : dtFreeDefault; -} - -void* dtAlloc(int size, dtAllocHint hint) -{ - return sAllocFunc(size, hint); -} - -void dtFree(void* ptr) -{ - if (ptr) - sFreeFunc(ptr); -} diff --git a/critterai/.svn/pristine/0e/0e16309eba1d4e32b6a767b913e1fe3125978ce7.svn-base b/critterai/.svn/pristine/0e/0e16309eba1d4e32b6a767b913e1fe3125978ce7.svn-base deleted file mode 100644 index 26b9593b..00000000 --- a/critterai/.svn/pristine/0e/0e16309eba1d4e32b6a767b913e1fe3125978ce7.svn-base +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -// Note: The file name does not match the element name because Unity -// doesn't support multiple script files with the same name, and the -// entity name exists in multiple namespaces. - -namespace org.critterai.nav.rcn -{ - internal struct InteropUtil - { - #if UNITY_IPHONE && !UNITY_EDITOR - public const string PLATFORM_DLL = "__Internal"; - #else - public const string PLATFORM_DLL = "cai-nav-rcn"; - #endif - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtvlVectorTest( - [In] ref Vector3 vector3in - , ref Vector3 vector3out); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtvlVectorArrayTest( - [In] Vector3[] vector3in - , int vectorCount - , [In, Out] Vector3[] vector3out); - } -} diff --git a/critterai/.svn/pristine/0e/0e1c9acdd098960fc661d43f65a85a3e536346cb.svn-base b/critterai/.svn/pristine/0e/0e1c9acdd098960fc661d43f65a85a3e536346cb.svn-base deleted file mode 100644 index 7ddb0fe7..00000000 --- a/critterai/.svn/pristine/0e/0e1c9acdd098960fc661d43f65a85a3e536346cb.svn-base +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "DetourNavMeshEx.h" -#include "DetourCommon.h" - -extern "C" -{ - EXPORT_API void dtnmGetParams(const dtNavMesh* pNavMesh - , dtNavMeshParams* params) - { - if (!pNavMesh) - return; - - const dtNavMeshParams* lparams = pNavMesh->getParams(); - - params->maxPolys = lparams->maxPolys; - params->maxTiles = lparams->maxTiles; - params->tileHeight = lparams->tileHeight; - params->tileWidth = lparams->tileWidth; - - dtVcopy(params->orig, lparams->orig); - } - - EXPORT_API dtStatus dtnmAddTile(dtNavMesh* navMesh - , rcnTileData* tileData - , dtTileRef lastRef - , dtTileRef* resultRef) - { - if (!navMesh - || !tileData - || !tileData->data - || tileData->dataSize < 1 - || tileData->isOwned) - return DT_FAILURE + DT_INVALID_PARAM; - - dtStatus status = navMesh->addTile(tileData->data - , tileData->dataSize - , DT_TILE_FREE_DATA - , lastRef - , resultRef); - - if (dtStatusSucceed(status)) - tileData->isOwned = true; - - return status; - } - - EXPORT_API dtStatus dtnmRemoveTile(dtNavMesh* navMesh - , dtTileRef ref - , unsigned char** data - , int* dataSize) - { - unsigned char* tData = 0; - int tDataSize = 0; - - if (!navMesh) - return DT_FAILURE + DT_INVALID_PARAM; - - dtStatus status = navMesh->removeTile(ref, &tData, &tDataSize); - - if (data) - *data = tData; - if (dataSize) - *dataSize = tDataSize; - - if (dtStatusFailed(status)) - return status; - - if (!data && tData) - { - // Data was returned, but the caller doesn't want it. - // Need to free the memory. - dtFree(tData); - tData = 0; - } - - return status; - } - - EXPORT_API void dtnmCalcTileLoc(const dtNavMesh* navMesh - , const float* pos, int* tx, int* ty) - { - if (navMesh) - navMesh->calcTileLoc(pos, tx, ty); - } - - EXPORT_API const dtMeshTile* dtnmGetTileAt(const dtNavMesh* navmesh - , int x - , int y - , int layer) - { - if (!navmesh) - return 0; - return navmesh->getTileAt(x, y, layer); - } - - EXPORT_API int dtnmGetTilesAt(const dtNavMesh* navmesh - , int x - , int y - , const dtMeshTile** tiles - , const int tilesSize) - { - if (navmesh) - return navmesh->getTilesAt(x, y, tiles, tilesSize); - return 0; - } - - EXPORT_API dtTileRef dtnmGetTileRefAt(const dtNavMesh* navMesh - , int x - , int y - , int layer) - { - if (navMesh) - return navMesh->getTileRefAt(x, y, layer); - return 0; - } - - EXPORT_API dtTileRef dtnmGetTileRef(const dtNavMesh* navmesh - , const dtMeshTile* tile) - { - if (navmesh) - return navmesh->getTileRef(tile); - return 0; - } - - EXPORT_API const dtMeshTile* dtnmGetTileByRef(const dtNavMesh* navmesh - , dtTileRef ref) - { - if (navmesh) - return navmesh->getTileByRef(ref); - return 0; - } - - EXPORT_API int dtnmGetMaxTiles(const dtNavMesh* pNavMesh) - { - if (!pNavMesh) - return -1; - - return pNavMesh->getMaxTiles(); - } - - EXPORT_API const dtMeshTile* dtnmGetTile(const dtNavMesh* navmesh - , int index) - { - if (navmesh) - return navmesh->getTile(index); - return 0; - } - - EXPORT_API dtStatus dtnmGetTileAndPolyByRef(const dtNavMesh* navmesh - , const dtPolyRef ref - , const dtMeshTile** tile - , const dtPoly** poly) - { - if (navmesh) - return navmesh->getTileAndPolyByRef(ref, tile, poly); - return (DT_FAILURE + DT_INVALID_PARAM); - } - - EXPORT_API bool dtnmIsValidPolyRef(const dtNavMesh* pNavMesh - , const dtPolyRef polyRef) - { - if (!pNavMesh) - return false; - - return pNavMesh->isValidPolyRef(polyRef); - } - - EXPORT_API dtStatus dtnmGetConnectionEndPoints( - const dtNavMesh* pNavMesh - , const dtPolyRef prevRef - , const dtPolyRef polyRef - , float* startPos - , float* endPos) - { - if (!pNavMesh) - return (DT_FAILURE | DT_INVALID_PARAM); - - return pNavMesh->getOffMeshConnectionPolyEndPoints( - prevRef - , polyRef - , startPos - , endPos); - } - - EXPORT_API const dtOffMeshConnection* dtnmGetOffMeshConnectionByRef( - const dtNavMesh* navmesh - , dtPolyRef ref) - { - if (navmesh) - return navmesh->getOffMeshConnectionByRef(ref); - return 0; - } - - EXPORT_API dtStatus dtnmGetPolyFlags(const dtNavMesh* pNavMesh - , const dtPolyRef polyRef - , unsigned short* flags) - { - if (!pNavMesh || !polyRef) - return (DT_FAILURE | DT_INVALID_PARAM); - - return pNavMesh->getPolyFlags(polyRef, flags); - } - - EXPORT_API dtStatus dtnmSetPolyFlags(dtNavMesh* pNavMesh - , const dtPolyRef polyRef - , unsigned short flags) - { - if (!pNavMesh || !polyRef) - return (DT_FAILURE | DT_INVALID_PARAM); - - return pNavMesh->setPolyFlags(polyRef, flags); - } - - EXPORT_API dtStatus dtnmGetPolyArea(const dtNavMesh* pNavMesh - , const dtPolyRef polyRef - , unsigned char* area) - { - if (!pNavMesh || !polyRef) - return (DT_FAILURE | DT_INVALID_PARAM); - - return pNavMesh->getPolyArea(polyRef, area); - } - - EXPORT_API dtStatus dtnmSetPolyArea(dtNavMesh* pNavMesh - , const dtPolyRef polyRef - , unsigned char area) - { - if (!pNavMesh || !polyRef) - return (DT_FAILURE | DT_INVALID_PARAM); - - return pNavMesh->setPolyArea(polyRef, area); - } - - EXPORT_API int dtnmGetTileStateSize(const dtNavMesh* navmesh - , const dtMeshTile* tile) - { - if (navmesh) - return navmesh->getTileStateSize(tile); - return 0; - } - - EXPORT_API dtStatus dtnmStoreTileState(const dtNavMesh* navmesh - , const dtMeshTile* tile - , unsigned char* data - , const int maxDataSize) - { - if (navmesh) - return navmesh->storeTileState(tile, data, maxDataSize); - return (DT_FAILURE + DT_INVALID_PARAM); - } - - EXPORT_API dtStatus dtnmRestoreTileState(dtNavMesh* navmesh - , dtMeshTile* tile - , const unsigned char* data - , const int maxDataSize) - { - if (navmesh) - return navmesh->restoreTileState(tile, data, maxDataSize); - return (DT_FAILURE + DT_INVALID_PARAM); - } - - EXPORT_API const dtMeshHeader* dtnmGetTileHeader(const dtMeshTile* tile) - { - return tile->header; - } - - EXPORT_API dtPolyRef dtnmGetPolyRefBase(const dtNavMesh* navmesh - , const dtMeshTile* tile) - { - if (navmesh) - return navmesh->getPolyRefBase(tile); - return 0; - } - - EXPORT_API int dtnmGetTileVerts(const dtMeshTile* tile - , float* verts - , const int vertsCount) - { - if (!tile - || !verts - || !tile->header - || !tile->dataSize - || vertsCount < tile->header->vertCount) - { - return 0; - } - - int count = tile->header->vertCount; - - if (count > 0) - memcpy(verts, tile->verts, sizeof(float) * count * 3); - - return count; - } - - EXPORT_API int dtnmGetTilePolys(const dtMeshTile* tile - , dtPoly* polys - , const int polysSize) - { - if (!tile - || !polys - || !tile->header - || !tile->dataSize - || polysSize < tile->header->polyCount) - { - return 0; - } - - int count = tile->header->polyCount; - - if (count > 0) - memcpy(polys, tile->polys, sizeof(dtPoly) * count); - - return count; - } - - EXPORT_API int dtnmGetTileDetailVerts(const dtMeshTile* tile - , float* verts - , const int vertsCount) - { - if (!tile - || !verts - || !tile->header - || !tile->dataSize - || vertsCount < tile->header->detailVertCount) - { - return 0; - } - - int count = tile->header->detailVertCount; - - if (count > 0) - memcpy(verts, tile->detailVerts, sizeof(float) * count * 3); - - return count; - } - - EXPORT_API int dtnmGetTileDetailTris(const dtMeshTile* tile - , unsigned char* tris - , const int trisSize) - { - if (!tile - || !tris - || !tile->header - || !tile->dataSize - || trisSize < tile->header->detailTriCount * 4) - { - return 0; - } - - int count = tile->header->detailTriCount; - - if (count > 0) - memcpy(tris, tile->detailTris, sizeof(unsigned char) * count * 4); - - return count; - } - - EXPORT_API int dtnmGetTileDetailMeshes(const dtMeshTile* tile - , dtPolyDetail* detailMeshes - , const int meshesSize) - { - if (!tile - || !detailMeshes - || !tile->header - || !tile->dataSize - || meshesSize < tile->header->detailMeshCount) - { - return 0; - } - - int count = tile->header->detailMeshCount; - - if (count > 0) - memcpy(detailMeshes, tile->detailMeshes, sizeof(dtPolyDetail) * count); - - return count; - } - - EXPORT_API int dtnmGetTileLinks(const dtMeshTile* tile - , dtLink* links - , const int linksSize) - { - if (!tile - || !links - || !tile->header - || !tile->dataSize - || linksSize < tile->header->maxLinkCount) - { - return 0; - } - - int count = tile->header->maxLinkCount; - - if (count > 0) - memcpy(links, tile->links, sizeof(dtLink) * count); - - return count; - } - - EXPORT_API int dtnmGetTileBVTree(const dtMeshTile* tile - , dtBVNode* nodes - , const int nodesSize) - { - if (!tile - || !nodes - || !tile->header - || !tile->dataSize - || nodesSize < tile->header->bvNodeCount) - { - return 0; - } - - int count = tile->header->bvNodeCount; - - if (count > 0) - memcpy(nodes, tile->bvTree, sizeof(dtBVNode) * count); - - return count; - } - - EXPORT_API int dtnmGetTileConnections(const dtMeshTile* tile - , dtOffMeshConnection* conns - , const int connsSize) - { - if (!tile - || !conns - || !tile->header - || !tile->dataSize - || connsSize < tile->header->offMeshConCount) - { - return 0; - } - - int count = tile->header->offMeshConCount; - - if (count > 0) - { - memcpy(conns - , tile->offMeshCons - , sizeof(dtOffMeshConnection) * count); - } - - return count; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/0e/0e8600b4ddb734eb59651971febd6e53e4fac4d1.svn-base b/critterai/.svn/pristine/0e/0e8600b4ddb734eb59651971febd6e53e4fac4d1.svn-base deleted file mode 100644 index 159e6d19..00000000 --- a/critterai/.svn/pristine/0e/0e8600b4ddb734eb59651971febd6e53e4fac4d1.svn-base +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav; -using UnityEditor; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class MultiTileBuildControl - : BuilderControl - { - private const float MarginSize = ControlUtil.MarginSize; - private const int GridCellSize = 32; - - private Vector3[] mCellVerts = new Vector3[4]; - - private static GUIStyle mBlackLabel; - - private Vector2 mScrollPos = Vector2.zero; - - private int mMouseX = TileSelection.NoSelection; - private int mMouseZ = TileSelection.NoSelection; - - public override bool Enter(ControlContext context, DebugViewContext debug) - { - if (base.Enter(context, debug)) - { - NavmeshBuild build = context.Build; - - if (build.TileSetDefinition == null) - { - Debug.LogError(typeof(MultiTileBuildControl) - + ": Build data has not been initialized, or not a tiled build."); - return false; - } - - return true; - } - return false; - } - - protected override void OnGUIMain() - { - if (mBlackLabel == null) - { - // Need to initialize shared style. - mBlackLabel = new GUIStyle(GUI.skin.label); - mBlackLabel.normal.textColor = Color.black; - mBlackLabel.fontStyle = FontStyle.Bold; - } - - TileSelection selection = Context.Selection; - - selection.Validate(); - - TileBuildData tdata = Context.Build.BuildData; - - if (tdata == null) - return; - - Rect mainArea = Context.MainArea; - - // The box and shift makes it look better. - GUI.Box(mainArea, ""); - mainArea.x += MarginSize; - mainArea.y += MarginSize; - - // Draw the status grid. - - // Note: View is expanded by one grid size in order to minimize - // grid/slider overlap. - Rect view - = new Rect(0, 0, tdata.Width * GridCellSize + GridCellSize - , tdata.Depth * GridCellSize + GridCellSize); - - mScrollPos = GUI.BeginScrollView(mainArea, mScrollPos, view); - - OnGUIStatusGrid(view.height - GridCellSize); - - GUI.EndScrollView(); - - OnGUIMainStandard(); - - if (IsBaseBusy) - return; - - // Handle the mouse, including click selection. - - Event evt = Event.current; - Vector2 mousePos = evt.mousePosition; - - if (mainArea.Contains(mousePos)) - { - Vector2 gridPos = mousePos; - - gridPos.x -= mainArea.xMin - mScrollPos.x; - gridPos.y -= mainArea.yMin - mScrollPos.y; - - int x = Mathf.FloorToInt(gridPos.x / GridCellSize); - // For the depth, we need to invert the y-axis. - int z = tdata.Depth - Mathf.FloorToInt(gridPos.y / GridCellSize) - 1; - - if (x < tdata.Width && z >= 0 && z < tdata.Depth) - { - GUI.Label(new Rect(mousePos.x - 20, mousePos.y - 20, 120, 25) - , "(" + x + "," + z + "): " + tdata.GetState(x, z) - , mBlackLabel); - - mMouseX = x; - mMouseZ = z; - - if (evt.type == EventType.MouseDown && evt.button == 0) - { - if (selection.SelectedX == mMouseX && selection.SelectedZ == mMouseZ) - // Clicked on same tile. Deselect. - selection.ClearSelection(); - else - selection.SetSelection(mMouseX, mMouseZ); - } - } - else - { - mMouseX = TileSelection.NoSelection; - mMouseZ = TileSelection.NoSelection; - } - } - else - { - mMouseX = TileSelection.NoSelection; - mMouseZ = TileSelection.NoSelection; - } - } - - private void OnGUIStatusGrid(float areaHeight) - { - TileBuildData tdata = Context.Build.BuildData; - - for (int tx = 0; tx < tdata.Width; tx++) - { - for (int tz = 0; tz < tdata.Depth; tz++) - { - Vector3 origin = new Vector3(tx * GridCellSize, areaHeight - tz * GridCellSize); - - mCellVerts[0] = origin; - - mCellVerts[1] = origin; - mCellVerts[1].x += GridCellSize; - - mCellVerts[2] = origin; - mCellVerts[2].x += GridCellSize; - mCellVerts[2].y -= GridCellSize; - - mCellVerts[3] = origin; - mCellVerts[3].y -= GridCellSize; - - Color c = ToColor(tdata.GetState(tx, tz)); - - Handles.DrawSolidRectangleWithOutline(mCellVerts, c, Color.black); - } - } - - OnGUISelection(areaHeight); - } - - private void OnGUISelection(float areaHeight) - { - Vector3 origin; - int xSize = GridCellSize; - int ySize = GridCellSize; - - TileSelection selection = Context.Selection; - - if (selection.Validate()) - { - // Draw the tile marker. - origin = new Vector3(selection.SelectedX * GridCellSize - , areaHeight - selection.SelectedZ * GridCellSize); - - mCellVerts[0] = origin; - - mCellVerts[1] = origin; - mCellVerts[1].x += GridCellSize; - - mCellVerts[2] = origin; - mCellVerts[2].x += GridCellSize; - mCellVerts[2].y -= GridCellSize; - - mCellVerts[3] = origin; - mCellVerts[3].y -= GridCellSize; - - Handles.DrawSolidRectangleWithOutline(mCellVerts - , Color.clear - , new Color(0.93f, 0.58f, 0.11f)); // Orange. - - TileZone zone = selection.Zone; - - origin = - new Vector3(zone.xmin * GridCellSize, areaHeight - zone.zmin * GridCellSize); - - xSize = zone.Width * GridCellSize; - ySize = zone.Depth * GridCellSize; - } - else - { - origin = new Vector3(0, areaHeight); - - TileBuildData tdata = Context.Build.BuildData; - - xSize = tdata.Width * GridCellSize; - ySize = tdata.Depth * GridCellSize; - } - - mCellVerts[0] = origin; - - mCellVerts[1] = origin; - mCellVerts[1].x += xSize; - - mCellVerts[2] = origin; - mCellVerts[2].x += xSize; - mCellVerts[2].y -= ySize; - - mCellVerts[3] = origin; - mCellVerts[3].y -= ySize; - - Handles.DrawSolidRectangleWithOutline(mCellVerts - , Color.clear - , ControlUtil.SelectionColor); - } - - protected override void OnGUIButtons() - { - DebugContext.SetViews(ViewOption.Grid | ViewOption.Selection | ViewOption.Mesh); - - NavmeshBuild build = Context.Build; - - if (!build) - return; - - TileBuildData tdata = build.BuildData; - - if (tdata == null) - return; - - TileSelection selection = Context.Selection; - - bool hasSelection = selection.Validate(); - bool needBaking = (tdata.NeedsBakingCount() > 0); - int activeCount = Context.TaskCount; - int bakeableCount = tdata.BakeableCount(); - - bool origGUIEnabled = GUI.enabled; - - bool guiEnabled = !IsBaseBusy; - - GUI.enabled = guiEnabled; - - ControlUtil.BeginButtonArea(Context.ButtonArea); - - if (GUILayout.Button("Build All")) - HandleBuildRequest(true); - - GUI.enabled = guiEnabled && hasSelection; - - if (GUILayout.Button("Build Zone")) - HandleBuildRequest(false); - - //////////////////////////////////////////////////////////////////// - GUILayout.Space(MarginSize); - - // Only disable baking if there is nothing at all that can be baked. - GUI.enabled = guiEnabled && activeCount == 0 && (bakeableCount > 0); - - GUIStyle style = (bakeableCount > 0 && activeCount == 0) - ? ControlUtil.HighlightedButton : GUI.skin.button; - - if (GUILayout.Button("Bake All", style)) - HandleBake(); - - //////////////////////////////////////////////////////////////////// - GUILayout.Space(MarginSize); - - // Note: Technically only the last condition is needed. But checking the - // other conditions first saves processing time. - GUI.enabled = guiEnabled && activeCount == 0 - && tdata.GetStateCount(TileBuildState.NotBuilt) < tdata.Width * tdata.Depth; - - if (GUILayout.Button((needBaking ? "Revert Unbaked" : "Clear All"))) - HandleClear(); - - GUI.enabled = guiEnabled && (activeCount != 0); - - if (GUILayout.Button("Abort Builds")) - Context.AbortAllReqests("User requested."); - - //////////////////////////////////////////////////////////////////// - GUILayout.Space(ControlUtil.MarginSize); - - GUI.enabled = guiEnabled; - if (OnGUIStandardButtons()) - { - // Special case. Build was discarded. - ControlUtil.EndButtonArea(); - return; - } - - /////////////////////////////////////////////////////////////////// - GUILayout.Space(MarginSize); - - GUI.enabled = guiEnabled && hasSelection; - - EditorGUIUtility.LookLikeControls(100); - selection.ZoneSize = EditorGUILayout.IntField("Zone Size", selection.ZoneSize); - EditorGUIUtility.LookLikeControls(); - - GUI.enabled = guiEnabled; - - //////////////////////////////////////////////////////////////////// - GUILayout.Space(MarginSize); - - GUILayout.Label("Bakeable Tiles: " + bakeableCount); - - ControlUtil.OnGUIStandardButtons(Context, DebugContext, true); - - ControlUtil.EndButtonArea(); - - GUI.enabled = origGUIEnabled; - } - - private void HandleBake() - { - const string Category = "Bake To Target"; - - NavmeshBuild build = Context.Build; // Caller checks for null. - TileBuildData tdata = build.BuildData; - - // Double check. - if (tdata.BakeableCount() == 0) - { - Debug.LogWarning(Category + ": No tiles were produced. (All tiles empty?)", build); - return; - } - - if (Context.TaskCount > 0) - { - Debug.LogWarning(Category + ": There are in-progress background builds." - + " The tiles associated with these builds will not be baked." - + " In-progress builds: " + Context.TaskCount - , build); - } - - NavmeshParams nconfig; - NavmeshTileData[] tiles; - - bool success = tdata.GetMeshBuildData(build.TileSetDefinition.BoundsMin - , build.TileSetDefinition.TileWorldSize - , out nconfig, out tiles); - - if (!success) - { - Logger.PostError("Bake to target: Error creating navigation mesh from build data." - , Context.Build); - return; - } - - NavStatus status = - build.BuildTarget.Load(nconfig, tiles, NMBEditorUtil.GetConfig(build)); - - if ((status & NavStatus.Failure) == 0) - { - build.BuildData.SetAsBaked(); - EditorUtility.SetDirty((Object)build.BuildTarget); - } - else - Logger.PostError("Bake to target: Target reported failure." - , (Object)Context.Build.BuildTarget); - } - - private void HandleClear() - { - // Abort any in-progress builds. - Context.AbortAllReqests("User requested."); - - TileBuildData tdata = Context.Build.BuildData; - - int w = tdata.Width; - int d = tdata.Depth; - - bool needsBaking = - (tdata.NeedsBakingCount() == 0) ? false : true; - - for (int tx = 0; tx < w; tx++) - { - for (int tz = 0; tz < d; tz++) - { - if (needsBaking) - tdata.ClearUnbaked(tx, tz); - else - tdata.Reset(tx, tz); - } - } - } - - private void HandleBuildRequest(bool forceAll) - { - TileSelection sel = Context.Selection; - - int w; - int d; - int ix = 0; - int iz = 0; - - int priority; - - if (!forceAll && sel.Validate()) - { - TileZone zone = sel.Zone; - - w = zone.xmax + 1; - d = zone.zmax + 1; - - ix = zone.xmin; - iz = zone.zmin; - - priority = BuildTaskProcessor.MediumPriority; - } - else - { - TileBuildData tdata = Context.Build.BuildData; - - w = tdata.Width; - d = tdata.Depth; - - priority = BuildTaskProcessor.LowPriority; - } - - // Note: The iteration order appears odd, but it makes for better - // progress visualizations. Filling downward. - for (int tz = d - 1; tz >= iz; tz--) - { - for (int tx = ix; tx < w; tx++) - { - if (!Context.QueueTask(tx, tz, priority--, Logger)) - { - Logger.PostError(string.Format("Build task failed: ({0},{1})", tx, tz) - , Context.Build); - } - } - } - } - - private static Color ToColor(TileBuildState state) - { - switch (state) - { - case TileBuildState.Baked: - - return new Color(0.07f, 0.43f, 0.09f); // Green - - case TileBuildState.Built: - - return new Color(0.08f, 0.34f, 0.63f); // Dark blue - - case TileBuildState.Empty: - - return new Color(0.3f, 0.3f, 0.3f); // Dark grey - - case TileBuildState.Error: - - return new Color(0.63f, 0.03f, 0); // Red - - case TileBuildState.InProgress: - - return new Color(0.12f, 0.5f, 0.92f); // Medium blue - - case TileBuildState.NotBuilt: - - return new Color(0.6f, 0.6f, 0.6f); // Light grey - - case TileBuildState.Queued: - - return new Color(0.4f, 0.65f, 0.93f); // Light blue - } - - return Color.white; // Should never get here. - } - - - } -} diff --git a/critterai/.svn/pristine/0f/0f158cf953b33fdc76f349a2e5f201e8410ee30a.svn-base b/critterai/.svn/pristine/0f/0f158cf953b33fdc76f349a2e5f201e8410ee30a.svn-base deleted file mode 100644 index de1b70b8..00000000 --- a/critterai/.svn/pristine/0f/0f158cf953b33fdc76f349a2e5f201e8410ee30a.svn-base +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -namespace org.critterai -{ - /// - /// Represents a generic prioritized item. - /// - public interface IPriorityItem - { - /// - /// The priority of the item. - /// - /// - /// - /// This value is immutable after object construction. - /// - /// - int Priority { get; } - } -} diff --git a/critterai/.svn/pristine/0f/0f79b77949a29266e2f4b1896284297cac0e2782.svn-base b/critterai/.svn/pristine/0f/0f79b77949a29266e2f4b1896284297cac0e2782.svn-base deleted file mode 100644 index 33c33559..00000000 --- a/critterai/.svn/pristine/0f/0f79b77949a29266e2f4b1896284297cac0e2782.svn-base +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using org.critterai.geom; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.u3d; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(TerrainCompiler))] -public sealed class TerrainCompilerEditor - : Editor -{ - private const float CheckDelay = 5; - - private static bool mDebugEnabled; - private static int mDebugZoneSize = 10; - private static float mDebugOffset = 0; - - private Terrain mDebugTerrain = null; - private Vector3 mDebugPosition; - - private double mLastCheck = 0; - private TerrainData mLastSource = null; - - void OnEnable() - { - SceneView.onSceneGUIDelegate += this.OnSceneGUI; - } - - void OnDisable() - { - SceneView.onSceneGUIDelegate -= this.OnSceneGUI; - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - TerrainCompiler targ = (TerrainCompiler)target; - - EditorGUILayout.Separator(); - - GUILayout.Label("Priority: " + targ.Priority); - - EditorGUILayout.Separator(); - - targ.terrainData = (TerrainData)EditorGUILayout.ObjectField("Terrain Data" - , targ.terrainData - , typeof(TerrainData) - , false); - - targ.includeTrees = EditorGUILayout.Toggle("Include Trees", targ.includeTrees); - - float res = EditorGUILayout.Slider("Resolution (%)", targ.Resolution * 100, 0.01f, 100); - - targ.Resolution = (float)System.Math.Round(Mathf.Max(0.001f, res * 0.01f), 3); - - EditorGUILayout.Separator(); - - OnGUIDebug(targ); - - GUI.enabled = true; - - EditorGUILayout.Separator(); - - GUILayout.Box("Input Build Processor\n\nLoads and compiles a " - + typeof(Terrain).Name + " component if it references the specified " - + typeof(TerrainData).Name + " object." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - private void OnGUIDebug(TerrainCompiler targ) - { - // Getting the terrain requires a full terrain search. So only check - // for it occationally. - if (mDebugEnabled) - { - double time = EditorApplication.timeSinceStartup; - if (targ.terrainData != mLastSource || mLastCheck + CheckDelay > time) - { - Terrain terrain = targ.GetTerrain(); - mLastSource = targ.terrainData; - mLastCheck = time; - if (mDebugTerrain != terrain) - { - mDebugTerrain = terrain; - SceneView.RepaintAll(); - } - } - } - else - { - mDebugTerrain = null; - mLastCheck = 0; - mLastSource = null; - } - - EditorGUILayout.Separator(); - - GUI.enabled = targ.terrainData; - - bool origChanged = GUI.changed; - - mDebugEnabled = EditorGUILayout.Toggle("Enable Preview", mDebugEnabled); - - if (!mDebugEnabled || !targ.terrainData) - return; - - GUILayout.Label("Size"); - mDebugZoneSize = (int)GUILayout.HorizontalSlider(mDebugZoneSize, 10, 50); - - GUILayout.Label("Offset"); - mDebugOffset = GUILayout.HorizontalSlider(mDebugOffset, 0, 10); - - EditorGUILayout.Separator(); - - string helpText; - if (mDebugTerrain == null) - helpText = "There is no enabled terrain in the scene using the source terrain data."; - else - { - int xc; - int zc; - Vector3 scale = TerrainUtil.DeriveScale(mDebugTerrain, targ.Resolution, out xc, out zc); - int triCount = (xc - 1) * (zc - 1) * 2; - - helpText = string.Format("Mouse-over the terrain in the scene to see a " - + " triangulation preview. Trees are not included in the preview.\n\n" - + "Total surface triangles: {0:N0}\n" - + "Sample distance: {1:F1} x {2:F1}" - , triCount, scale.x, scale.z); - } - - GUILayout.Box(helpText, EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - - if (GUI.changed) - SceneView.RepaintAll(); - - GUI.changed = origChanged; - - } - - void OnSceneGUI(SceneView view) - { - TerrainCompiler targ = (TerrainCompiler)target; - - if (!mDebugEnabled || mDebugTerrain == null) - // Nothing to do. - return; - - Vector3 mousePos = Event.current.mousePosition; - Camera cam = Camera.current; - - Ray ray = cam.ScreenPointToRay(new Vector3(mousePos.x, -mousePos.y + cam.pixelHeight)); - - Vector3 point = Vector3.zero; - - RaycastHit hit; - if (Physics.Raycast(ray, out hit, 1000.0f)) - { - Terrain terrain = hit.collider.gameObject.GetComponent(); - if (terrain == mDebugTerrain) - point = hit.point; - } - - if (mDebugPosition != point) - { - mDebugPosition = point; - SceneView.RepaintAll(); - } - - if (mDebugPosition == Vector3.zero) - return; - - Color c = Color.yellow; - c.a = 0.25f; - - int trash; - Vector3 scale = TerrainUtil.DeriveScale(mDebugTerrain, targ.Resolution, out trash, out trash); - - float xmin = mDebugPosition.x - scale.x * mDebugZoneSize; - float zmin = mDebugPosition.z - scale.z * mDebugZoneSize; - float xmax = mDebugPosition.x + scale.x * mDebugZoneSize; - float zmax = mDebugPosition.z + scale.z * mDebugZoneSize; - - TriangleMesh mesh = TerrainUtil.TriangulateSurface(mDebugTerrain - , xmin, zmin, xmax, zmax - , targ.Resolution - , mDebugOffset); - - if (mesh != null) - DebugDraw.TriangleMesh(mesh.verts, mesh.tris, mesh.triCount, true, c); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Compiler : Terrain", false, NMBEditorUtil.CompilerGroup)] - static void CreateAsset() - { - TerrainCompiler item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/0f/0fb705ec277da2c7b2f6ee2bb4557b35a69d599f.svn-base b/critterai/.svn/pristine/0f/0fb705ec277da2c7b2f6ee2bb4557b35a69d599f.svn-base deleted file mode 100644 index 6f3d37b4..00000000 --- a/critterai/.svn/pristine/0f/0fb705ec277da2c7b2f6ee2bb4557b35a69d599f.svn-base +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using System.Collections.Generic; -using org.critterai.nmbuild.u3d.editor; - -/// -/// Queries the scene for components based on game object tag. (Editor Only) -/// -/// -/// -/// Components are returned based the tags assigned to game objects. The query can be local -/// to the tagged objects, or can include children. -/// -/// -[System.Serializable] -public sealed class TagSceneQuery - : ScriptableObject, ISceneQuery -{ - /// - /// One or more tags to base the query on. - /// - public List tags = new List(); - - [SerializeField] - private bool mIncludeChildren = true; - - private GameObject[] mObjects; - - /// - /// True if components whose parents have one of the tags should be included in the results. - /// - /// - /// - /// If true, the query behavior will be the same as calling GetComponentsInChildren() on the - /// tagged game object. If false, the query behavior will be the same as GetComponent(). - /// - /// - public bool IncludeChildren - { - get { return mIncludeChildren; } - set { mIncludeChildren = value; } - } - - /// - /// Initializes the object before each use. - /// - /// - /// - /// This method is called by the manager of the object before each use. It allows the - /// object to refresh its internal state. - /// - /// - public void Initialize() - { - if (tags == null || tags.Count == 0) - { - mObjects = new GameObject[0]; - return; - } - - if (tags.Count == 1) - // Shortcut. - mObjects = GameObject.FindGameObjectsWithTag(tags[0]); - else - { - // Need to aggregate. - List list = new List(); - foreach (string tag in tags) - { - if (tag != null && tag.Length > 0) - { - GameObject[] g = GameObject.FindGameObjectsWithTag(tag); - list.AddRange(g); - } - } - mObjects = list.ToArray(); - } - } - - /// - /// Gets all scene components of the specified type, based the component or parent tags. - /// - /// - /// - /// All queries are against the currently open scene. - /// - /// - /// The type of component to retrieve. - /// All components of the specified type. - public T[] GetComponents() where T : Component - { - List result = new List(); - foreach (GameObject go in mObjects) - { - if (go == null || !go.active) - continue; - - if (mIncludeChildren) - { - T[] cs = go.GetComponentsInChildren(false); - result.AddRange(cs); - } - else - { - T cs = go.GetComponent(); - - if (cs != null) - result.Add(cs); - } - } - return result.ToArray(); - } -} diff --git a/critterai/.svn/pristine/10/1065ea83c75311af580d662bd0f203766515407b.svn-base b/critterai/.svn/pristine/10/1065ea83c75311af580d662bd0f203766515407b.svn-base deleted file mode 100644 index 8e146098..00000000 --- a/critterai/.svn/pristine/10/1065ea83c75311af580d662bd0f203766515407b.svn-base +++ /dev/null @@ -1,39 +0,0 @@ - - - - AABB - http://en.wikipedia.org/wiki/Bounding_volume - - - Discussion Group - http://groups.google.com/group/critterai - - - Mikko Mononen - http://digestingduck.blogspot.com/ - - - Project Home - http://www.critterai.org/ - - - CAINav Source - http://code.google.com/p/critterai/source/browse/ - - - Recast Navigation - http://code.google.com/p/recastnavigation/ - - - Unity - http://unity3d.com/ - - - Unity Pro - http://unity3d.com/ - - - Issues List - http://code.google.com/p/critterai/issues/list - - \ No newline at end of file diff --git a/critterai/.svn/pristine/10/10993eb1e617d3def659247fe5d799f2c289828a.svn-base b/critterai/.svn/pristine/10/10993eb1e617d3def659247fe5d799f2c289828a.svn-base deleted file mode 100644 index 03de4108..00000000 --- a/critterai/.svn/pristine/10/10993eb1e617d3def659247fe5d799f2c289828a.svn-base +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - internal enum MeshDebugOption - { - None = 0, - InputGeometry, - PolyMesh, - Detailmesh, - WorkingMesh, - } -} diff --git a/critterai/.svn/pristine/10/10c86d9c263490b27c7361cbe603df994a4fc11c.svn-base b/critterai/.svn/pristine/10/10c86d9c263490b27c7361cbe603df994a4fc11c.svn-base deleted file mode 100644 index bd1963a0..00000000 --- a/critterai/.svn/pristine/10/10c86d9c263490b27c7361cbe603df994a4fc11c.svn-base +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// The state of a asset. (Editor Only) - /// - public enum NavmeshBuildState - { - /// - /// The build is missing core references needed to perform the build. - /// - /// - /// - /// In general, no build operations can be performed until the issues are resolved. - /// - /// - Invalid, - - /// - /// Build data is available, but there is no input data. - /// - /// - /// - /// The build data may have been left in place purposefully or accidentally. - /// (E.g. An editor reset, user forgot to exit the build, etc.) - /// - /// - /// The next expected action is to either reset the build or set the input data. - /// - /// - NeedsRecovery, - - /// - /// The build has not been started. (Has no input data and no build data.) - /// - /// - /// - /// The next step is to set the input data. - /// - /// - Inactive, - - /// - /// The build has input data, but no build data. - /// - /// - /// - /// The next step is to set the configuration and prepare the build. - /// - /// - InputCompiled, - - /// - /// Build operations are supported. - /// - /// - /// - /// The input and build data are available for use in builds. - /// - /// - Buildable, - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/10/10cde236325662e20132c343155f7e825e0624a7.svn-base b/critterai/.svn/pristine/10/10cde236325662e20132c343155f7e825e0624a7.svn-base deleted file mode 100644 index 0c861f62..00000000 --- a/critterai/.svn/pristine/10/10cde236325662e20132c343155f7e825e0624a7.svn-base +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen.rcn -{ - [StructLayout(LayoutKind.Sequential)] - internal sealed class ContourSetEx - { - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcsBuildSet(IntPtr context - , [In] CompactHeightfield chf - , float maxError - , int maxEdgeLen - , [In, Out] ContourSetEx cset - , ContourBuildFlags flags); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmcsFreeSetData([In, Out] ContourSetEx cset); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcsGetContour([In] ContourSetEx cset - , int index - , [In, Out] Contour result); - - public IntPtr contours = IntPtr.Zero; // rcContour[contourCount] - public int contourCount = 0; - - public Vector3 boundsMin; - public Vector3 boundsMax; - - public float xzCellSize = 0; - public float yCellSize = 0; - public int width = 0; - public int depth = 0; - public int borderSize = 0; - - public void Reset() - { - contourCount = 0; - contours = IntPtr.Zero; - boundsMax = Vector3Util.Zero; - boundsMin = Vector3Util.Zero; - xzCellSize = 0; - yCellSize = 0; - width = 0; - depth = 0; - borderSize = 0; - } - } -} diff --git a/critterai/.svn/pristine/11/110f0b424ee33718967f05e0fe69e5b42b252170.svn-base b/critterai/.svn/pristine/11/110f0b424ee33718967f05e0fe69e5b42b252170.svn-base deleted file mode 100644 index f986b948..00000000 --- a/critterai/.svn/pristine/11/110f0b424ee33718967f05e0fe69e5b42b252170.svn-base +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.junit.Assert.*; -import static org.critterai.math.MathUtil.*; - -import org.critterai.math.MathUtil; -import org.junit.Test; - -/** - * Unit tests for the {@link MathUtil} class. - */ -public class MathUtilTests { - - @Test - public void testSloppyEquals() - { - float tol = 0.1f; - assertTrue(sloppyEquals(5, 5.09f, tol)); - assertTrue(sloppyEquals(5, 4.91f, tol)); - assertTrue(sloppyEquals(5, 5.10f, tol)); - assertTrue(sloppyEquals(5, 4.90f, tol)); - assertFalse(sloppyEquals(5, 5.101f, tol)); - assertFalse(sloppyEquals(5, 4.899f, tol)); - } - - @Test - public void testClampToPositiveNonZero() - { - assertTrue(clampToPositiveNonZero(0.1f) == 0.1f); - assertTrue(clampToPositiveNonZero(Float.MIN_VALUE) == Float.MIN_VALUE); - assertTrue(clampToPositiveNonZero(0) == Float.MIN_VALUE); - assertTrue(clampToPositiveNonZero(-Float.MIN_VALUE) == Float.MIN_VALUE); - } - - @Test - public void testClampFloat() - { - assertTrue(clamp(5.0f, 4.99f, 5.01f) == 5.0f); - assertTrue(clamp(4.99f, 4.99f, 5.01f) == 4.99f); - assertTrue(clamp(4.9899f, 4.99f, 5.01f) == 4.99f); - assertTrue(clamp(5.01f, 4.99f, 5.01f) == 5.01f); - assertTrue(clamp(5.01001f, 4.99f, 5.01f) == 5.01f); - } - - @Test - public void testClampInt() - { - assertTrue(clamp(5, 4, 6) == 5); - assertTrue(clamp(4, 4, 6) == 4); - assertTrue(clamp(3, 4, 6) == 4); - assertTrue(clamp(6, 4, 6) == 6); - assertTrue(clamp(7, 4, 6) == 6); - } - - @Test - public void testClampShort() - { - assertTrue(clamp((short)5, (short)4, (short)6) == 5); - assertTrue(clamp((short)4, (short)4, (short)6) == 4); - assertTrue(clamp((short)3, (short)4, (short)6) == 4); - assertTrue(clamp((short)6, (short)4, (short)6) == 6); - assertTrue(clamp((short)7, (short)4, (short)6) == 6); - } - - @Test - public void testMax() - { - assertTrue(max(2) == 2); - assertTrue(max(-1, 0, 1, 2) == 2); - assertTrue(max(-1, 2, -1, 0) == 2); - } - - @Test - public void testMin() - { - assertTrue(min(2) == 2); - assertTrue(min(-1, 0, 1, 2) == -1); - assertTrue(min(2, 2, -1, 0) == -1); - } - -} diff --git a/critterai/.svn/pristine/13/1303f17d0bd6711888b6f8b51ceaeb3ce4b61dcf.svn-base b/critterai/.svn/pristine/13/1303f17d0bd6711888b6f8b51ceaeb3ce4b61dcf.svn-base deleted file mode 100644 index 35b23fa0..00000000 --- a/critterai/.svn/pristine/13/1303f17d0bd6711888b6f8b51ceaeb3ce4b61dcf.svn-base +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Applies an algorithm to contours which results in null-region edges - * following the original detail source geometry edge more closely. - * @see Visualizations - */ -public final class MatchNullRegionEdges - implements IContourAlgorithm -{ - - /* - * Recast Reference: simplifyContour() in RecastContour.cpp - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * The maximum distance the edge of the contour may deviate from the source - * geometry. - */ - private final float mThreshold; - - /** - * Constructor. - * @param threshold The maximum distance the edge of the contour may - * deviate from the source geometry. - *

Setting this lower will result in the navmesh edges following the - * geometry contour more accurately at the expense of an increased - * vertex count.

- *

Setting the value to zero is not recommended since it can result - * in a large increase in the number of vertices at a high processing - * cost.

- *

Constraints: >= 0

- */ - public MatchNullRegionEdges(float threshold) - { - this.mThreshold = Math.max(threshold, 0); - } - - /** - * {@inheritDoc} - *

Adds vertices from the source list to the result list such that - * if any null region vertices are compared against the result list, - * none of the vertices will be further from the null region edges than - * the allowed threshold.

- *

Only null-region edges are operated on. All other edges are - * ignored.

- *

The result vertices is expected to be seeded with at least two - * source vertices.

- */ - @Override - public void apply(ArrayList sourceVerts - , ArrayList inoutResultVerts) - { - if (sourceVerts == null || inoutResultVerts == null) - return; - - final int sourceVertCount = sourceVerts.size() / 4; - int simplifiedVertCount = inoutResultVerts.size() / 4; // Will change. - int iResultVertA = 0; - - /* - * Loop through all edges in this contour. - * - * NOTE: The simplifiedVertCount in the loop condition - * increases over iterations. That is what keeps the loop going beyond - * the initial vertex count. - */ - while (iResultVertA < simplifiedVertCount) - { - int iResultVertB = (iResultVertA + 1) % simplifiedVertCount; - - // The line segment's beginning vertex. - final int ax = inoutResultVerts.get(iResultVertA*4); - final int az = inoutResultVerts.get(iResultVertA*4+2); - final int iVertASource = inoutResultVerts.get(iResultVertA*4+3); - - // The line segment's ending vertex. - final int bx = inoutResultVerts.get(iResultVertB*4); - final int bz = inoutResultVerts.get(iResultVertB*4+2); - final int iVertBSource = inoutResultVerts.get(iResultVertB*4+3); - - // The source index of the next vertex to test. (The vertex just - // after the current vertex in the source vertex list.) - int iTestVert = (iVertASource + 1) % sourceVertCount; - float maxDeviation = 0; - - // Default to no index. No new vert to add. - int iVertToInsert = -1; - - if (sourceVerts.get(iTestVert*4+3) == NULL_REGION) - { - /* - * This test vertex is part of a null region edge. - * Loop through the source vertices until the end vertex - * is found, searching for the vertex that is farthest from - * the line segment formed by the begin/end vertices. - * - * Visualizations: - * http://www.critterai.org/nmgen_contourgen#nulledgesimple - */ - while (iTestVert != iVertBSource) - { - final float deviation = Geometry.getPointSegmentDistanceSq( - sourceVerts.get(iTestVert * 4) - , sourceVerts.get(iTestVert * 4 + 2) - , ax - , az - , bx - , bz); - if (deviation > maxDeviation) - { - // A new maximum deviation was detected. - maxDeviation = deviation; - iVertToInsert = iTestVert; - } - // Move to the next vertex. - iTestVert = (iTestVert+1) % sourceVertCount; - } - } - - if (iVertToInsert != -1 && maxDeviation > (mThreshold * mThreshold)) - { - // A vertex was found that is further than allowed from the - // current edge. Add this vertex to the contour. - inoutResultVerts.add((iResultVertA+1)*4 - , sourceVerts.get(iVertToInsert*4)); - inoutResultVerts.add((iResultVertA+1)*4+1 - , sourceVerts.get(iVertToInsert*4+1)); - inoutResultVerts.add((iResultVertA+1)*4+2 - , sourceVerts.get(iVertToInsert*4+2)); - inoutResultVerts.add((iResultVertA+1)*4+3 - , iVertToInsert); - // Update the vertex count since a new vertex was added. - simplifiedVertCount = inoutResultVerts.size() / 4; - // Not incrementing the vertex since we need to test the edge - // formed by vertA and this this new vertex on the next - // iteration of the loop. - } - else - // This edge segment does not need to be altered. Move to - // the next vertex. - iResultVertA++; - } - } -} diff --git a/critterai/.svn/pristine/13/134553d9f4595d174bc4c4db170362d94f0af70a.svn-base b/critterai/.svn/pristine/13/134553d9f4595d174bc4c4db170362d94f0af70a.svn-base deleted file mode 100644 index 4b48505d..00000000 Binary files a/critterai/.svn/pristine/13/134553d9f4595d174bc4c4db170362d94f0af70a.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/13/13e78c1155771492a9d6b14b9840de3e1c5c24a3.svn-base b/critterai/.svn/pristine/13/13e78c1155771492a9d6b14b9840de3e1c5c24a3.svn-base deleted file mode 100644 index d23da721..00000000 Binary files a/critterai/.svn/pristine/13/13e78c1155771492a9d6b14b9840de3e1c5c24a3.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/14/14c532afd84f286e86104190d00aff134cb832d2.svn-base b/critterai/.svn/pristine/14/14c532afd84f286e86104190d00aff134cb832d2.svn-base deleted file mode 100644 index 14dbfc84..00000000 --- a/critterai/.svn/pristine/14/14c532afd84f286e86104190d00aff134cb832d2.svn-base +++ /dev/null @@ -1,84 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {8093F287-EA45-46AB-AF58-710DA654392E} - Library - Properties - org.critterai - cai-nav-u3d-editor - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - ..\bin\Release\cai-nav-u3d-editor.XML - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEditor.dll - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - Properties\AssemblyInfo.cs - - - - - {319D361B-147F-45AC-854E-50C06FCA3393} - cai-nav-rcn - - - {D2154397-4098-4170-BBB0-58714D84E4C8} - cai-nav-u3d - - - {1FF01BFD-2593-406A-959E-D4D84CEB662C} - cai-util-u3d-editor - - - {AF812AB8-633B-4e23-ABA7-6D02082FB2EE} - cai-util-u3d - - - {42218E47-156D-46ff-84E0-119D47B0E4EB} - cai-nav - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/14/14d1ef16fac065b841ed8cdf84482a5652de7150.svn-base b/critterai/.svn/pristine/14/14d1ef16fac065b841ed8cdf84482a5652de7150.svn-base deleted file mode 100644 index 390936f1..00000000 --- a/critterai/.svn/pristine/14/14d1ef16fac065b841ed8cdf84482a5652de7150.svn-base +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - Areas in CAINav are represented by a byte value between zero and 63. In the navigation mesh they are assigned to polygons - and used to assign traversal cost. For example, all polygons assigned an area of 24 may be assigned a cost of 1.5 while polygons - assigned an area of 63 may be assigned a cost of 1.0. The meaning and cost associated with each area is defined by the end user. The only - exception is 0, which is always considered to mean 'unwalkable'. - - - - Areas are also used in the NMGen build process. But while their purpose and use in the navigation mesh is fairly straight forward, - things can get complicated in the build process. This topic covers various ways of using areas during the build process to get the navigation mesh you want. - - - - - - - Area constants can be found in the T:org.critterai.nmgen.NMGen and - T:org.critterai.nav.Navmesh classes. - - - - - - -
- - Why Use Areas in the Build Process - - - - - If you assign everything to only a single area during the NMGen build process then polygons will form based solely - on the structure of the source geometry. Polygon edges will form along the borders of obstructions, in structural portals such as doorways, etc. - The surface type of the source geometry is unknown and can't be taken into account. So, for example, a single polygon may cover both - meadow and swamp surfaces, even though the cost of traversing the surfaces is different. - - - - Essentially, areas allow you to specify surface type so that the build process can make sure that polygons are formed such that they don't - overlap different area types. Polygon edges will always form at the boundry between different areas. - - - - The obvious benefit of forming polygons based on surface type is that it allows you to properly control traversal cost. But there are other purposes. - One example is flag assignment. Polygons have an associated 16-bit flags field. These flags are used to filter polygons during pathfinding. For example, you - can specify that all polygons with the 0x10 flag are inaccessible, so pathfinding will ignore the polygons. Areas can be used to ensure that polygons - form in a way that allow flags to be used properly. - - - - Let's say you have a bridge that can partially collapse. There is no way for the build process to know exaclty which part of the bridge can collapse, - so you can't guarentee that separate polygons will exist at the proper location. Unless, of course, you mark the collapse location with a different area - than the rest of the bridge. - - - - In the below example, cylinder and convex areas are marked into the mesh. The convex marker was given a higher priority so that it overwrites part - of the cyclinder area. - - - - - - - - As you can see, areas provide a powerful method of ensuring the final mesh structure is what you need it to be. - - - - -
- -
- - The Power of Zero - - - - - The zero area is called the 'NullArea' and has a special meaning to the NMGen build process. Any surface marked as NullArea - is unwalkable and no polygons will form. All NullArea surfaces are considered obstacles. - - - - The build process automatically handles NullArea assignment for most cases. The surface's slope may be too steep. (E.g. Walls) The - polygons formed on the surface may be too small to be of use. (E.g. Stairway railings or a counter top.) The surface may be inaccessible due - to height restrictions. (E.g. The floor under a table.) - - - - But sometimes you may want to manually block off an area. For example, let's say you have a surface covered by burning rubbish. The structure - of the surface may be walkable, but you never want it to be walkable. In cases such as this you can manually mark the surface as a NullArea and - the build process will treat it as an obstacle. - - - - The NullArea is treated differently than other areas in another way. Normal areas can be reassigned at will. You can assign a surface to area - 15 during one part of the build process then reassign part of it to area 22 later on. A NullArea can never be reassigned. Once a NullArea, always - a NullArea. You never have to worry about accidentally making a NullArea walkable again. - - - - -
- -
- - How to Assign Areas - - - - - There are three points in the build process where you can assign areas: - - - - - To the source geometry triangles when compiling the input. - To convex areas in the CompactField object. - To polygons in the PolyMesh object. - - - - - - - Technically, you can't perform a NMGen build without assigning areas. At some point in the build it will detect - that you haven't assigned areas and will assign all surfaces to a default area. - - - - -
- - Source Geometry Area Assignment - - - - - The first point at which you can assign areas is during the input compile. You can assign each source geometry triangle to an area. - This is a great place to assign areas if your source geometry is inherently categorized by surface type. E.g. All bridge and sidewalk - meshes get one area while all water meshes get a different area. - - - - Both the T:org.critterai.nmbuild.InputGeometryCompiler and - InputGeometry classes provide ways to assign areas to triangles. The Unity build process - includes the ability to assign area by tag assignment or mesh. - - - - -
- -
- - Marking the CompactHeightfield - - - - - In some cases it either isn't possible or isn't appropriate to assign areas to the source geometry. The next option is to mark areas - directly into the CompactField during its post-processing step. The - T:org.critterai.nmbuild.AreaBoxMarker, - T:org.critterai.nmbuild.AreaCylinderMarker, and - T:org.critterai.nmbuild.AreaConvexMarker classes can be used to mark arbitrary convex areas - into the heightfield. - - - - This is the most accurate method of marking an area since marking occurs at the resolution of the heightfield. (I.e. The cell size.) - However, if abused it can create a lot of extra polygons. - - - - - - - The above area markers and the build process supports priority assignment, so it is possible to use overlapping markers. The overlapped - area will be assigned the area of the highest priority marker. - - - - - - -
- -
- - Area Assignment in the PolyMesh - - - - - Each polygon in the PolyMesh has an area assignment that is inherited from the earlier in the build process. This is the value - that will be assigned to the polygon once it is added to the navigation mesh. At this point the polygons are pretty much fixed, so it isn't particularly - useful to assign the NullArea. But sometimes it is useful to perform some final area adjustements. For example, if you assigned an area only - to ensure proper polygon formation, and the area isn't needed for adjusting traversal cost in the navigation mesh, you can re-assign the area to - a default area. (I.e. Clean things up.) - - - - -
- -
- -
- - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/15/152159ca40ddf9b51e8ac250e8d72f60b271dd80.svn-base b/critterai/.svn/pristine/15/152159ca40ddf9b51e8ac250e8d72f60b271dd80.svn-base deleted file mode 100644 index e0c25c17..00000000 --- a/critterai/.svn/pristine/15/152159ca40ddf9b51e8ac250e8d72f60b271dd80.svn-base +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.u3d -{ - /// - /// Provides various utility methods related to Unity Color structures. - /// - public static class ColorUtil - { - // Returns 1 if the bit at position b in value a is 1. Otherwise returns 0. - private static int bit(int a, int b) - { - return (a & (1 << b)) >> b; - } - - /// - /// Creates a Unity color from a hex format color. (E.g. 0xFFCCAA) - /// - /// The hex value of the color. - /// The color's alpha. - /// The Unity color associated with the hex color. - public static Color HexToColor(int hex, float alpha) - { - float factor = 1f / 255; - float r = ((hex >> 16) & 0xff) * factor; - float g = ((hex >> 8) & 0xff) * factor; - float b = (hex & 0xff) * factor; - Color c = new Color(r, g, b, alpha); - return c; - } - - /// - /// Creates a Unity color from an integer value. - /// - /// - /// - /// This method is useful for generating a variety of colors that are visually disimilar. - /// - /// - /// An integer value to create the color from. - /// The color's alpha. - /// A Unity color based on the integer value. - public static Color IntToColor(int i, float alpha) - { - // r, g, and b are constrained to between 1 and 4 inclusive. - const float factor = 63f / 255f; // Approximately 0.25. - float r = bit(i, 1) + bit(i, 3) * 2 + 1; - float g = bit(i, 2) + bit(i, 4) * 2 + 1; - float b = bit(i, 0) + bit(i, 5) * 2 + 1; - return new Color(r * factor, g * factor, b * factor, alpha); - } - } -} diff --git a/critterai/.svn/pristine/15/153c3beee5348796b770131d2c5114a41731d6f0.svn-base b/critterai/.svn/pristine/15/153c3beee5348796b770131d2c5114a41731d6f0.svn-base deleted file mode 100644 index 08143295..00000000 --- a/critterai/.svn/pristine/15/153c3beee5348796b770131d2c5114a41731d6f0.svn-base +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - The path corridor provides a way of moving along a navigation path without worrying about the minutiae of managing the path. - - - - Core Class: PathCorridor - - - - In the simplest scenario, a path is a list of waypoints from a starting point to an end point. The waypoints form a connected - set of line segments along which a navigation client moves. But navigation is much more complex in the real world. There are - locomotion limitations, local steering restrictions, dynamic obstacle avoidance, and good old floating point errors. All of these - issues can make management of a path difficult. - - - - Navigation based on a polygon mesh provides a different abstraction than just a list of waypoints. The path returned by the - NavmeshQuery class is a list of polygons. Technically, a client can move freely anywhere within this corridor of polygons. - If a client strays outside the corridor, then the corridor can be patched up using local searches rather than full path replanning. - - - - The path corridor is loaded with a path, a start point, and a target point. It is then used to move the navigation client through - the corridor. It handles path straightening, constraining the client to the navigation mesh, and adjusting the corridor due to - inaccurate client locomotion. - - - - The PathCorridor API is well documented. The only thing worth repeating here is a warning: You can't just initialize a - corridor with a path and forget long distance path planning. Since the path corridor class uses local searches to maintain the corridor, - attempting to apply large delta movement to the corridor's position or target can result in a malformed corridor. Details are in the API - documentation. - - - - - - - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.PathCorridor - T:org.critterai.nav.PathCorridorData - - - - - - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/15/15b6162f090e2e1942978c1150f9bdd94e4ecc0a.svn-base b/critterai/.svn/pristine/15/15b6162f090e2e1942978c1150f9bdd94e4ecc0a.svn-base deleted file mode 100644 index ed26a8c2..00000000 --- a/critterai/.svn/pristine/15/15b6162f090e2e1942978c1150f9bdd94e4ecc0a.svn-base +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Undocumented class meant for internal use only. (Editor Only) - /// - [System.Serializable] - public sealed class BuildDataItem - { - /* Design notes: - * - * Odd design due to the need to support Unity serialization. - * - * Arrays are set to zero length at construction. Zero length represents an invalid - * state. - * - */ - - internal const int EmptyId = -1; - internal const int ErrorId = -2; - internal const int QueuedId = -3; - internal const int InProgressId = -4; - - /// - /// Undocumented. - /// - public int tileX; - - /// - /// Undocumented. - /// - public int tileZ; - - /// - /// Undocumented. - /// - public byte[] polyMesh; - - /// - /// Undocumented. - /// - public byte[] detailMesh; - - /// - /// Undocumented. - /// - public byte[] bakedTile; - - /// - /// Undocumented. - /// - public int bakedPolyCount; - - /// - /// Undocumented. - /// - public byte[] workingTile; - - /// - /// Undocumented. - /// - public int workingPolyCount; - - internal TileBuildState TileState - { - get - { - if (workingPolyCount < 0) - { - // Special informational state. - switch (workingPolyCount) - { - case EmptyId: - return TileBuildState.Empty; - case QueuedId: - return TileBuildState.Queued; - case InProgressId: - return TileBuildState.InProgress; - case ErrorId: - return TileBuildState.Error; - } - } - - if (workingTile.Length == 0) - { - if (bakedTile.Length == 0) - return TileBuildState.NotBuilt; - else - return TileBuildState.Baked; - } - - return TileBuildState.Built; - } - } - - internal BuildDataItem(int tx, int tz) - { - tileX = tx; - tileZ = tz; - Reset(); - } - - internal void SetAsEmpty() - { - ClearUnbaked(); - workingPolyCount = EmptyId; - } - - internal void ClearUnbaked() - { - polyMesh = new byte[0]; - detailMesh = new byte[0]; - - workingTile = new byte[0]; - workingPolyCount = 0; // This clears special states. - } - - internal void SetAsFailed() - { - ClearUnbaked(); - workingPolyCount = ErrorId; - } - - internal void SetAsQueued() - { - ClearUnbaked(); - workingPolyCount = QueuedId; - } - - internal void SetAsInProgress() - { - ClearUnbaked(); - workingPolyCount = InProgressId; - } - - internal void SetWorkingData(PolyMesh polyMesh, PolyMeshDetail detailMesh) - { - if (polyMesh == null - || polyMesh.PolyCount == 0) - { - SetAsEmpty(); - return; - } - - this.polyMesh = polyMesh.GetSerializedData(false); - - if (detailMesh == null) - this.detailMesh = new byte[0]; - else - this.detailMesh = detailMesh.GetSerializedData(false); - } - - internal void SetWorkingData(NavmeshTileData tile, int polyCount) - { - if (tile == null || polyCount <= 0) - { - SetAsEmpty(); - return; - } - - workingTile = tile.GetData(); - workingPolyCount = polyCount; - } - - internal bool SetAsBaked(byte[] tile, int polyCount) - { - if (tile == null || tile.Length == 0 || polyCount <= 0) - { - return false; - } - - ClearUnbaked(); - bakedTile = tile; - bakedPolyCount = polyCount; - - return true; - } - - internal bool SetAsBaked() - { - if (workingTile.Length > 0) - { - bakedTile = workingTile; - bakedPolyCount = workingPolyCount; - ClearUnbaked(); - return true; - } - workingPolyCount = 0; // Clears all special states. - return false; - } - - internal void Reset() - { - polyMesh = new byte[0]; - detailMesh = new byte[0]; - - workingTile = new byte[0]; - workingPolyCount = 0; - - bakedTile = new byte[0]; - bakedPolyCount = 0; - } - } -} diff --git a/critterai/.svn/pristine/16/16e65bb86fe280084861f8edb3f6473fcda36dd3.svn-base b/critterai/.svn/pristine/16/16e65bb86fe280084861f8edb3f6473fcda36dd3.svn-base deleted file mode 100644 index 96457e8d..00000000 --- a/critterai/.svn/pristine/16/16e65bb86fe280084861f8edb3f6473fcda36dd3.svn-base +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nav -{ - - /// - /// configurtation flags. - /// - [System.Flags] - public enum CrowdUpdateFlags : byte - { - /// - /// Modify steering in order to anticipate turns. - /// - AnticipateTurns = 0x01, - - /// - /// Modify steering to avoid obstacles. - /// - ObstacleAvoidance = 0x02, - - /// - /// Modify steering for crowd separation. - /// - CrowdSeparation = 0x04, - - /// - /// Optimize visibility using . - /// - /// - /// - /// Improves pathfinding appearance when using meshes that contain non-border. - /// vertices. (E.g. Tiled meshes and meshes constructed using multiple areas.) - /// - /// - OptimizeVis = 0x08, - - /// - /// Optimize topology using . - /// - /// - /// - /// Improves pathfinding appearance in crowded areas and for complex meshes. - /// - /// - OptimizeTopo = 0x10 - } -} diff --git a/critterai/.svn/pristine/16/16fd3f71931def4595aa772cd73d21a519465f08.svn-base b/critterai/.svn/pristine/16/16fd3f71931def4595aa772cd73d21a519465f08.svn-base deleted file mode 100644 index d1378bf7..00000000 --- a/critterai/.svn/pristine/16/16fd3f71931def4595aa772cd73d21a519465f08.svn-base +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#if NUNITY -using Vector2 = org.critterai.Vector2; -#else -using Vector2 = UnityEngine.Vector2; -#endif - -namespace org.critterai.geom -{ - /// - /// Provides various 2D rectangle utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Rectangle2 - { - /* - * Design note: - * - * This class does not use Vector2's since a common use case is to test - * on the xz-plane using Vector3's. - * - */ - - /// - /// Indicates whether or not a point is contained within an axis-aligned rectangle. - /// - /// - /// - /// The test is inclusive of the edges of the rectangle. - /// - /// - /// The minimum x-axis bounds of the rectangle. - /// The minimum y-axis bounds of the rectangle. - /// The maximum x-axis bounds of the rectangle. - /// The maximum y-axis bounds of the rectangle. - /// x-value of the point (x, y) to test. - /// y-value of the point (x, y) to test. - /// True if the point lies within the rectangle. - public static bool Contains(float minX, float minY, float maxX, float maxY - , float x, float y) - { - return !(x < minX || y < minY || x > maxX || y > maxY); - } - - /// - /// Indicates whether or not an axis-alighed rectangle (B) is fully contained within - /// another axis-aligned rectangle (A). - /// - /// - /// - /// The test is inclusive of the edges of the rectangles. - /// - /// - /// The minimum x-axis bounds of rectangle A. - /// The minimum y-axis bounds of rectangle A. - /// The maximum x-axis bounds of rectangle A. - /// The maximum y-axis bounds of rectangle A. - /// The minimum x-axis bounds of rectangle B. - /// The minimum y-axis bounds of rectangle B. - /// The maximum x-axis bounds of rectangle B. - /// The maximum y-axis bounds of rectangle B. - /// True if rectangle B is fully contained by rectangle A. - /// - public static bool Contains(float minXA, float minYA, float maxXA, float maxYA - , float minXB, float minYB, float maxXB, float maxYB) - { - return (minXB >= minXA && minYB >= minYA && maxXB <= maxXA && maxYB <= maxYA); - } - - /// - /// Indicates whether or not two axis-aligned rectangles intersect. - /// - /// - /// - /// The test is inclusive of the edges of the rectangles. - /// - /// - /// The minimum x-axis bounds of rectangle A. - /// The minimum y-axis bounds of rectangle A. - /// The maximum x-axis bounds of rectangle A. - /// The maximum y-axis bounds of rectangle A. - /// The minimum x-axis bounds of rectangle B. - /// The minimum y-axis bounds of rectangle B. - /// The maximum x-axis bounds of rectangle B. - /// The maximum y-axis bounds of rectangle B. - /// True if the two rectangles intersect in any manner. - public static bool IntersectsAABB(float minAX, float minAY, float maxAX, float maxAY - , float minBX, float minBY, float maxBX, float maxBY) - { - return !(maxBX < minAX || maxAX < minBX || maxBY < minAY || maxAY < minBY); - } - } -} diff --git a/critterai/.svn/pristine/17/171644a670c870786665929b710007e7bc5fcc2d.svn-base b/critterai/.svn/pristine/17/171644a670c870786665929b710007e7bc5fcc2d.svn-base deleted file mode 100644 index 7426dcd2..00000000 --- a/critterai/.svn/pristine/17/171644a670c870786665929b710007e7bc5fcc2d.svn-base +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - The input compile step involves gathering together all the resources needed to build the - navigation mesh. This may be as simple as compiling the source geometry into the correct - format, or it may be very complex, such as gathering off-mesh connections, mapping triangle type - to area, gathering custom processors, etc. - - - - The results of this step are the InputGeometry, ProcessorSet, - and ConnectionSet objects. (Though finalization of the connection set can be delayed to a later step.) - - - - There is no standard implementation for compiling the input since the process is specific to the - design environment. In Unity the input is gathered from various project assets and scene objects, - such as mesh filters. In other environments it might be gathered directly from Maya or 3DSMax data. - - - - -
- - Input Geometry - - - - - The InputGeometry object consists of standard triangle mesh data (vertices and indices) with additional triangle area assignment. It is - derived from the source geometry. - - - - The T:org.critterai.nmbuild.InputGeometryCompiler and - T:org.critterai.nmbuild.InputGeometryBuilder classes are used - to create the input geometry object. - - - - Each triangle in the input geometry is assigned an area based on surface type. Usually, triangles are assigned a default area, - such as F:org.critterai.nmgen.NMGen.MaxArea, then special triangles - are assigned special areas as needed. For example, 'meadow' and 'sidewalk' triangles may be the default area, while - 'water' and 'swamp' triangles are assigned to other areas. Assigning areas during the build process ensures that - polygons are properly formed for each type of surface. - - - - - // Example: Creating a simple input geometry object. - - // Where 'mesh' is a TriangleMesh object containing all of the input triangles. - - // Create an area buffer that assigns the default area id to all triangles. - byte[] areas = NMGen.CreateDefaultAreaBuffer(mesh.triCount); - - // Create the builder. - // All triangles with a slope over 45.5f will be re-assigned to NMGen.NullArea. - InputGeometryBuilder gbuilder = InputGeometryBuilder.Create(mesh, areas, 45.5f); - - // Build in a single step. - gbuilder.BuildAll(); - - // Get the result. - InputGeometry geom = gbuilder.Result; - - - - - The T:org.critterai.nmbuild.InputGeometryCompiler class can be used to - combine multiple triangle meshes into a single triangle mesh, including area assignment. - - - - -
- -
- - ProcessorSet - - - - - The ProcessorSet contains INMGenProcessor objects used to add special behavior to the - main build step. A processor may do something simple, such as applying default flags - to all polygons (T:org.critterai.nmbuild.ApplyPolygonFlags), or something - complex such as evaluating heightfield intermediates in order to auto-generate off-mesh connections. - - - - - // Example: Creating a processor set. - - // There is a standard set of processors needed for almost every build. - myProccessorList.Add(ProcessorSet.GetStandard(ProcessorSet.StandardOptions)); - - // You can also add other processors, including custom processors of your own. - myProccessorList.Add(myCustomProcessor); - myProcessorList.Add(myOtherCustomProcessor); - - // Create the set. - ProcessorSet processors = ProcessorSet.Create(myProcessorList.ToArray()); - - - - How these processors are used is described further in topic. - - - -
- -
- - ConnectionSet - - - - - The ConnectionSet defines the off-mesh connections that will be added to the navigation mesh. In some cases - they are fully defined during the input build process. In other cases they are generated by custom processor's - later in the build process. - - - - The T:org.critterai.nmbuild.ConnectionSetCompiler can be used to dynamically compile - connections for eventual inclusion in the connection set. - - - - -
- - - - T:org.critterai.nmbuild.InputGeometry - T:org.critterai.nmbuild.ProcessorSet - T:org.critterai.nmbuild.ConnectionSet - T:org.critterai.nmbuild.IncrementalBuilder - - - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/18/1862ab65796a69183890d9ab8efbf93a0475be93.svn-base b/critterai/.svn/pristine/18/1862ab65796a69183890d9ab8efbf93a0475be93.svn-base deleted file mode 100644 index e81b68b4..00000000 --- a/critterai/.svn/pristine/18/1862ab65796a69183890d9ab8efbf93a0475be93.svn-base +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - The Unity NMGen build process is pretty much the same as the standard build process describe by - . The main difference is in the input - compile process. - - - - The input compile process is manged by an input builder that is modified by the scene query and input processors assigned to the - T:NavmeshBuild asset. - - - - -
- - The Input Compile Process - - - - - The input compile process is managed by the input builder. The the only thing the builder does is manage - the input processors. At each step it makes sure all the necessary build assets are ready for use and calls the - processors in ascending priority. A processor can be active during one step or multiple steps. For example, - the T:MeshCompiler loads MeshFilter components from the scene during the - load step, then triangulates them during the compile step. - - - - - - -
- - Load Components - - - - - The scene query asset is used to determine which components in the scene will be included in the input compile. Any ScritableObject that - implements the T:org.critterai.nmbuild.u3d.editor.ISceneQuery interface can be used. For example, - if you want the build to gather scene components based on tags, then you'll use the T:TagSceneQuery asset. - If no scene query is provided, then the the query will be global. (E.g. All MeshFitlers in the scene, all Terrains in the scene, etc.) - - - - During the load component step, each input processor uses the scene query to load the components that it cares about. For example, - the T:MeshCompiler will load all MeshFilters and the T:TerrainCompiler will - load the Terrain component. - - - - -
- -
- - Filter Components - - - - - During the filter component step the input processors have a chance to remove components from the input compile. The component loaders are generally dumb. - They load everything the scene query let's them load. In this step, other processors can refine the result. For example, a - T:MeshInputFilter can be used to remove MeshFilter's that reference all 'door' meshes. Or the - T:StaticFilter can be used to remove all components not marked as static. - - - - -
- -
- - Apply Area Modifiers - - - - - At this point all components that will be compiled have been gathered. During this step input processors can assign custom areas to each - component. The assignments will be used during the compile step. For example, the T:MeshAreaDef - can assign the area 21 to all MeshFilters that reference swamp and marsh meshes. During the compile step the - T:MeshCompiler will then assign 21 to all triangles generated from the meshes. - - - - - - - F:org.critterai.nmgen.NMGen.MaxArea will be assigned by default. You can use the - T:DefaultAreaDef asset to assign a different area as the default. - - - - - - -
- -
- - Compile Input - - - - - During the compile input step the input processors will compile everything needed to create the objects required by the rest of the NMGen build process. - (I.e. The InputGeometry, ProcessorSet, and ConnectionSet objects.) MeshFilter and Terrain components will - be triangulated, and off-mesh connections and NMGen processors created. - - - - -
- -
- - Post-Process - - - - - At this point all data needed to create the final input objects has been compiled. During the post-process step the input processors are - given the oportunity to make final adjustmwents to the data before it is locked down in the immutable InputGeometry, ProcessorSet, - and ConnectionSet objects. - - - - -
- -
- -
- - - - - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/18/187c198847ad97ce4ac297d8e5f996c04a4dd5d1.svn-base b/critterai/.svn/pristine/18/187c198847ad97ce4ac297d8e5f996c04a4dd5d1.svn-base deleted file mode 100644 index 61022405..00000000 --- a/critterai/.svn/pristine/18/187c198847ad97ce4ac297d8e5f996c04a4dd5d1.svn-base +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - [System.Flags] - internal enum ViewOption : byte - { - Input = 0x01, - Grid = 0x02, - Mesh = 0x04, - Selection = 0x08, - } -} diff --git a/critterai/.svn/pristine/19/1906b98f7dbc9366c9570178d075d336ca4d8c2d.svn-base b/critterai/.svn/pristine/19/1906b98f7dbc9366c9570178d075d336ca4d8c2d.svn-base deleted file mode 100644 index 47d1cf8c..00000000 --- a/critterai/.svn/pristine/19/1906b98f7dbc9366c9570178d075d336ca4d8c2d.svn-base +++ /dev/null @@ -1,17 +0,0 @@ -version=snapshot -project.name=cai-util -project.fullname=${project.name}-${version} - -lib.dir=../../lib/java -misc.resources.dir=../../misc - -src.dir=src -local.misc.dir=misc -test.src.dir=test -dist.scm.dir=${lib.dir} - -build.dir=build -classes.dir=${build.dir}/classes -test.classes.dir=${build.dir}/test -dist.dir=${build.dir}/dist -doc.dir=${build.dir}/docs \ No newline at end of file diff --git a/critterai/.svn/pristine/1a/1a85922d0250c54a1d8f388ec704d312c82f5740.svn-base b/critterai/.svn/pristine/1a/1a85922d0250c54a1d8f388ec704d312c82f5740.svn-base deleted file mode 100644 index 7f59cb29..00000000 --- a/critterai/.svn/pristine/1a/1a85922d0250c54a1d8f388ec704d312c82f5740.svn-base +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nmgen -{ - /// - /// A node in a object. - /// - /// - /// - /// The bounds of the node represents the AABB of the triangles contained by the node. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct ChunkyTriMeshNode - { - /// - /// The minimum x-bounds. - /// - public float xmin; - - /// - /// The minimum z-bounds. - /// - public float zmin; - - /// - /// The maximum x-bounds. - /// - public float xmax; - - /// - /// The maximum z-bounds. - /// - public float zmax; - - /// - /// The start index of the triangles in the node. - /// - public int i; - - /// - /// The number of triangles in the node. - /// - public int count; - - internal bool Overlaps(float xmin, float zmin, float xmax, float zmax) - { - bool result = true; - result = (xmin > this.xmax || xmax < this.xmin) ? false : result; - result = (zmin > this.zmax || zmax < this.zmin) ? false : result; - return result; - } - } -} diff --git a/critterai/.svn/pristine/1a/1ade38785cce3e326e396d052f825c5fa385ac15.svn-base b/critterai/.svn/pristine/1a/1ade38785cce3e326e396d052f825c5fa385ac15.svn-base deleted file mode 100644 index 6d5edf52..00000000 --- a/critterai/.svn/pristine/1a/1ade38785cce3e326e396d052f825c5fa385ac15.svn-base +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#if NUNITY -using Vector2 = org.critterai.Vector2; -#else -using Vector2 = UnityEngine.Vector2; -#endif - -namespace org.critterai.geom -{ - /// - /// Provides various 2D triangle utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Triangle2 - { - /// - /// Returns true if the point is contained by the triangle. - /// - /// - /// - /// The test is inclusive of the triangle edges. - /// - /// - /// The point to test. - /// Vertex A of triangle ABC. - /// Vertex B of triangle ABC - /// Vertex C of triangle ABC - /// True if the point is contained by the triangle ABC. - public static bool Contains(Vector2 p, Vector2 a, Vector2 b, Vector2 c) - { - Vector2 dirAB = b - a; - Vector2 dirAC = c - a; - Vector2 dirAP = p - a; - - float dotABAB = Vector2Util.Dot(dirAB, dirAB); - float dotACAB = Vector2Util.Dot(dirAC, dirAB); - float dotACAC = Vector2Util.Dot(dirAC, dirAC); - float dotACAP = Vector2Util.Dot(dirAC, dirAP); - float dotABAP = Vector2Util.Dot(dirAB, dirAP); - - float invDenom = 1 / (dotACAC * dotABAB - dotACAB * dotACAB); - float u = (dotABAB * dotACAP - dotACAB * dotABAP) * invDenom; - float v = (dotACAC * dotABAP - dotACAB * dotACAP) * invDenom; - - // Altered this slightly from the reference so that points on the - // vertices and edges are considered to be inside the triangle. - return (u >= 0) && (v >= 0) && (u + v <= 1); - } - - /// - /// The absolute value of the returned value is two times the area of the triangle ABC. - /// - /// - /// - /// A positive return value indicates: - /// - ///
    - ///
  • Counterclockwise wrapping of the vertices.
  • - ///
  • Vertex B lies to the right of line AC, looking from A toward C.
  • - ///
- /// A negative value indicates: - ///
    - ///
  • Clockwise wrapping of the vertices.
  • - ///
  • Vertex B lies to the left of line AC, looking from A toward C.
  • - ///
- /// - /// A value of zero indicates that all points are collinear or represent the same point. - /// - /// - /// This is a low cost method. - /// - ///
- /// Vertex A of triangle ABC. - /// Vertex B of triangle ABC - /// Vertex C of triangle ABC - /// - /// The absolute value of the returned value is two times the area of the triangle ABC. - /// - public static float GetSignedAreaX2(Vector2 a, Vector2 b, Vector2 c) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - // http://mathworld.wolfram.com/TriangleArea.html - // (Search for "signed".) - return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y); - } - - /// - /// The absolute value of the returned value is two times the area of the triangle ABC. - /// - /// - /// - /// A positive return value indicates: - /// - ///
    - ///
  • Counterclockwise wrapping of the vertices.
  • - ///
  • Vertex B lies to the right of line AC, looking from A toward C.
  • - ///
- /// A negative value indicates: - ///
    - ///
  • Clockwise wrapping of the vertices.
  • - ///
  • Vertex B lies to the left of line AC, looking from A toward C.
  • - ///
- /// - /// A value of zero indicates that all points are collinear or represent the same point. - /// - /// - /// This is a low cost method. - /// - ///
- /// The x-value for vertex A of triangle ABC - /// The y-value for vertex A of triangle ABC - /// The x-value for vertex B of triangle ABC - /// The y-value for vertex B of triangle ABC - /// The x-value for vertex C of triangle ABC - /// The y-value for vertex C of triangle ABC - /// The absolute value of the returned value is two times the - /// area of the triangle ABC. - public static float GetSignedAreaX2(float ax, float ay - , float bx, float by - , float cx, float cy) - { - // Note: Keep this around for use by Vector3. - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - - /// - /// The absolute value of the returned value is two times the area of the triangle ABC. - /// (Integer version.) - /// - /// - /// - /// A positive return value indicates: - /// - ///
    - ///
  • Counterclockwise wrapping of the vertices.
  • - ///
  • Vertex B lies to the right of line AC, looking from A toward C.
  • - ///
- /// - /// A negative value indicates: - /// - ///
    - ///
  • Clockwise wrapping of the vertices.
  • - ///
  • Vertex B lies to the left of line AC, looking from A toward C.
  • - ///
- /// - /// A value of zero indicates that all points are collinear orrepresent the same point. - /// - /// - /// This is a low cost method. - /// - ///
- /// The x-value for vertex A of triangle ABC - /// The y-value for vertex A of triangle ABC - /// The x-value for vertex B of triangle ABC - /// The y-value for vertex B of triangle ABC - /// The x-value for vertex C of triangle ABC - /// The y-value for vertex C of triangle ABC - /// - /// The absolute value of the returned value is two times the area of the triangle ABC. - /// - public static int GetSignedAreaX2(int ax, int ay - , int bx, int by - , int cx, int cy) - { - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - } -} diff --git a/critterai/.svn/pristine/1b/1b366d0fdd7404b492e1c8f7f52d836a982f6b32.svn-base b/critterai/.svn/pristine/1b/1b366d0fdd7404b492e1c8f7f52d836a982f6b32.svn-base deleted file mode 100644 index 482f1065..00000000 --- a/critterai/.svn/pristine/1b/1b366d0fdd7404b492e1c8f7f52d836a982f6b32.svn-base +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Assigns areas to MeshFilter components based on the component's mesh. (Editor Only) -/// -/// -/// -/// Will not override the assignment of . -/// -/// -public sealed class MeshAreaDef - : ScriptableObject, IInputBuildProcessor -{ - /// - /// The list of meshes that will be assigned an area. - /// - public List meshes; - - /// - /// The areas to be assigned. - /// - public List areas; - - /// - /// The type of match to use. - /// - public MatchType matchType; - - [SerializeField] - private int mPriority = NMBuild.DefaultPriority; - - /// - /// The priority of the processor. - /// - public int Priority { get { return mPriority; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// Duplicates allowed. (Always true.) - /// - public bool DuplicatesAllowed { get { return true; } } - - /// - /// Sets the priority. - /// - /// The new priority. - public void SetPriority(int value) - { - mPriority = NMBuild.ClampPriority(value); - } - - /// - /// Processes the context. - /// - /// - /// - /// Applied during the state. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (state != InputBuildState.ApplyAreaModifiers) - return true; - - context.info.areaModifierCount++; - - if (meshes == null || areas == null || meshes.Count != areas.Count) - { - context.LogError("Mesh/Area size error. (Invalid processor state.)", this); - return false; - } - - if (meshes.Count == 0) - { - context.Log("No action taken. No mesh areas defined.", this); - return true; - } - - List targetFilters = context.components; - List targetAreas = context.areas; - - int applied = 0; - for (int iTarget = 0; iTarget < targetFilters.Count; iTarget++) - { - if (!(targetFilters[iTarget] is MeshFilter)) - continue; - - MeshFilter filter = (MeshFilter)targetFilters[iTarget]; - - if (filter == null || targetAreas[iTarget] == org.critterai.nmgen.NMGen.NullArea) - // Never override null area. - continue; - - MatchPredicate p = new MatchPredicate(filter.sharedMesh, matchType, true); - - int iSource = meshes.FindIndex(p.Matches); - - if (iSource != -1) - { - targetAreas[iTarget] = areas[iSource]; - applied++; - } - } - - context.Log(string.Format("Applied area(s) to {0} components.", applied), this); - - return true; - } -} diff --git a/critterai/.svn/pristine/1b/1b3840533eebebf325b3531d067e3093d06588f2.svn-base b/critterai/.svn/pristine/1b/1b3840533eebebf325b3531d067e3093d06588f2.svn-base deleted file mode 100644 index 7efe10a4..00000000 --- a/critterai/.svn/pristine/1b/1b3840533eebebf325b3531d067e3093d06588f2.svn-base +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" -#include "RecastAlloc.h" - -// Used for versioning related to serialization. -static const long NMG_POLYMESH_VERSION = 1; - -struct nmgPolyMeshHeader -{ - // Same layout as non-pointer fields in rcPolyMesh except last field. - int nverts; - int npolys; - int maxpolys; - int nvp; - float bmin[3], bmax[3]; - float cs, ch; - int borderSize; - int maxverts; - float walkableHeight; - float walkableRadius; - float walkableStep; - long version; -}; - -int getMaxVerts(rcPolyMesh& mesh) -{ - int maxIndex = 0; - for (int i = 0; i < mesh.npolys; i++) - { - int p = i * 2 * mesh.nvp; - for (int j = 0; j < mesh.nvp; j++) - { - int index = mesh.polys[p + j]; - if (index == RC_MESH_NULL_IDX) - break; - maxIndex = rcMax(index, maxIndex); - } - } - - return maxIndex + 1; -} - -extern "C" -{ - // Not meant to be used with externally allocated meshes. - EXPORT_API bool rcpmFreeMeshData(rcPolyMesh* mesh) - { - // Dev Note: Expect that the structure was allocated externally. - // So only free the fields expected to have been allocated internally. - - if (!mesh) - return false; - - rcFree(mesh->polys); - rcFree(mesh->verts); - rcFree(mesh->regs); - rcFree(mesh->areas); - rcFree(mesh->flags); - - mesh->polys = 0; - mesh->verts = 0; - mesh->regs = 0; - mesh->areas = 0; - mesh->flags = 0; - mesh->borderSize = 0; - mesh->ch = 0; - mesh->cs = 0; - mesh->flags = 0; - mesh->maxpolys = 0; - mesh->npolys = 0; - mesh->nverts = 0; - mesh->nvp = 0; - - memset(&mesh->bmin[0], 0, sizeof(float) * 6); - - return true; - } - - EXPORT_API bool rcpmGetSerializedData(const rcPolyMesh* mesh - , const int maxVerts - , const float walkableHeight - , const float walkableRadius - , const float walkableStep - , const bool includeBuffer - , unsigned char** resultData - , int* dataSize) - { - if (!mesh - || !resultData - || !dataSize - || mesh->maxpolys == 0) - { - return false; - } - - int cap = sizeof(int) + sizeof(float) * 2 + sizeof(long); - - nmgPolyMeshHeader header; - header.version = NMG_POLYMESH_VERSION; - memcpy(&header - , &mesh->nverts - , sizeof(nmgPolyMeshHeader) - cap); - - int polyCount = (includeBuffer ? mesh->maxpolys : mesh->npolys); - int vertCount = (includeBuffer ? maxVerts : mesh->nverts); - - header.maxpolys = polyCount; - header.maxverts = vertCount; - header.walkableHeight = walkableHeight; - header.walkableRadius = walkableRadius; - header.walkableStep = walkableStep; - - int headerSize = sizeof(nmgPolyMeshHeader); - int vertSize = sizeof(unsigned short) * (vertCount * 3); - int polySize = sizeof(unsigned short) * (polyCount * 2 * mesh->nvp); - int regionFlagSize = sizeof(unsigned short) * polyCount; - int areaSize = sizeof(unsigned char) * polyCount; - - int totalDataSize = headerSize + vertSize + polySize - + 2 * regionFlagSize + areaSize; - - unsigned char* data = - (unsigned char*)rcAlloc(totalDataSize, RC_ALLOC_PERM); - - if (!data) - return false; - - int pos = 0; - memcpy(&data[pos], &header, headerSize); - pos += headerSize; - - memcpy(&data[pos], mesh->verts, vertSize); - pos += vertSize; - - memcpy(&data[pos], mesh->polys, polySize); - pos += polySize; - - memcpy(&data[pos], mesh->regs, regionFlagSize); - pos += regionFlagSize; - - memcpy(&data[pos], mesh->flags, regionFlagSize); - pos += regionFlagSize; - - memcpy(&data[pos], mesh->areas, areaSize); - - *resultData = data; - *dataSize = totalDataSize; - - return true; - } - - EXPORT_API bool rcpmBuildSerializedData(const unsigned char* meshData - , const int dataSize - , rcPolyMesh* resultMesh - , int* maxVerts - , float* walkableHeight - , float* walkableRadius - , float* walkableStep) - { - int headerSize = sizeof(nmgPolyMeshHeader); - - if (!meshData - || !resultMesh - || resultMesh->polys // Buffers should not be allocated. - || dataSize < headerSize - || !maxVerts - || !walkableStep - || !walkableRadius - || !walkableHeight) - return false; - - nmgPolyMeshHeader header; - - memcpy(&header, meshData, headerSize); - - if (header.version != NMG_POLYMESH_VERSION) - return false; - - int vertSize = sizeof(unsigned short) * (header.maxverts * 3); - int polySize = - sizeof(unsigned short) * (header.maxpolys * 2 * header.nvp); - int regionFlagSize = sizeof(unsigned short) * header.maxpolys; - int areaSize = sizeof(unsigned char) * header.maxpolys; - - int totalDataSize = headerSize + vertSize + polySize - + 2 * regionFlagSize + areaSize; - - if (dataSize < totalDataSize) - return false; - - resultMesh->verts = (unsigned short*)rcAlloc(vertSize, RC_ALLOC_PERM); - if (!resultMesh->verts) - { - rcpmFreeMeshData(resultMesh); - return false; - } - - resultMesh->polys = (unsigned short*)rcAlloc(polySize, RC_ALLOC_PERM); - if (!resultMesh->polys) - { - rcpmFreeMeshData(resultMesh); - return false; - } - - resultMesh->regs = - (unsigned short*)rcAlloc(regionFlagSize, RC_ALLOC_PERM); - if (!resultMesh->regs) - { - rcpmFreeMeshData(resultMesh); - return false; - } - - resultMesh->flags = - (unsigned short*)rcAlloc(regionFlagSize, RC_ALLOC_PERM); - if (!resultMesh->flags) - { - rcpmFreeMeshData(resultMesh); - return false; - } - - resultMesh->areas = (unsigned char*)rcAlloc(areaSize, RC_ALLOC_PERM); - if (!resultMesh->areas) - { - rcpmFreeMeshData(resultMesh); - return false; - } - - // Populate the mesh. - - int cap = sizeof(int) + sizeof(float) * 2 + sizeof(long); - memcpy(&resultMesh->nverts, &header, headerSize - cap); - - int pos = headerSize; - memcpy(resultMesh->verts, &meshData[pos], vertSize); - pos += vertSize; - - memcpy(resultMesh->polys, &meshData[pos], polySize); - pos += polySize; - - memcpy(resultMesh->regs, &meshData[pos], regionFlagSize); - pos += regionFlagSize; - - memcpy(resultMesh->flags, &meshData[pos], regionFlagSize); - pos += regionFlagSize; - - memcpy(resultMesh->areas, &meshData[pos], areaSize); - - *maxVerts = header.maxverts; - *walkableHeight = header.walkableHeight; - *walkableRadius = header.walkableRadius; - *walkableStep = header.walkableStep; - - return true; - } - - EXPORT_API bool rcpmBuildFromContourSet(nmgBuildContext* ctx - , rcContourSet* cset - , const int nvp - , rcPolyMesh* mesh - , int* maxVerts) - { - if (!ctx || !cset || !mesh || !maxVerts) - return false; - - if (!rcBuildPolyMesh(ctx, *cset, nvp, *mesh)) - return false; - - *maxVerts = getMaxVerts(*mesh); - - return true; - } - - EXPORT_API bool rcmpMergePolyMeshes(nmgBuildContext* ctx - , rcPolyMesh* meshes - , const int nmeshes - , rcPolyMesh* mesh - , int* maxVerts) - { - if (!ctx || !meshes || !mesh || !maxVerts) - return false; - - rcPolyMesh** m = (rcPolyMesh**) - rcAlloc(sizeof(rcPolyMesh*) * nmeshes, RC_ALLOC_PERM); - - for (int i = 0; i < nmeshes; i++) - { - m[i] = &meshes[i]; - } - - bool result = rcMergePolyMeshes(ctx, m, nmeshes, *mesh); - - rcFree(m); - - if (!result) - return false; - - *maxVerts = getMaxVerts(*mesh); - - return true; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/1b/1b4ab24a52f389c5eae0e979a1c13e7f743b78f4.svn-base b/critterai/.svn/pristine/1b/1b4ab24a52f389c5eae0e979a1c13e7f743b78f4.svn-base deleted file mode 100644 index de325623..00000000 --- a/critterai/.svn/pristine/1b/1b4ab24a52f389c5eae0e979a1c13e7f743b78f4.svn-base +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class InputBuildTask - : BuildTask - { - private InputGeometryBuilder mBuilder; - - public override bool IsThreadSafe { get {return mBuilder.IsThreadSafe; } } - - private InputBuildTask(InputGeometryBuilder builder, int priority) - : base(priority) - { - mBuilder = builder; - } - - protected override bool LocalUpdate() - { - return mBuilder.Build(); - } - - protected override bool GetResult(out InputGeometry result) - { - result = mBuilder.Result; - return true; - } - - protected override void FinalizeTask() - { - mBuilder = null; - } - - public static InputBuildTask Create(InputGeometryBuilder builder, int priority) - { - if (builder == null || builder.IsFinished) - return null; - - return new InputBuildTask(builder, priority); - } - } -} diff --git a/critterai/.svn/pristine/1c/1c90065edbc7207ea5dc7df0e486cec328870596.svn-base b/critterai/.svn/pristine/1c/1c90065edbc7207ea5dc7df0e486cec328870596.svn-base deleted file mode 100644 index 4e6e4a9d..00000000 --- a/critterai/.svn/pristine/1c/1c90065edbc7207ea5dc7df0e486cec328870596.svn-base +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.nav.u3d -{ - /// - /// Provides a convenient structure for grouping together related navigation resources. - /// - public struct NavGroup - { - /// - /// The navigation mesh used by . - /// - public Navmesh mesh; - - /// - /// A navigation mesh query. - /// - public NavmeshQuery query; - - /// - /// The filter to use with . - /// - public NavmeshQueryFilter filter; - - /// - /// A crowd. - /// - public CrowdManager crowd; - - /// - /// The extents to use with . - /// - public Vector3 extents; - - /// - /// Constructor. - /// - /// The navigation mesh used by the query. - /// A navigation mesh query. - /// A crowd. - /// The filter to use with the query. - /// The extents to use with the query. - /// - /// If true, the filter will be cloned rather than referenced. - /// - public NavGroup(Navmesh mesh, NavmeshQuery query, CrowdManager crowd - , NavmeshQueryFilter filter, Vector3 extents - , bool cloneFilter) - { - this.mesh = mesh; - this.query = query; - this.crowd = crowd; - this.filter = (cloneFilter ? filter.Clone() : filter); - this.extents = extents; - } - - /// - /// Copy constructor. - /// - /// The group to copy. - /// - /// If true, the filter will be cloned. Otherwise it will be referenced. - /// - public NavGroup(NavGroup copy, bool cloneFilter) - { - this.mesh = copy.mesh; - this.query = copy.query; - this.crowd = copy.crowd; - this.filter = (cloneFilter ? copy.filter.Clone() : copy.filter); - this.extents = copy.extents; - } - } -} diff --git a/critterai/.svn/pristine/1c/1cb9df6303d5aa233704ec449f242c336621f608.svn-base b/critterai/.svn/pristine/1c/1cb9df6303d5aa233704ec449f242c336621f608.svn-base deleted file mode 100644 index 5c324bce..00000000 --- a/critterai/.svn/pristine/1c/1cb9df6303d5aa233704ec449f242c336621f608.svn-base +++ /dev/null @@ -1,851 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#define _USE_MATH_DEFINES -#include -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" - - -static int getCornerHeight(int x, int y, int i, int dir, - const rcCompactHeightfield& chf, - bool& isBorderVertex) -{ - const rcCompactSpan& s = chf.spans[i]; - int ch = (int)s.y; - int dirp = (dir+1) & 0x3; - - unsigned int regs[4] = {0,0,0,0}; - - // Combine region and area codes in order to prevent - // border vertices which are in between two areas to be removed. - regs[0] = chf.spans[i].reg | (chf.areas[i] << 16); - - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir); - const rcCompactSpan& as = chf.spans[ai]; - ch = rcMax(ch, (int)as.y); - regs[1] = chf.spans[ai].reg | (chf.areas[ai] << 16); - if (rcGetCon(as, dirp) != RC_NOT_CONNECTED) - { - const int ax2 = ax + rcGetDirOffsetX(dirp); - const int ay2 = ay + rcGetDirOffsetY(dirp); - const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dirp); - const rcCompactSpan& as2 = chf.spans[ai2]; - ch = rcMax(ch, (int)as2.y); - regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16); - } - } - if (rcGetCon(s, dirp) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dirp); - const int ay = y + rcGetDirOffsetY(dirp); - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dirp); - const rcCompactSpan& as = chf.spans[ai]; - ch = rcMax(ch, (int)as.y); - regs[3] = chf.spans[ai].reg | (chf.areas[ai] << 16); - if (rcGetCon(as, dir) != RC_NOT_CONNECTED) - { - const int ax2 = ax + rcGetDirOffsetX(dir); - const int ay2 = ay + rcGetDirOffsetY(dir); - const int ai2 = (int)chf.cells[ax2+ay2*chf.width].index + rcGetCon(as, dir); - const rcCompactSpan& as2 = chf.spans[ai2]; - ch = rcMax(ch, (int)as2.y); - regs[2] = chf.spans[ai2].reg | (chf.areas[ai2] << 16); - } - } - - // Check if the vertex is special edge vertex, these vertices will be removed later. - for (int j = 0; j < 4; ++j) - { - const int a = j; - const int b = (j+1) & 0x3; - const int c = (j+2) & 0x3; - const int d = (j+3) & 0x3; - - // The vertex is a border vertex there are two same exterior cells in a row, - // followed by two interior cells and none of the regions are out of bounds. - const bool twoSameExts = (regs[a] & regs[b] & RC_BORDER_REG) != 0 && regs[a] == regs[b]; - const bool twoInts = ((regs[c] | regs[d]) & RC_BORDER_REG) == 0; - const bool intsSameArea = (regs[c]>>16) == (regs[d]>>16); - const bool noZeros = regs[a] != 0 && regs[b] != 0 && regs[c] != 0 && regs[d] != 0; - if (twoSameExts && twoInts && intsSameArea && noZeros) - { - isBorderVertex = true; - break; - } - } - - return ch; -} - -static void walkContour(int x, int y, int i, - rcCompactHeightfield& chf, - unsigned char* flags, rcIntArray& points) -{ - // Choose the first non-connected edge - unsigned char dir = 0; - while ((flags[i] & (1 << dir)) == 0) - dir++; - - unsigned char startDir = dir; - int starti = i; - - const unsigned char area = chf.areas[i]; - - int iter = 0; - while (++iter < 40000) - { - if (flags[i] & (1 << dir)) - { - // Choose the edge corner - bool isBorderVertex = false; - bool isAreaBorder = false; - int px = x; - int py = getCornerHeight(x, y, i, dir, chf, isBorderVertex); - int pz = y; - switch(dir) - { - case 0: pz++; break; - case 1: px++; pz++; break; - case 2: px++; break; - } - int r = 0; - const rcCompactSpan& s = chf.spans[i]; - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir); - r = (int)chf.spans[ai].reg; - if (area != chf.areas[ai]) - isAreaBorder = true; - } - if (isBorderVertex) - r |= RC_BORDER_VERTEX; - if (isAreaBorder) - r |= RC_AREA_BORDER; - points.push(px); - points.push(py); - points.push(pz); - points.push(r); - - flags[i] &= ~(1 << dir); // Remove visited edges - dir = (dir+1) & 0x3; // Rotate CW - } - else - { - int ni = -1; - const int nx = x + rcGetDirOffsetX(dir); - const int ny = y + rcGetDirOffsetY(dir); - const rcCompactSpan& s = chf.spans[i]; - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const rcCompactCell& nc = chf.cells[nx+ny*chf.width]; - ni = (int)nc.index + rcGetCon(s, dir); - } - if (ni == -1) - { - // Should not happen. - return; - } - x = nx; - y = ny; - i = ni; - dir = (dir+3) & 0x3; // Rotate CCW - } - - if (starti == i && startDir == dir) - { - break; - } - } -} - -static float distancePtSeg(const int x, const int z, - const int px, const int pz, - const int qx, const int qz) -{ -/* float pqx = (float)(qx - px); - float pqy = (float)(qy - py); - float pqz = (float)(qz - pz); - float dx = (float)(x - px); - float dy = (float)(y - py); - float dz = (float)(z - pz); - float d = pqx*pqx + pqy*pqy + pqz*pqz; - float t = pqx*dx + pqy*dy + pqz*dz; - if (d > 0) - t /= d; - if (t < 0) - t = 0; - else if (t > 1) - t = 1; - - dx = px + t*pqx - x; - dy = py + t*pqy - y; - dz = pz + t*pqz - z; - - return dx*dx + dy*dy + dz*dz;*/ - - float pqx = (float)(qx - px); - float pqz = (float)(qz - pz); - float dx = (float)(x - px); - float dz = (float)(z - pz); - float d = pqx*pqx + pqz*pqz; - float t = pqx*dx + pqz*dz; - if (d > 0) - t /= d; - if (t < 0) - t = 0; - else if (t > 1) - t = 1; - - dx = px + t*pqx - x; - dz = pz + t*pqz - z; - - return dx*dx + dz*dz; -} - -static void simplifyContour(rcIntArray& points, rcIntArray& simplified, - const float maxError, const int maxEdgeLen, const int buildFlags) -{ - // Add initial points. - bool hasConnections = false; - for (int i = 0; i < points.size(); i += 4) - { - if ((points[i+3] & RC_CONTOUR_REG_MASK) != 0) - { - hasConnections = true; - break; - } - } - - if (hasConnections) - { - // The contour has some portals to other regions. - // Add a new point to every location where the region changes. - for (int i = 0, ni = points.size()/4; i < ni; ++i) - { - int ii = (i+1) % ni; - const bool differentRegs = (points[i*4+3] & RC_CONTOUR_REG_MASK) != (points[ii*4+3] & RC_CONTOUR_REG_MASK); - const bool areaBorders = (points[i*4+3] & RC_AREA_BORDER) != (points[ii*4+3] & RC_AREA_BORDER); - if (differentRegs || areaBorders) - { - simplified.push(points[i*4+0]); - simplified.push(points[i*4+1]); - simplified.push(points[i*4+2]); - simplified.push(i); - } - } - } - - if (simplified.size() == 0) - { - // If there is no connections at all, - // create some initial points for the simplification process. - // Find lower-left and upper-right vertices of the contour. - int llx = points[0]; - int lly = points[1]; - int llz = points[2]; - int lli = 0; - int urx = points[0]; - int ury = points[1]; - int urz = points[2]; - int uri = 0; - for (int i = 0; i < points.size(); i += 4) - { - int x = points[i+0]; - int y = points[i+1]; - int z = points[i+2]; - if (x < llx || (x == llx && z < llz)) - { - llx = x; - lly = y; - llz = z; - lli = i/4; - } - if (x > urx || (x == urx && z > urz)) - { - urx = x; - ury = y; - urz = z; - uri = i/4; - } - } - simplified.push(llx); - simplified.push(lly); - simplified.push(llz); - simplified.push(lli); - - simplified.push(urx); - simplified.push(ury); - simplified.push(urz); - simplified.push(uri); - } - - // Add points until all raw points are within - // error tolerance to the simplified shape. - const int pn = points.size()/4; - for (int i = 0; i < simplified.size()/4; ) - { - int ii = (i+1) % (simplified.size()/4); - - const int ax = simplified[i*4+0]; - const int az = simplified[i*4+2]; - const int ai = simplified[i*4+3]; - - const int bx = simplified[ii*4+0]; - const int bz = simplified[ii*4+2]; - const int bi = simplified[ii*4+3]; - - // Find maximum deviation from the segment. - float maxd = 0; - int maxi = -1; - int ci, cinc, endi; - - // Traverse the segment in lexilogical order so that the - // max deviation is calculated similarly when traversing - // opposite segments. - if (bx > ax || (bx == ax && bz > az)) - { - cinc = 1; - ci = (ai+cinc) % pn; - endi = bi; - } - else - { - cinc = pn-1; - ci = (bi+cinc) % pn; - endi = ai; - } - - // Tessellate only outer edges or edges between areas. - if ((points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0 || - (points[ci*4+3] & RC_AREA_BORDER)) - { - while (ci != endi) - { - float d = distancePtSeg(points[ci*4+0], points[ci*4+2], ax, az, bx, bz); - if (d > maxd) - { - maxd = d; - maxi = ci; - } - ci = (ci+cinc) % pn; - } - } - - - // If the max deviation is larger than accepted error, - // add new point, else continue to next segment. - if (maxi != -1 && maxd > (maxError*maxError)) - { - // Add space for the new point. - simplified.resize(simplified.size()+4); - const int n = simplified.size()/4; - for (int j = n-1; j > i; --j) - { - simplified[j*4+0] = simplified[(j-1)*4+0]; - simplified[j*4+1] = simplified[(j-1)*4+1]; - simplified[j*4+2] = simplified[(j-1)*4+2]; - simplified[j*4+3] = simplified[(j-1)*4+3]; - } - // Add the point. - simplified[(i+1)*4+0] = points[maxi*4+0]; - simplified[(i+1)*4+1] = points[maxi*4+1]; - simplified[(i+1)*4+2] = points[maxi*4+2]; - simplified[(i+1)*4+3] = maxi; - } - else - { - ++i; - } - } - - // Split too long edges. - if (maxEdgeLen > 0 && (buildFlags & (RC_CONTOUR_TESS_WALL_EDGES|RC_CONTOUR_TESS_AREA_EDGES)) != 0) - { - for (int i = 0; i < simplified.size()/4; ) - { - const int ii = (i+1) % (simplified.size()/4); - - const int ax = simplified[i*4+0]; - const int az = simplified[i*4+2]; - const int ai = simplified[i*4+3]; - - const int bx = simplified[ii*4+0]; - const int bz = simplified[ii*4+2]; - const int bi = simplified[ii*4+3]; - - // Find maximum deviation from the segment. - int maxi = -1; - int ci = (ai+1) % pn; - - // Tessellate only outer edges or edges between areas. - bool tess = false; - // Wall edges. - if ((buildFlags & RC_CONTOUR_TESS_WALL_EDGES) && (points[ci*4+3] & RC_CONTOUR_REG_MASK) == 0) - tess = true; - // Edges between areas. - if ((buildFlags & RC_CONTOUR_TESS_AREA_EDGES) && (points[ci*4+3] & RC_AREA_BORDER)) - tess = true; - - if (tess) - { - int dx = bx - ax; - int dz = bz - az; - if (dx*dx + dz*dz > maxEdgeLen*maxEdgeLen) - { - // Round based on the segments in lexilogical order so that the - // max tesselation is consistent regardles in which direction - // segments are traversed. - const int n = bi < ai ? (bi+pn - ai) : (bi - ai); - if (n > 1) - { - if (bx > ax || (bx == ax && bz > az)) - maxi = (ai + n/2) % pn; - else - maxi = (ai + (n+1)/2) % pn; - } - } - } - - // If the max deviation is larger than accepted error, - // add new point, else continue to next segment. - if (maxi != -1) - { - // Add space for the new point. - simplified.resize(simplified.size()+4); - const int n = simplified.size()/4; - for (int j = n-1; j > i; --j) - { - simplified[j*4+0] = simplified[(j-1)*4+0]; - simplified[j*4+1] = simplified[(j-1)*4+1]; - simplified[j*4+2] = simplified[(j-1)*4+2]; - simplified[j*4+3] = simplified[(j-1)*4+3]; - } - // Add the point. - simplified[(i+1)*4+0] = points[maxi*4+0]; - simplified[(i+1)*4+1] = points[maxi*4+1]; - simplified[(i+1)*4+2] = points[maxi*4+2]; - simplified[(i+1)*4+3] = maxi; - } - else - { - ++i; - } - } - } - - for (int i = 0; i < simplified.size()/4; ++i) - { - // The edge vertex flag is take from the current raw point, - // and the neighbour region is take from the next raw point. - const int ai = (simplified[i*4+3]+1) % pn; - const int bi = simplified[i*4+3]; - simplified[i*4+3] = (points[ai*4+3] & (RC_CONTOUR_REG_MASK|RC_AREA_BORDER)) | (points[bi*4+3] & RC_BORDER_VERTEX); - } - -} - -static void removeDegenerateSegments(rcIntArray& simplified) -{ - // Remove adjacent vertices which are equal on xz-plane, - // or else the triangulator will get confused. - for (int i = 0; i < simplified.size()/4; ++i) - { - int ni = i+1; - if (ni >= (simplified.size()/4)) - ni = 0; - - if (simplified[i*4+0] == simplified[ni*4+0] && - simplified[i*4+2] == simplified[ni*4+2]) - { - // Degenerate segment, remove. - for (int j = i; j < simplified.size()/4-1; ++j) - { - simplified[j*4+0] = simplified[(j+1)*4+0]; - simplified[j*4+1] = simplified[(j+1)*4+1]; - simplified[j*4+2] = simplified[(j+1)*4+2]; - simplified[j*4+3] = simplified[(j+1)*4+3]; - } - simplified.resize(simplified.size()-4); - } - } -} - -static int calcAreaOfPolygon2D(const int* verts, const int nverts) -{ - int area = 0; - for (int i = 0, j = nverts-1; i < nverts; j=i++) - { - const int* vi = &verts[i*4]; - const int* vj = &verts[j*4]; - area += vi[0] * vj[2] - vj[0] * vi[2]; - } - return (area+1) / 2; -} - -inline bool ileft(const int* a, const int* b, const int* c) -{ - return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]) <= 0; -} - -static void getClosestIndices(const int* vertsa, const int nvertsa, - const int* vertsb, const int nvertsb, - int& ia, int& ib) -{ - int closestDist = 0xfffffff; - ia = -1, ib = -1; - for (int i = 0; i < nvertsa; ++i) - { - const int in = (i+1) % nvertsa; - const int ip = (i+nvertsa-1) % nvertsa; - const int* va = &vertsa[i*4]; - const int* van = &vertsa[in*4]; - const int* vap = &vertsa[ip*4]; - - for (int j = 0; j < nvertsb; ++j) - { - const int* vb = &vertsb[j*4]; - // vb must be "infront" of va. - if (ileft(vap,va,vb) && ileft(va,van,vb)) - { - const int dx = vb[0] - va[0]; - const int dz = vb[2] - va[2]; - const int d = dx*dx + dz*dz; - if (d < closestDist) - { - ia = i; - ib = j; - closestDist = d; - } - } - } - } -} - -static bool mergeContours(rcContour& ca, rcContour& cb, int ia, int ib) -{ - const int maxVerts = ca.nverts + cb.nverts + 2; - int* verts = (int*)rcAlloc(sizeof(int)*maxVerts*4, RC_ALLOC_PERM); - if (!verts) - return false; - - int nv = 0; - - // Copy contour A. - for (int i = 0; i <= ca.nverts; ++i) - { - int* dst = &verts[nv*4]; - const int* src = &ca.verts[((ia+i)%ca.nverts)*4]; - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst[3] = src[3]; - nv++; - } - - // Copy contour B - for (int i = 0; i <= cb.nverts; ++i) - { - int* dst = &verts[nv*4]; - const int* src = &cb.verts[((ib+i)%cb.nverts)*4]; - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst[3] = src[3]; - nv++; - } - - rcFree(ca.verts); - ca.verts = verts; - ca.nverts = nv; - - rcFree(cb.verts); - cb.verts = 0; - cb.nverts = 0; - - return true; -} - -/// @par -/// -/// The raw contours will match the region outlines exactly. The @p maxError and @p maxEdgeLen -/// parameters control how closely the simplified contours will match the raw contours. -/// -/// Simplified contours are generated such that the vertices for portals between areas match up. -/// (They are considered mandatory vertices.) -/// -/// Setting @p maxEdgeLength to zero will disabled the edge length feature. -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcAllocContourSet, rcCompactHeightfield, rcContourSet, rcConfig -bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, - const float maxError, const int maxEdgeLen, - rcContourSet& cset, const int buildFlags) -{ - rcAssert(ctx); - - const int w = chf.width; - const int h = chf.height; - const int borderSize = chf.borderSize; - - ctx->startTimer(RC_TIMER_BUILD_CONTOURS); - - rcVcopy(cset.bmin, chf.bmin); - rcVcopy(cset.bmax, chf.bmax); - if (borderSize > 0) - { - // If the heightfield was build with bordersize, remove the offset. - const float pad = borderSize*chf.cs; - cset.bmin[0] += pad; - cset.bmin[2] += pad; - cset.bmax[0] -= pad; - cset.bmax[2] -= pad; - } - cset.cs = chf.cs; - cset.ch = chf.ch; - cset.width = chf.width - chf.borderSize*2; - cset.height = chf.height - chf.borderSize*2; - cset.borderSize = chf.borderSize; - - int maxContours = rcMax((int)chf.maxRegions, 8); - cset.conts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM); - if (!cset.conts) - return false; - cset.nconts = 0; - - rcScopedDelete flags = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); - if (!flags) - { - ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'flags' (%d).", chf.spanCount); - return false; - } - - ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE); - - // Mark boundaries. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - unsigned char res = 0; - const rcCompactSpan& s = chf.spans[i]; - if (!chf.spans[i].reg || (chf.spans[i].reg & RC_BORDER_REG)) - { - flags[i] = 0; - continue; - } - for (int dir = 0; dir < 4; ++dir) - { - unsigned short r = 0; - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); - r = chf.spans[ai].reg; - } - if (r == chf.spans[i].reg) - res |= (1 << dir); - } - flags[i] = res ^ 0xf; // Inverse, mark non connected edges. - } - } - } - - ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE); - - rcIntArray verts(256); - rcIntArray simplified(64); - - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - if (flags[i] == 0 || flags[i] == 0xf) - { - flags[i] = 0; - continue; - } - const unsigned short reg = chf.spans[i].reg; - if (!reg || (reg & RC_BORDER_REG)) - continue; - const unsigned char area = chf.areas[i]; - - verts.resize(0); - simplified.resize(0); - - ctx->startTimer(RC_TIMER_BUILD_CONTOURS_TRACE); - walkContour(x, y, i, chf, flags, verts); - ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_TRACE); - - ctx->startTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY); - simplifyContour(verts, simplified, maxError, maxEdgeLen, buildFlags); - removeDegenerateSegments(simplified); - ctx->stopTimer(RC_TIMER_BUILD_CONTOURS_SIMPLIFY); - - - // Store region->contour remap info. - // Create contour. - if (simplified.size()/4 >= 3) - { - if (cset.nconts >= maxContours) - { - // Allocate more contours. - // This can happen when there are tiny holes in the heightfield. - const int oldMax = maxContours; - maxContours *= 2; - rcContour* newConts = (rcContour*)rcAlloc(sizeof(rcContour)*maxContours, RC_ALLOC_PERM); - for (int j = 0; j < cset.nconts; ++j) - { - newConts[j] = cset.conts[j]; - // Reset source pointers to prevent data deletion. - cset.conts[j].verts = 0; - cset.conts[j].rverts = 0; - } - rcFree(cset.conts); - cset.conts = newConts; - - ctx->log(RC_LOG_WARNING, "rcBuildContours: Expanding max contours from %d to %d.", oldMax, maxContours); - } - - rcContour* cont = &cset.conts[cset.nconts++]; - - cont->nverts = simplified.size()/4; - cont->verts = (int*)rcAlloc(sizeof(int)*cont->nverts*4, RC_ALLOC_PERM); - if (!cont->verts) - { - ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'verts' (%d).", cont->nverts); - return false; - } - memcpy(cont->verts, &simplified[0], sizeof(int)*cont->nverts*4); - if (borderSize > 0) - { - // If the heightfield was build with bordersize, remove the offset. - for (int j = 0; j < cont->nverts; ++j) - { - int* v = &cont->verts[j*4]; - v[0] -= borderSize; - v[2] -= borderSize; - } - } - - cont->nrverts = verts.size()/4; - cont->rverts = (int*)rcAlloc(sizeof(int)*cont->nrverts*4, RC_ALLOC_PERM); - if (!cont->rverts) - { - ctx->log(RC_LOG_ERROR, "rcBuildContours: Out of memory 'rverts' (%d).", cont->nrverts); - return false; - } - memcpy(cont->rverts, &verts[0], sizeof(int)*cont->nrverts*4); - if (borderSize > 0) - { - // If the heightfield was build with bordersize, remove the offset. - for (int j = 0; j < cont->nrverts; ++j) - { - int* v = &cont->rverts[j*4]; - v[0] -= borderSize; - v[2] -= borderSize; - } - } - -/* cont->cx = cont->cy = cont->cz = 0; - for (int i = 0; i < cont->nverts; ++i) - { - cont->cx += cont->verts[i*4+0]; - cont->cy += cont->verts[i*4+1]; - cont->cz += cont->verts[i*4+2]; - } - cont->cx /= cont->nverts; - cont->cy /= cont->nverts; - cont->cz /= cont->nverts;*/ - - cont->reg = reg; - cont->area = area; - } - } - } - } - - // Check and merge droppings. - // Sometimes the previous algorithms can fail and create several contours - // per area. This pass will try to merge the holes into the main region. - for (int i = 0; i < cset.nconts; ++i) - { - rcContour& cont = cset.conts[i]; - // Check if the contour is would backwards. - if (calcAreaOfPolygon2D(cont.verts, cont.nverts) < 0) - { - // Find another contour which has the same region ID. - int mergeIdx = -1; - for (int j = 0; j < cset.nconts; ++j) - { - if (i == j) continue; - if (cset.conts[j].nverts && cset.conts[j].reg == cont.reg) - { - // Make sure the polygon is correctly oriented. - if (calcAreaOfPolygon2D(cset.conts[j].verts, cset.conts[j].nverts)) - { - mergeIdx = j; - break; - } - } - } - if (mergeIdx == -1) - { - ctx->log(RC_LOG_WARNING, "rcBuildContours: Could not find merge target for bad contour %d.", i); - } - else - { - rcContour& mcont = cset.conts[mergeIdx]; - // Merge by closest points. - int ia = 0, ib = 0; - getClosestIndices(mcont.verts, mcont.nverts, cont.verts, cont.nverts, ia, ib); - if (ia == -1 || ib == -1) - { - ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to find merge points for %d and %d.", i, mergeIdx); - continue; - } - if (!mergeContours(mcont, cont, ia, ib)) - { - ctx->log(RC_LOG_WARNING, "rcBuildContours: Failed to merge contours %d and %d.", i, mergeIdx); - continue; - } - } - } - } - - ctx->stopTimer(RC_TIMER_BUILD_CONTOURS); - - return true; -} diff --git a/critterai/.svn/pristine/1d/1dd00a188c488906b9c81f587b1193f6372c5ff2.svn-base b/critterai/.svn/pristine/1d/1dd00a188c488906b9c81f587b1193f6372c5ff2.svn-base deleted file mode 100644 index 73d68214..00000000 --- a/critterai/.svn/pristine/1d/1dd00a188c488906b9c81f587b1193f6372c5ff2.svn-base +++ /dev/null @@ -1,18 +0,0 @@ -package org.critterai.nmgen; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * Unit tests for all classes in the org.critterai.nav package. - */ -@RunWith(Suite.class) -@SuiteClasses( {GeometryTests.class - , OpenHeightSpanTests.class - , EncompassedNullRegionTests.class - , NullRegionOuterCornerTipTests.class - , NullRegionShortWrapTests.class - , RemoveIntersectingSegmentTests.class - , RemoveVerticalSegmentTests.class} ) -public final class AllTests { } diff --git a/critterai/.svn/pristine/1e/1ec1511af9031506142d705dda1a65522be13ef0.svn-base b/critterai/.svn/pristine/1e/1ec1511af9031506142d705dda1a65522be13ef0.svn-base deleted file mode 100644 index 69edbd20..00000000 --- a/critterai/.svn/pristine/1e/1ec1511af9031506142d705dda1a65522be13ef0.svn-base +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Input build options. (Editor Only) - /// - [System.Flags] - public enum InputBuildOption - { - /// - /// Only permit objects that are marked as thread-safe. - /// - ThreadSafeOnly = 0x01, - - /// - /// Automatically remove invalid triangles during post-processing. - /// - AutoCleanGeometry = 0x02, - } -} diff --git a/critterai/.svn/pristine/1e/1ee56a0e7a9d168229b2d155d461d21a39d89050.svn-base b/critterai/.svn/pristine/1e/1ee56a0e7a9d168229b2d155d461d21a39d89050.svn-base deleted file mode 100644 index b1f1382b..00000000 --- a/critterai/.svn/pristine/1e/1ee56a0e7a9d168229b2d155d461d21a39d89050.svn-base +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav.u3d; -using org.critterai.u3d.editor; -using UnityEditor; -using UnityEngine; - -namespace org.critterai.nav.u3d.editor -{ - /// - /// Provides various navigation editor related constants and methods. - /// - public static class NavEditorUtil - { - /// - /// The standard label for navigation assets. - /// - public static string AssetLabel = "Navigation"; - - /// - /// The menu priority for navigation asset creation. - /// - public const int NavAssetGroup = EditorUtil.AssetGroup + 500; - - /// - /// True if the provided information does not match the current scene or is not - /// available. - /// - /// The build information to check. (Null is valid.) - /// True if the provided information does not match the current scene. - public static bool SceneMismatch(NavmeshBuildInfo info) - { - return !(info == null - || info.inputScene == EditorApplication.currentScene - || info.inputScene == null - || info.inputScene.Length == 0); - } - - /// - /// The standard scene display name for the information. - /// - /// The build information to check. (Null is valid.) - /// The standard scene display name for the information. - public static string SceneDisplayName(NavmeshBuildInfo info) - { - if (info == null || info.inputScene == null || info.inputScene.Length == 0) - return "Unknown"; - - string result = System.IO.Path.GetFileName(info.inputScene); - - return result.Substring(0, result.LastIndexOf(".")); - } - - /// - /// Displays an object field that will only accept ScriptableObjects that implement - /// the interface. - /// - /// - /// - /// Handles error logging when an invalid object is selected. - /// - /// - /// The label for the object field. - /// The ScriptableObject the field shows. - /// The ScriptableObject selected by the user. - public static INavmeshData OnGUINavmeshDataField(string label, INavmeshData item) - { - ScriptableObject so = (ScriptableObject)item; - - ScriptableObject nso = (ScriptableObject)EditorGUILayout.ObjectField(label - , so, typeof(ScriptableObject), false); - - if (nso is INavmeshData || !nso) // Null OK. - return (INavmeshData)nso; - - Debug.LogError( - string.Format("{0} does not implement {1}.", nso.name, typeof(INavmeshData).Name)); - - return item; - } - } -} diff --git a/critterai/.svn/pristine/1f/1f2d0796df2714fe11e65287a4c6578b747ac3f8.svn-base b/critterai/.svn/pristine/1f/1f2d0796df2714fe11e65287a4c6578b747ac3f8.svn-base deleted file mode 100644 index ae1862a7..00000000 --- a/critterai/.svn/pristine/1f/1f2d0796df2714fe11e65287a4c6578b747ac3f8.svn-base +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.nav.u3d; - -namespace org.critterai.nav.u3d.editor -{ - /// - /// Controls the debug visualization of objects. - /// - /// - /// - /// Implemented as a singleton to allow multiple components to manage the display. - /// - /// - /// Also provides shared GUI features for the Editor. - /// - /// - public sealed class NavmeshSceneDraw - { - private static NavmeshSceneDraw mInstance; - - private INavmeshData mNavmeshData; - private Navmesh mNavmesh; - private int mDataVersion; - private SceneView.OnSceneFunc mDelegate; - - private bool mColorByArea = false; - - private NavmeshSceneDraw() { } - - /// - /// Singleton instance. - /// - public static NavmeshSceneDraw Instance - { - get - { - if (mInstance == null) - mInstance = new NavmeshSceneDraw(); - return mInstance; - } - } - - /// - /// True if color should be assigned by area, false to color by tile. - /// - public bool ColorByArea - { - get { return mColorByArea; } - set { mColorByArea = value; } - } - - /// - /// True if the object is currently assigned for visualization. - /// - /// The object to visualize. - /// True if the object is currently assigned for visualization. - public bool IsShown(INavmeshData data) - { - return ((ScriptableObject)data && data == mNavmeshData); - } - - /// - /// True if the visualization is active. - /// - /// True if an object is currently assigned for visualization. - public bool IsShown() - { - return (ScriptableObject)mNavmeshData; - } - - /// - /// Show the visualization for the object. - /// - /// The object to visualize. - public void Show(INavmeshData data) - { - Hide(); - - if (!(ScriptableObject)data) - return; - - mNavmeshData = data; - - mDelegate = new SceneView.OnSceneFunc(OnSceneGUI); - - SceneView.onSceneGUIDelegate += mDelegate; - SceneView.RepaintAll(); - } - - /// - /// Disable the visualization. - /// - public void Hide() - { - if (mDelegate != null) - { - SceneView.onSceneGUIDelegate -= mDelegate; - SceneView.RepaintAll(); - } - - mNavmeshData = null; - mDataVersion = -1; - mNavmesh = null; - mDelegate = null; - } - - /// - /// Provides a standard Editor GUI for managing scene drawing. - /// - /// The object being managed by the GUI. - /// The label of the 'show' toggle. - /// True if the inspector format should be used. - /// - /// True if the option to color by area should be displayed. - /// - /// True the display of the target has been toggled on. - public bool OnGUI(INavmeshData target - , string label - , bool isInspector - , bool includeAreaOption) - { - if (!(ScriptableObject)target) - return false; - - bool guiEnabled = GUI.enabled; - - bool origChanged = GUI.changed; - GUI.changed = false; - - bool orig = IsShown(target); - bool curr; - - if (isInspector) - { - curr = EditorGUILayout.Toggle(label, orig); - GUI.enabled = guiEnabled && curr; - if (includeAreaOption) - mColorByArea = EditorGUILayout.Toggle("Color by area", mColorByArea); - } - else - { - curr = GUILayout.Toggle(orig, label); - GUI.enabled = guiEnabled && curr; - if (includeAreaOption) - mColorByArea = GUILayout.Toggle(mColorByArea, "Color by area"); - } - - GUI.enabled = guiEnabled; - - if (orig != curr) - { - if (curr) - Show(target); - else - Hide(); - } - - if (GUI.changed) - { - SceneView.RepaintAll(); - } - - GUI.changed = origChanged; - - return curr; - } - - private void OnSceneGUI(SceneView sceneView) - { - if (!(ScriptableObject)mNavmeshData) - { - Hide(); - return; - } - - if (!mNavmeshData.HasNavmesh) - { - mDataVersion = -1; - mNavmesh = null; - return; - } - - if (mNavmesh == null || mNavmeshData.Version != mDataVersion) - { - mNavmesh = mNavmeshData.GetNavmesh(); - mDataVersion = mNavmeshData.Version; - - if (mNavmesh == null) - return; - } - - NavDebug.Draw(mNavmesh, mColorByArea); - } - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/20/206efe638702c55648a01b022dd1f94ace7f155d.svn-base b/critterai/.svn/pristine/20/206efe638702c55648a01b022dd1f94ace7f155d.svn-base deleted file mode 100644 index 7d282f59..00000000 --- a/critterai/.svn/pristine/20/206efe638702c55648a01b022dd1f94ace7f155d.svn-base +++ /dev/null @@ -1,83 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-util", "util\cai-util.csproj", "{C4B32B85-13F0-42B8-AC89-770BEFEAF022}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cai-nmgen-rcn", "nmgen-rcn\cai-nmgen-rcn.vcproj", "{B783B817-8746-4D54-A6CC-664C0A73186F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nmgen", "nmgen\cai-nmgen.csproj", "{9DFC1FE0-6469-4A04-AB13-9EAC59087802}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nav", "nav\cai-nav.csproj", "{42218E47-156D-46FF-84E0-119D47B0E4EB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cai-nav-rcn", "nav-rcn\cai-nav-rcn.vcproj", "{319D361B-147F-45AC-854E-50C06FCA3393}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nmbuild", "nmbuild\cai-nmbuild.csproj", "{08B1606A-B8CD-4725-AF68-A9CC8CEAE336}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Win32.ActiveCfg = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Win32.ActiveCfg = Release|Any CPU - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Win32.ActiveCfg = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Win32.Build.0 = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Any CPU.ActiveCfg = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Mixed Platforms.Build.0 = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Win32.ActiveCfg = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Win32.Build.0 = Release|Win32 - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Win32.ActiveCfg = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Win32.ActiveCfg = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Win32.ActiveCfg = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Win32.ActiveCfg = Release|Any CPU - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Win32.ActiveCfg = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Win32.Build.0 = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Any CPU.ActiveCfg = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Mixed Platforms.Build.0 = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Win32.ActiveCfg = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Win32.Build.0 = Release|Win32 - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Any CPU.Build.0 = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Win32.ActiveCfg = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Any CPU.ActiveCfg = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Any CPU.Build.0 = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Win32.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/critterai/.svn/pristine/20/20814f6d6f2cd08136882ed7d42a10aeac751be3.svn-base b/critterai/.svn/pristine/20/20814f6d6f2cd08136882ed7d42a10aeac751be3.svn-base deleted file mode 100644 index 9a6f531a..00000000 --- a/critterai/.svn/pristine/20/20814f6d6f2cd08136882ed7d42a10aeac751be3.svn-base +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmgen -{ - /// - /// Flags used to control the contour build process. - /// - /// - [System.Flags] - public enum ContourBuildFlags - { - /// - /// Tessellate the wall (unconnected border) edges. - /// - TessellateWallEdges = 0x01, - - /// - /// Tessellate the edges between areas. - /// - TessellateAreaEdges = 0x02 - } -} diff --git a/critterai/.svn/pristine/20/20c8433b80716839c0e7c9478fdb3b6c46278175.svn-base b/critterai/.svn/pristine/20/20c8433b80716839c0e7c9478fdb3b6c46278175.svn-base deleted file mode 100644 index 9e422de9..00000000 Binary files a/critterai/.svn/pristine/20/20c8433b80716839c0e7c9478fdb3b6c46278175.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/20/20fbe71e4346bc26f4ae0fdf5ad86d9e255394c9.svn-base b/critterai/.svn/pristine/20/20fbe71e4346bc26f4ae0fdf5ad86d9e255394c9.svn-base deleted file mode 100644 index b9615d40..00000000 --- a/critterai/.svn/pristine/20/20fbe71e4346bc26f4ae0fdf5ad86d9e255394c9.svn-base +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nav; -using org.critterai.geom; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Represents a set of off-mesh connections used during construction of a navigation mesh. - /// - /// - public sealed class ConnectionSet - { - private readonly Vector3[] verts; - private readonly float[] radii; - private readonly byte[] dirs; - private readonly byte[] areas; - private readonly ushort[] flags; - private readonly uint[] userIds; - - private ConnectionSet(Vector3[] verts, float[] radii - , byte[] dirs, byte[] areas, ushort[] flags, uint[] userIds) - { - this.verts = verts; - this.radii = radii; - this.dirs = dirs; - this.areas = areas; - this.flags = flags; - this.userIds = userIds; - } - - private ConnectionSet() - { - verts = new Vector3[0]; - radii = new float[0]; - dirs = new byte[0]; - areas = new byte[0]; - flags = new ushort[0]; - userIds = new uint[0]; - } - - /// - /// The number of connections in the set. [Limit: >= 0] - /// - public int Count { get { return radii.Length; } } - - /// - /// Gets the connections whose start vertex is within the specified bounds. - /// - /// - /// - /// The out parameters will be null if the return result is zero. - /// - /// - /// The minimum x-axis bounds. - /// The minimum z-axis bounds. - /// The maximum x-axis bounds. - /// The maximum z-axis bounds. - /// The connection vertices. [(start, end) * connCount] - /// The connection radii. [Length: connCount] - /// The connection direction flags. [Length: connCount] - /// The connection areas. [Length: connCount] - /// The connection flags. [Length: connCount] - /// The connection user ids. [Length: connCount] - /// The number of connection returned. - public int GetConnections(float xmin, float zmin, float xmax, float zmax - , out Vector3[] rverts, out float[] rradii - , out byte[] rdirs, out byte[] rareas, out ushort[] rflags, out uint[] ruserIds) - { - rverts = null; - rradii = null; - rdirs = null; - rareas = null; - rflags = null; - ruserIds = null; - - if (radii.Length == 0) - return 0; - - List rlverts = new List(); - List rlradii = new List(); - List rldirs = new List(); - List rlareas = new List(); - List rlflags = new List(); - List rluserIds = new List(); - - for (int i = 0; i < radii.Length; i++) - { - Vector3 v = verts[i * 2 + 0]; - if (Rectangle2.Contains(xmin, zmin, xmax, zmax, v.x, v.z)) - { - rlverts.Add(v); - rlverts.Add(verts[i * 2 + 1]); - - rlradii.Add(radii[i]); - rldirs.Add(dirs[i]); - rlareas.Add(areas[i]); - rlflags.Add(flags[i]); - rluserIds.Add(userIds[i]); - } - } - - if (rlradii.Count == 0) - return 0; - - rverts = rlverts.ToArray(); - rradii = rlradii.ToArray(); - rdirs = rldirs.ToArray(); - rareas = rlareas.ToArray(); - rflags = rlflags.ToArray(); - ruserIds = rluserIds.ToArray(); - - return rradii.Length; - } - - /// - /// Creates an empty connection set. ( == 0) - /// - /// An empty connection set. - public static ConnectionSet CreateEmpty() - { - return new ConnectionSet(); - } - - /// - /// Creates a connection set guarenteed to be thread-safe, immutable, and content valid. - /// - /// - /// - /// This method performs a full validation of the structure and content of the - /// connection data. - /// - /// - /// This method cannot be used to create an empty set. Attempting to do so will - /// return null. Use instead. - /// - /// - /// A connection set, or null on failure. - /// The connection vertices. [(start, end) * connCount] - /// The connection radii. [Length: connCount] - /// The connection direction flags. [Length: connCount] - /// The connection areas. [Length: connCount] - /// The connection flags. [Length: connCount] - /// The connection user ids. [Length: connCount] - /// The connection set. - public static ConnectionSet Create(Vector3[] verts, float[] radii - , byte[] dirs, byte[] areas, ushort[] flags, uint[] userIds) - { - if (IsValid(verts, radii, dirs, areas, flags, userIds)) - { - return new ConnectionSet((Vector3[])verts.Clone() - , (float[])radii.Clone() - , (byte[])dirs.Clone() - , (byte[])areas.Clone() - , (ushort[])flags.Clone() - , (uint[])userIds.Clone()); - } - return null; - } - - /// - /// Creates a connection set. - /// - /// - /// - /// Connection sets created using this method are not guarenteed to be valid or - /// safe for threaded builds. - /// - /// - /// The generated connection set will directly reference the construction - /// parameters. - /// - /// - /// The connection vertices. [(start, end) * connCount] - /// The connection radii. [Length: connCount] - /// The connection direction flags. [Length: connCount] - /// The connection areas. [Length: connCount] - /// The connection flags. [Length: connCount] - /// The connection user ids. [Length: connCount] - /// An unsafe connection set. - public static ConnectionSet UnsafeCreate(Vector3[] verts, float[] radii - , byte[] dirs, byte[] areas, ushort[] flags, uint[] userIds) - { - return new ConnectionSet(verts - , radii - , dirs - , areas - , flags - , userIds); - } - - /// - /// Validates the structure and content of the connection data. - /// - /// - /// - /// This is the same validation performed by the safe creation method. - /// - /// - /// Structural checks include null array and length checks. - /// - /// - /// The connection vertices. [(start, end) * connCount] - /// The connection radii. [Length: connCount] - /// The connection direction flags. [Length: connCount] - /// The connection areas. [Length: connCount] - /// The connection flags. [Length: connCount] - /// The connection user ids. [Length: connCount] - /// True if the structure and content of the parameters is valid. - public static bool IsValid(Vector3[] verts, float[] radii - , byte[] dirs, byte[] areas, ushort[] flags, uint[] userIds) - { - // Will fail is there are zero connections. - - if (verts == null - || radii == null - || dirs == null - || areas == null - || flags == null - || userIds == null) - { - return false; - } - - if ((verts.Length < 2 || verts.Length % 2 != 0) - || radii.Length != verts.Length / 2 - || dirs.Length != radii.Length - || areas.Length != radii.Length - || flags.Length != radii.Length - || userIds.Length != radii.Length) - { - return false; - } - - foreach (float val in radii) - { - if (val < MathUtil.Epsilon) - return false; - } - - foreach (byte val in dirs) - { - if (val > 1) - return false; - } - - foreach (byte val in areas) - { - if (val > Navmesh.MaxArea) - return false; - } - - return true; - } - } -} diff --git a/critterai/.svn/pristine/21/21145285e9e5021f5b644c3244139c72db5b80dc.svn-base b/critterai/.svn/pristine/21/21145285e9e5021f5b644c3244139c72db5b80dc.svn-base deleted file mode 100644 index bcedc448..00000000 Binary files a/critterai/.svn/pristine/21/21145285e9e5021f5b644c3244139c72db5b80dc.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/21/2149bf52357c42b1174e4437101b71df66723ec5.svn-base b/critterai/.svn/pristine/21/2149bf52357c42b1174e4437101b71df66723ec5.svn-base deleted file mode 100644 index 119c4d63..00000000 --- a/critterai/.svn/pristine/21/2149bf52357c42b1174e4437101b71df66723ec5.svn-base +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(AreaMarkerCompiler))] -public sealed class AreaMarkerCompilerEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - AreaMarkerCompiler targ = (AreaMarkerCompiler)target; - - EditorGUILayout.Separator(); - - GUILayout.Label("Priority: " + targ.Priority); - - EditorGUILayout.Separator(); - - GUILayout.Box("Input Build Processor\n\n" - + "Loads and compiles the " + typeof(NMGenAreaMarker).Name + " components in the scene." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Compiler : Area Marker" - , false, NMBEditorUtil.CompilerGroup)] - static void CreateAsset() - { - AreaMarkerCompiler item = - EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/21/21a5ad7d8a4c842445531685779c6bf7639f2fe5.svn-base b/critterai/.svn/pristine/21/21a5ad7d8a4c842445531685779c6bf7639f2fe5.svn-base deleted file mode 100644 index de7b159b..00000000 --- a/critterai/.svn/pristine/21/21a5ad7d8a4c842445531685779c6bf7639f2fe5.svn-base +++ /dev/null @@ -1,164 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include "DetourNode.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include "DetourCommon.h" -#include - -inline unsigned int dtHashRef(dtPolyRef a) -{ - a += ~(a<<15); - a ^= (a>>10); - a += (a<<3); - a ^= (a>>6); - a += ~(a<<11); - a ^= (a>>16); - return (unsigned int)a; -} - -////////////////////////////////////////////////////////////////////////////////////////// -dtNodePool::dtNodePool(int maxNodes, int hashSize) : - m_nodes(0), - m_first(0), - m_next(0), - m_maxNodes(maxNodes), - m_hashSize(hashSize), - m_nodeCount(0) -{ - dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize); - dtAssert(m_maxNodes > 0); - - m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM); - m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM); - m_first = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*hashSize, DT_ALLOC_PERM); - - dtAssert(m_nodes); - dtAssert(m_next); - dtAssert(m_first); - - memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize); - memset(m_next, 0xff, sizeof(dtNodeIndex)*m_maxNodes); -} - -dtNodePool::~dtNodePool() -{ - dtFree(m_nodes); - dtFree(m_next); - dtFree(m_first); -} - -void dtNodePool::clear() -{ - memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize); - m_nodeCount = 0; -} - -dtNode* dtNodePool::findNode(dtPolyRef id) -{ - unsigned int bucket = dtHashRef(id) & (m_hashSize-1); - dtNodeIndex i = m_first[bucket]; - while (i != DT_NULL_IDX) - { - if (m_nodes[i].id == id) - return &m_nodes[i]; - i = m_next[i]; - } - return 0; -} - -dtNode* dtNodePool::getNode(dtPolyRef id) -{ - unsigned int bucket = dtHashRef(id) & (m_hashSize-1); - dtNodeIndex i = m_first[bucket]; - dtNode* node = 0; - while (i != DT_NULL_IDX) - { - if (m_nodes[i].id == id) - return &m_nodes[i]; - i = m_next[i]; - } - - if (m_nodeCount >= m_maxNodes) - return 0; - - i = (dtNodeIndex)m_nodeCount; - m_nodeCount++; - - // Init node - node = &m_nodes[i]; - node->pidx = 0; - node->cost = 0; - node->total = 0; - node->id = id; - node->flags = 0; - - m_next[i] = m_first[bucket]; - m_first[bucket] = i; - - return node; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -dtNodeQueue::dtNodeQueue(int n) : - m_heap(0), - m_capacity(n), - m_size(0) -{ - dtAssert(m_capacity > 0); - - m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM); - dtAssert(m_heap); -} - -dtNodeQueue::~dtNodeQueue() -{ - dtFree(m_heap); -} - -void dtNodeQueue::bubbleUp(int i, dtNode* node) -{ - int parent = (i-1)/2; - // note: (index > 0) means there is a parent - while ((i > 0) && (m_heap[parent]->total > node->total)) - { - m_heap[i] = m_heap[parent]; - i = parent; - parent = (i-1)/2; - } - m_heap[i] = node; -} - -void dtNodeQueue::trickleDown(int i, dtNode* node) -{ - int child = (i*2)+1; - while (child < m_size) - { - if (((child+1) < m_size) && - (m_heap[child]->total > m_heap[child+1]->total)) - { - child++; - } - m_heap[i] = m_heap[child]; - i = child; - child = (i*2)+1; - } - bubbleUp(i, node); -} diff --git a/critterai/.svn/pristine/21/21a6d4c8570b789d89b64b756a50460e71f603cd.svn-base b/critterai/.svn/pristine/21/21a6d4c8570b789d89b64b756a50460e71f603cd.svn-base deleted file mode 100644 index aaf69443..00000000 --- a/critterai/.svn/pristine/21/21a6d4c8570b789d89b64b756a50460e71f603cd.svn-base +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using System.Collections.Generic; -using org.critterai.nav; - -/// -/// Global navigation settings. (Editor Only) -/// -/// -/// The values in this class can only be edited via the Unity Editor. -/// -[System.Serializable] -public sealed class CAINavEditorSettings - : ScriptableObject -{ - /// - /// The well known name for . - /// - public const string NotWalkable = "Not Walkable"; - - /// - /// The well known name for . - /// - public const string Default = "Default"; - - /// - /// The area name for areas with no defined well known name. - /// - public const string Undefined = ""; - - /// - /// A value indicating that the area is unknown. - /// - /// - public const byte UnknownArea = Navmesh.MaxArea + 1; - - [SerializeField] - internal string[] areaNames; - - [SerializeField] - internal string[] flagNames; - - [SerializeField] - internal string[] avoidanceNames; - - void OnEnable() - { - if (areaNames == null || areaNames.Length == 0) - // First startup. - Reset(); - } - - /// - /// Resets the settings to the default state. - /// - public void Reset() - { - areaNames = new string[Navmesh.MaxArea + 1]; - - for (int i = 1; i < Navmesh.MaxArea; i++) - { - areaNames[i] = Undefined; - } - - areaNames[Navmesh.NullArea] = NotWalkable; - areaNames[Navmesh.MaxArea] = Default; - areaNames[Navmesh.MaxArea - 1] = "Water"; - - flagNames = new string[16]; - - flagNames[0] = Default; - flagNames[1] = "Jump"; - flagNames[2] = "Swim"; - flagNames[3] = "Blocked"; - - for (int i = 4; i < flagNames.Length; i++) - { - flagNames[i] = string.Format("Flag 0x{0:X}", 1 << i); - } - - avoidanceNames = new string[CrowdManager.MaxAvoidanceParams]; - - avoidanceNames[0] = "Low"; - avoidanceNames[1] = "Medium"; - avoidanceNames[2] = "Good"; - avoidanceNames[3] = "High"; - - for (int i = 4; i < avoidanceNames.Length; i++) - { - avoidanceNames[i] = "Quality " + i; - } - } - - /// - /// Gets a clone of the area names. - /// - /// - /// - /// This is the full array, including the values. - /// - /// - /// A clone of the area names. [Length: + 1] - public string[] GetAreaNames() - { - return (string[])areaNames.Clone(); - } - - /// - /// Gets the area associated with the well known area name. - /// - /// The well known area name. - /// Gets the area associated with the well known name, or - /// if the name is invalid. - public byte GetArea(string name) - { - if (name == NotWalkable) - return Navmesh.NullArea; - - for (int i = 0; i < areaNames.Length; i++) - { - if (areaNames[i] == name) - return (byte)i; - } - - return UnknownArea; - } - - /// - /// Gets a clone of the well known names for flags, indexed on the flag's bit. - /// - /// - /// - /// All flags have a well known name. - /// - /// - /// The order of the names match the order of the flags. So the name at index 5 is the name - /// for flag (1 << 5). - /// - /// - /// A clone of the flag names. [Length: 16] - public string[] GetFlagNames() - { - return (string[])flagNames.Clone(); - } - - /// - /// Gets a clone of the well known crowd avoidance names. - /// - /// - /// A clone of the avoidance names. [Length: ] - /// - public string[] GetAvoidanceNames() - { - return (string[])avoidanceNames.Clone(); - } -} diff --git a/critterai/.svn/pristine/22/22eca79d8a94bb3b033450b772d2a65cc2985e4b.svn-base b/critterai/.svn/pristine/22/22eca79d8a94bb3b033450b772d2a65cc2985e4b.svn-base deleted file mode 100644 index 5b4336bc..00000000 --- a/critterai/.svn/pristine/22/22eca79d8a94bb3b033450b772d2a65cc2985e4b.svn-base +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" -#include "RecastAlloc.h" - -extern "C" -{ - EXPORT_API bool nmcsBuildSet(nmgBuildContext* ctx - , rcCompactHeightfield* chf - , const float maxError - , const int maxEdgeLen - , rcContourSet* cset - , const int flags) - { - if (!ctx || !chf || !cset) - return false; - - return rcBuildContours(ctx - , *chf - , maxError - , maxEdgeLen - , *cset - , flags); - } - - EXPORT_API void nmcsFreeSetData(rcContourSet* cset) - { - if (!cset || !cset->conts) - return; - - for (int i = 0; i < cset->nconts; ++i) - { - rcFree(cset->conts[i].verts); - rcFree(cset->conts[i].rverts); - } - - rcFree(cset->conts); - - cset->ch = 0; - cset->borderSize = 0; - cset->conts = 0; - cset->cs = 0; - cset->height = 0; - cset->nconts = 0; - cset->width = 0; - - memset(&cset->bmin, 0, sizeof(float) * 6); - } - - EXPORT_API bool nmcsGetContour(const rcContourSet* cset - , const int index - , rcContour* result) - { - if (!cset - || !result - || index < 0 - || index >= cset->nconts) - return false; - - memcpy(result, &cset->conts[index], sizeof(rcContour)); - - return true; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/23/2354f0279c6c0d6caeb65d164764f185b1971052.svn-base b/critterai/.svn/pristine/23/2354f0279c6c0d6caeb65d164764f185b1971052.svn-base deleted file mode 100644 index 86520995..00000000 --- a/critterai/.svn/pristine/23/2354f0279c6c0d6caeb65d164764f185b1971052.svn-base +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal static class ControlUtil - { - public const float MarginSize = 5; - public const float ButtonAreaWidth = 150; - - public static Color StandardHighlight - { - get { return new Color(0.43f, 0.77f, 0.13f); } // Green - } - - public static Color SelectionColor - { - get { return new Color(0.84f, 0.75f, 0.08f); } // Yellow - } - - private static GUIStyle mHighlightedButton; - - public static GUIStyle HighlightedButton - { - get - { - if (mHighlightedButton == null) - { - mHighlightedButton = new GUIStyle(GUI.skin.button); - mHighlightedButton.normal.textColor = StandardHighlight; - } - return mHighlightedButton; - } - } - - public static bool OnGUIStandardButtons(ControlContext context - , DebugViewContext debugContext - , bool resetAllowed) - { - NavmeshBuild build = context.Build; - - if (!build) - return false; - - TileBuildData tdata = build.BuildData; - - GUILayout.FlexibleSpace(); - - // Note: It is assumed that you should't get any debug display options unless - // you can reset the build. So they are inside this condition. - if (resetAllowed) - { - if (build.BuildState == NavmeshBuildState.Buildable || build.HasInputData) - // One or more debug display options are allowed. - GUILayout.Label("Show"); - - // Always call these. - debugContext.OnGUIMeshDisplayOptions(); - debugContext.OnGUIDebugExtras(); - - GUILayout.Space(MarginSize); - - GUIStyle style = (tdata != null && tdata.NeedsBakingCount() == 0) - ? ControlUtil.HighlightedButton : GUI.skin.button; - - return OnGUIResetButton(context, debugContext, style); - } - - return false; - } - - public static bool OnGUIResetButton(ControlContext context, DebugViewContext debug, GUIStyle style) - { - if (GUILayout.Button("Exit Build", style)) - { - context.AbortAllReqests("User requested build reset."); - context.Build.ResetBuild(); // Abort requests first! - debug.NeedsRepaint = true; - return true; - } - GUILayout.Space(MarginSize); - return false; - } - - public static void BeginButtonArea(Rect area) - { - GUILayout.BeginArea(area, GUI.skin.box); - } - - public static void EndButtonArea() - { - GUILayout.EndArea(); - } - } -} diff --git a/critterai/.svn/pristine/24/24771ea997207f9ca691450d71ee7543e22ffc9e.svn-base b/critterai/.svn/pristine/24/24771ea997207f9ca691450d71ee7543e22ffc9e.svn-base deleted file mode 100644 index f549bd56..00000000 --- a/critterai/.svn/pristine/24/24771ea997207f9ca691450d71ee7543e22ffc9e.svn-base +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - In order to use the advanced navigation mesh build features you will need to understand the core NMGen build process, - and in order to understand that process you'll need to understand heightfields. There are two types of heightfields: - - voxel - http://en.wikipedia.org/wiki/Voxel - _blank - - field, and vertex fields. Voxel fields include - T:org.critterai.nmgen.Heightfield and - T:org.critterai.nmgen.CompactHeightfield objects. - Vertext fields include T:org.critterai.nmgen.ContourSet and - PolyMesh objects. - - - - -
- - Basic Heightfield Structure - - - - - Consider an AABB at an arbitrary location in - - euclidean space - http://en.wikipedia.org/wiki/Euclidean_space - _blank - . Its bounds are defined by a minimum and maximum vertex. - - - - - - Now slice the box into vertical columns of uniform width and depth (XZCellSize). The columns make up a grid. - - - - - - Now slice the columns in uniform increments up the height axis (YCellSize), - breaking the columns into small axis-aligned boxes. The boxes represent a voxel field. - The vertices at the eight corners of the boxes represent a vertex field. - - - - - - Vertex fields are fairly easy to understand. They are simply a way of representing vertices laid out in a grid pattern. - But voxel fields require a bit more explanation... - - - - -
- -
- - The Solid Heightfield - - - - - In this documentation, the term voxel is usually discarded in favor of - span because spans are how voxel information is compressed by NMGen objects. - - - - Consider a column of voxels. The area defined by each voxel is either solid, - representing obstructed space, or open, representing space that does not contain any - obstructions. - - - - - - We merge the contiguous solid voxels within the column and we get a span of solid voxels. - - - - - - These solid spans, represented by the - T:org.critterai.nmgen.HeightfieldSpan structure, - are combined to form a - T:org.critterai.nmgen.Heightfield - representing obstructed space. - - - - - - -
- -
- - The Open Compact Heightfield - - - - - We don't only care about solid space. Many algorithms operate on the space above solid spans. - For navigation mesh generation this is the most important part of solid space, its upper surface. - Open spans represent this space. - - - - It is important to note that this is not a simple inversion of the solid space. If an - open heightfield column does not contain any solid spans, then it doesn't have any open spans. - Also, the area below the lowest solid span is ignored. An open span extends from the top of a solid - span to the bottom of the next higher solid span in the column. (Or to "infinity" if there - is no higher solid span.) - - - - - - - Though it may not be obvious at first glance, this example is the open space representation of the previous example. - Three open spans are fully visualized. - - - - - - - - - The open spans, represented by the T:org.critterai.nmgen.CompactSpan structure, - are combined to form a T:org.critterai.nmgen.CompactHeightfield representing open space. - - - - -
- - - - T:org.critterai.nmgen.Heightfield - T:org.critterai.nmgen.CompactHeightfield - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/25/2584e8fa0597f494189953e82bc8e2359fcf4388.svn-base b/critterai/.svn/pristine/25/2584e8fa0597f494189953e82bc8e2359fcf4388.svn-base deleted file mode 100644 index a00b4343..00000000 --- a/critterai/.svn/pristine/25/2584e8fa0597f494189953e82bc8e2359fcf4388.svn-base +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.Hashtable; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Provides a representation of the open (unobstructed) space above solid - * surfaces in a voxel field. - *

For this type of heightfield, spans represent the floor and ceiling - * of the open spaces.

- *

WARNING: This class has very little protections build into it. It - * is basically an uncontrolled data structure with convenience functions.

- *

- * - *

- * @see Introduction to Height Fields - */ -public final class OpenHeightfield - extends BoundedField -{ - /* - * Recast Reference: rcCompactHeightfield in Recast.h - * The internal structure of this class is very different from Recast. - * See: http://www.critterai.org/nmgen_diffs for the reason. - */ - - /** - * An iterator that will iterate through all spans within a - * height field. (Not just the base spans.) - *

Behavior of the iterator is undefined if the interator's source - * is changed during iteration.

- * The iterator returned by {@link OpenHeightfield#dataIterator()}. - */ - public final class OpenHeightFieldIterator - implements Iterator - { - - // See reset() for initialization information. - - private int mNextWidth; - private int mNextDepth; - private OpenHeightSpan mNext; - - private int mLastWidth; - private int mLastDepth; - - /** - * Constructor. - */ - private OpenHeightFieldIterator() - { - reset(); - } - - /** - * The depth index of the last span returned by {@link #next()} - * @return The depth index of the last span returned by {@link #next()} - */ - public int depthIndex() { return mLastDepth; } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasNext() - { - return (mNext != null); - } - - /** - * {@inheritDoc} - */ - @Override - public OpenHeightSpan next() - { - if (mNext == null) - throw new NoSuchElementException(); - // Select value cursor. - OpenHeightSpan next = mNext; - mLastWidth = mNextWidth; - mLastDepth = mNextDepth; - // Move the cursor to the next value. - moveToNext(); - return next; - } - - /** - * {@inheritDoc} - * This operation is not supported. - */ - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } - - /** - * Resets the iterator so that it can be re-used. - */ - public void reset() - { - mNextWidth = 0; - mNextDepth = 0; - mNext = null; - mLastWidth = 0; - mLastDepth = 0; - moveToNext(); - } - - /** - * The width index of the last span returned by {@link #next()} - * @return The width index of the last span returned by {@link #next()} - */ - public int widthIndex() { return mLastWidth; } - - /** - * This operation is called in order to move the - * cursor to the next span after the {@link #next()} operation - * has selected its span to return. - */ - private void moveToNext() - { - if (mNext != null) - { - // There is a current cell selected. - if (mNext.next() != null) - { - // The current cell has a next. Select it - mNext = mNext.next(); - return; - } - else mNextWidth++; // Move to next cell. - } - // Need to find the next grid location that contains a span. - // Loop until one is found or no more are available. - for (int depthIndex = mNextDepth - ; depthIndex < depth() - ; depthIndex++) - { - for (int widthIndex = mNextWidth - ; widthIndex < width() - ; widthIndex++) - { - OpenHeightSpan span = - mSpans.get(gridIndex(widthIndex, depthIndex)); - if (span != null) - { - // A span was found. Set the cursor to it. - mNext = span; - mNextWidth = widthIndex; - mNextDepth = depthIndex; - return; - } - } - mNextWidth = 0; - } - // If got here then there are no more spans. - // Set values to indicate the end of iteration. - mNext = null; - mNextDepth = -1; - mNextWidth = -1; - } - } - - /** - * Indicates that a value is unknown and need to be derived. - */ - private static final int UNKNOWN = -1; - private int mSpanCount = 0; - - // These next fields are derived only when the value is needed. - - private int mRegionCount = 0; - - /** - * The maximum distance a span is from a border span. - */ - private int mMaxBorderDistance = UNKNOWN; - - /** - * The minimum distance a span is from a border span. - */ - private int mMinBorderDistance = UNKNOWN; - - /** - * Key = Grid index from {@link #gridIndex(int, int)}. - * Value = The first (lowest) span in the grid column. - */ - private final Hashtable mSpans = - new Hashtable(); - - /** - * Constructor - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the base - * of the field.) - * @param cellHeight The height increment of the field. - * @throws IllegalArgumentException If the bounds are null or the - * wrong size. - */ - public OpenHeightfield(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize, float cellHeight) - throws IllegalArgumentException - { - super(gridBoundsMin, gridBoundsMax, cellSize, cellHeight); - } - - /** - * Puts the span at the grid location, replacing any spans already at the - * location. The added span becomes the new base span for the location. - *

WARNING: The span count must be manually updated to reflect changes - * in span count

- *

Behavior is undefined if the indices are invalid.

- * @param widthIndex The width index of the grid location to add the - * span to. (0 <= value < {@link #width()}) - * @param depthIndex The depth index of the grid location to add the - * span to. (0 <= value < {@link #depth()}) - * @param span The span to put at the grid location. - * @return The original base span that was in the grid location, or null - * if there was no pre-existing span in the location. - */ - public OpenHeightSpan addData(int widthIndex - , int depthIndex - , OpenHeightSpan span) - { - return mSpans.put(gridIndex(widthIndex, depthIndex), span); - } - - /** - * Resets the border distance values so they will - * be recacluated the next time they are needed. - */ - public void clearBorderDistanceBounds() - { - mMaxBorderDistance = UNKNOWN; - mMinBorderDistance = UNKNOWN; - } - - /** - * An iterator for the heightfields spans. - * The returned iterator does not support the - * {@link Iterator#remove()} operation. - */ - public OpenHeightFieldIterator dataIterator() - { - return this.new OpenHeightFieldIterator(); - } - - /** - * Retrieves the base (lowest) grid for the specified grid location. - *

Behavior is undefined if the indices are invalid.

- * @param widthIndex The width index of the grid location the span is - * located in. (0 <= value < {@link #width()}) - * @param depthIndex The depth index of the grid location the span is - * located in. (0 <= value < {@link #depth()}) - * @return The base (lowest) span for the specified grid location. Null - * if there is no data for the grid location. - */ - public OpenHeightSpan getData(int widthIndex, int depthIndex) - { - return mSpans.get(gridIndex(widthIndex, depthIndex)); - } - - /** - * Increments the span count. - *

IMPORTANT: There is no automatic span count updates. Span count - * must be managed manually.

- * @return The new span count. - */ - public int incrementSpanCount() { return ++mSpanCount; } - - /** - * The maximum distance a span in the heightfield is from its - * nearest border. - * @return The maximum distance a span in the heightfield is from - * its nearest border. - */ - public int maxBorderDistance() - { - if (mMaxBorderDistance == UNKNOWN) - calcBorderDistanceBounds(); - return mMaxBorderDistance; - } - - /** - * The minimum distance a span in the height field is from its nearest - * border. (Usually zero. But can depend on the generation method.) - * @return The minimum distance a span in the height field is from its - * nearest border. - */ - public int minBorderDistance() - { - if (mMinBorderDistance == UNKNOWN) - calcBorderDistanceBounds(); - return mMinBorderDistance; - } - - /** - * Sends a tab delimited table of the distance field values to - * standard out. - *

Only the lowest spans in the field are output. So this operation - * is really only suitable for simple tests on fields - * that don't contain overlapping spans.

- *

Columns: Width
- * Rows: Depth

- */ - public void printDistanceField() - { - System.out.println("Distance Field (Spans: " + mSpanCount + ")"); - final OpenHeightFieldIterator iter = new OpenHeightFieldIterator(); - int depth = -1; - System.out.print("\t"); - for (int width = 0; width < width(); width++) - System.out.print(width + "\t"); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (iter.depthIndex() != depth) - System.out.print("\n" + ++depth + "\t"); - System.out.print(span.distanceToBorder() + "\t"); - } - System.out.println(); - } - - /** - * Sends a tab delimited table of the region ID values to standard out. - *

Only the lowest spans in the field are output. So this operation - * is really only suitable for simple tests on fields - * that don't contain overlapping spans.

- *

Columns: Width
- * Rows: Depth

- */ - public void printRegionField() - { - System.out.println("Distance Field (Spans: " + mSpanCount - + ", Regions: " + mRegionCount + ")"); - System.out.print("\t"); - for (int width = 0; width < width(); width++) - System.out.print(width + "\t"); - for (int iDepth = 0; iDepth < depth(); iDepth++) - { - System.out.print("\n" + iDepth + "\t"); - for (int iWidth = 0; iWidth < width(); iWidth++) - { - OpenHeightSpan span = getData(iWidth, iDepth); - if (span == null) - System.out.print(" \t"); - else - System.out.print(span.regionID() + "\t"); - } - } - System.out.println(); - } - - /** - * The number of regions in the height field. - *

Includes the null region. So unless all spans are in the - * null region, this value will be >= 2. (E.g. The null region and at - * least one other region.)

- */ - public int regionCount() { return mRegionCount; } - - /** - * Sets the region count. - *

The region count is expected to be zero based with the zero - * region representing the null region. So the region count is - * expected to be one more that the maximum region value. E.g. If the - * highest region value is 14, then the region count is 15.

- *

IMPORTANT: There is no automatic region count management. - * Region count must be managed manually.

- * @param value The new region count. - */ - public void setRegionCount(int value) { mRegionCount = value; } - - /** - * The number of spans in the heightfield. - *

A value of zero indicates an empty heightfield.

- */ - public int spanCount() { return mSpanCount; } - - /** - * Calculates the min/max distance a span in the field is from it - * nearest border. Allows on-demand calculation of this information. - */ - private void calcBorderDistanceBounds() - { - if (mSpanCount == 0) - return; - - // Default the values. - mMinBorderDistance = Integer.MAX_VALUE; - mMaxBorderDistance = UNKNOWN; - - // Iterate through all spans and reset the values if new min/max's are - // found. - OpenHeightFieldIterator iter = - this.new OpenHeightFieldIterator(); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - mMinBorderDistance = Math.min(mMinBorderDistance - , span.distanceToBorder()); - mMaxBorderDistance = Math.max(mMaxBorderDistance - , span.distanceToBorder()); - } - if (mMinBorderDistance == Integer.MAX_VALUE) - // There ware a problem locating the maximum. - // So set it back to unknown. - mMinBorderDistance = UNKNOWN; - - } - -} diff --git a/critterai/.svn/pristine/25/25e5b9dda9296a0965c56560b1027411184a46e7.svn-base b/critterai/.svn/pristine/25/25e5b9dda9296a0965c56560b1027411184a46e7.svn-base deleted file mode 100644 index 0b101914..00000000 --- a/critterai/.svn/pristine/25/25e5b9dda9296a0965c56560b1027411184a46e7.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nmbuild-extras-u3d")] -[assembly: AssemblyDescription("Scene related navigation mesh build extensions for Unity.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/27/2710400a3dfe0a28515a17753b0bcd7da75cf8ff.svn-base b/critterai/.svn/pristine/27/2710400a3dfe0a28515a17753b0bcd7da75cf8ff.svn-base deleted file mode 100644 index eae54bcf..00000000 --- a/critterai/.svn/pristine/27/2710400a3dfe0a28515a17753b0bcd7da75cf8ff.svn-base +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.nmgen.rcn -{ - internal static class BuildContextEx - { - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr nmbcAllocateContext(bool logEnabled); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmbcFreeContext(IntPtr context); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmbcGetLogEnabled(IntPtr context); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmbcEnableLog(IntPtr context, bool state); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmbcResetLog(IntPtr context); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int nmbcGetMessageCount(IntPtr context); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int nmbcGetMessagePool(IntPtr context - , [In, Out] byte[] messageBuffer - , int bufferSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmbcLog(IntPtr ctx - , [In, MarshalAs(UnmanagedType.LPStr)] string message); - - // Note: It is ok for the method prefix to be different. - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmgTestContext(IntPtr ctx, int count); - - } -} diff --git a/critterai/.svn/pristine/27/277819cfd24290eb539033c5f75b228593eedbae.svn-base b/critterai/.svn/pristine/27/277819cfd24290eb539033c5f75b228593eedbae.svn-base deleted file mode 100644 index dcbd06ca..00000000 --- a/critterai/.svn/pristine/27/277819cfd24290eb539033c5f75b228593eedbae.svn-base +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CAI_DETOURNAVMESHEX_H -#define CAI_DETOURNAVMESHEX_H - -#include "DetourEx.h" - -struct rcnTileData -{ - unsigned char* data; - int dataSize; - bool isOwned; -}; - -#endif \ No newline at end of file diff --git a/critterai/.svn/pristine/27/277ef0751488cefc126e71e7545c1367f6aeeae8.svn-base b/critterai/.svn/pristine/27/277ef0751488cefc126e71e7545c1367f6aeeae8.svn-base deleted file mode 100644 index 082a7234..00000000 --- a/critterai/.svn/pristine/27/277ef0751488cefc126e71e7545c1367f6aeeae8.svn-base +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav.rcn -{ - internal static class NavmeshQueryEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnqBuildDTNavQuery(IntPtr navmesh - , int maxNodes - , ref IntPtr resultQuery); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtnqFree(ref IntPtr query); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqGetPolyWallSegments(IntPtr query - , uint polyRef - , IntPtr filter - , [In, Out] Vector3[] segmentVerts - , [In, Out] uint[] segmentPolyRefs - , ref int segmentCount - , int maxSegments); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindNearestPoly(IntPtr query - , [In] ref Vector3 position - , [In] ref Vector3 extents - , IntPtr filter - , ref NavmeshPoint nearest); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqClosestPointOnPoly(IntPtr query - , uint polyRef - , [In] ref Vector3 position - , ref Vector3 resultPoint); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqClosestPointOnPolyBoundary(IntPtr query - , uint polyRef - , [In] ref Vector3 position - , [In] ref Vector3 resultPoint); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqQueryPolygons(IntPtr query - , ref Vector3 position - , ref Vector3 extents - , IntPtr filter - , [In, Out] uint[] resultPolyRefs - , ref int resultCount - , int maxResult); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindPolysAroundCircle(IntPtr query - , uint startPolyRef - , [In] ref Vector3 position - , float radius - , IntPtr filter - , [In, Out] uint[] resultPolyRefs // Optional - , [In, Out] uint[] resultParentRefs // Optional - , [In, Out] float[] resultCosts // Optional - , ref int resultCount - , int maxResult); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindPolysAroundShape(IntPtr query - , uint startPolyRef - , [In] Vector3[] verts - , int vertCount - , IntPtr filter - , [In, Out] uint[] resultPolyRefs - , [In, Out] uint[] resultParentRefs - , [In, Out] float[] resultCosts - , ref int resultCount - , int maxResult); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindLocalNeighbourhood(IntPtr query - , uint startPolyRef - , [In] ref Vector3 position - , float radius - , IntPtr filter - , [In, Out] uint[] resultPolyRefs - , [In, Out] uint[] resultParentRefs - , ref int resultCount - , int maxResult); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqGetPolyHeight(IntPtr query - , NavmeshPoint position - , ref float height); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindDistanceToWall(IntPtr query - , NavmeshPoint position - , float searchRadius - , IntPtr filter - , ref float distance - , ref Vector3 closestPoint - , ref Vector3 normal); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindPath(IntPtr query - , NavmeshPoint startPosition - , NavmeshPoint endPosition - , IntPtr filter - , [In, Out] uint[] resultPath - , ref int pathCount - , int maxPath); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindPathExt(IntPtr query - , ref NavmeshPoint startPosition - , ref NavmeshPoint endPosition - , [In] ref Vector3 extents - , IntPtr filter - , [In, Out] uint[] resultPath - , ref int pathCount - , int maxPath); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtqIsInClosedList(IntPtr query - , uint polyRef); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtqIsValidPolyRef(IntPtr query - , uint polyRef - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqRaycast(IntPtr query - , NavmeshPoint startPosition - , [In] ref Vector3 endPosition - , IntPtr filter - , ref float hitParameter - , ref Vector3 hitNormal - , [In, Out] uint[] path - , ref int pathCount - , int maxPath); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindStraightPath(IntPtr query - , [In] ref Vector3 startPosition - , [In] ref Vector3 endPosition - , [In] uint[] path - , int pathStart - , int pathSize - , [In, Out] Vector3[] straightPathPoints - , [In, Out] WaypointFlag[] straightPathFlags - , [In, Out] uint[] straightPathRefs - , ref int straightPathCount - , int maxStraightPath); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqMoveAlongSurface(IntPtr query - , NavmeshPoint startPosition - , [In] ref Vector3 endPosition - , IntPtr filter - , ref Vector3 resultPosition - , [In, Out] uint[] visitedPolyRefs - , ref int visitedCount - , int maxVisited); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqInitSlicedFindPath(IntPtr query - , NavmeshPoint startPosition - , NavmeshPoint endPosition - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqUpdateSlicedFindPath(IntPtr query - , int maxIterations - , ref int actualIterations); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFinalizeSlicedFindPath(IntPtr query - , [In, Out] uint[] path - , ref int pathCount - , int maxPath); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindRandomPoint(IntPtr query - , IntPtr filter - , ref NavmeshPoint randomPt); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtqFindRandomPointCircle(IntPtr query - , NavmeshPoint start - , float radius - , IntPtr filter - , ref NavmeshPoint randomPt); - } -} diff --git a/critterai/.svn/pristine/27/27f2e4bd70f91080dc82418d39bd034f332f4ac6.svn-base b/critterai/.svn/pristine/27/27f2e4bd70f91080dc82418d39bd034f332f4ac6.svn-base deleted file mode 100644 index 082f609f..00000000 Binary files a/critterai/.svn/pristine/27/27f2e4bd70f91080dc82418d39bd034f332f4ac6.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/28/2831521ba514fa7d402fee7a7731059faeb993e8.svn-base b/critterai/.svn/pristine/28/2831521ba514fa7d402fee7a7731059faeb993e8.svn-base deleted file mode 100644 index 7c6ef7ac..00000000 --- a/critterai/.svn/pristine/28/2831521ba514fa7d402fee7a7731059faeb993e8.svn-base +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.geom; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.nmgen; -using UnityEngine; - -/// -/// Loads and compiles a terrain component. (Editor Only) -/// -/// -/// -/// The compiler is associated with a TerrainData asset. If the scene contains a Terrain component -/// that references the TerrainData it will be loaded and compiled. Only one Terrain will ever be -/// loaded. (Mutliple Terrain components referencing the same TerrainData is not supported.) -/// -/// -[System.Serializable] -public sealed class TerrainCompiler - : ScriptableObject, IInputBuildProcessor -{ - /// - /// The asset to use for the compile. - /// - public TerrainData terrainData; - - /// - /// True if tree's should also be triangulated. - /// - public bool includeTrees; - - [SerializeField] - private float mResolution = 0.1f; - - /// - /// The resolution factor to use when triangulating the terrain surface. - /// [0.001f <= value <= 1] - /// - /// - /// - /// The TerrainData heightfield has a build-in resolution that is usually much higher than - /// required for building the navigation mesh. For example, a 1024x1024 heightmap for a - /// 2000x2000 unit terrain can generate over 8 million triangles at 100% resolution. - /// This property allows the resolution to be scaled down. A good place to start for a normal - /// terrain is 0.1. - /// - /// - public float Resolution - { - get { return mResolution; } - set { mResolution = Mathf.Max(0.001f, Mathf.Clamp01(value)); } - } - - /// - /// Duplicates allowed. (Always true.) - /// - public bool DuplicatesAllowed { get { return true; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// The priority of the processor. - /// - public int Priority { get { return NMBuild.MinPriority; } } - - internal Terrain GetTerrain() - { - return GetTerrain(null); - } - - private Terrain GetTerrain(InputBuildContext context) - { - if (terrainData == null) - return null; - - Terrain[] items; - - if (context == null) - items = (Terrain[])FindObjectsOfType(typeof(Terrain)); - else - items = context.GetFromScene(); - - if (items.Length == 0) - return null; - - Terrain selected = null; - bool multiple = false; - - foreach (Terrain item in items) - { - if (item.terrainData == terrainData) - { - if (selected == null) - selected = item; - else - multiple = true; - } - } - - if (multiple) - { - string msg = string.Format( - "Multiple terrains in the scene use the same data. {0} was selected" - , selected.name); - - if (context == null) - Debug.LogWarning(msg, this); - else - context.Log(msg, this); - } - - return selected; - } - - /// - /// Processes the context. - /// - /// - /// - /// Processes during the - /// and states. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (context != null && terrainData) - { - switch (state) - { - case InputBuildState.CompileInput: - - Compile(context); - break; - - case InputBuildState.LoadComponents: - - Load(context); - break; - } - } - - return true; - } - - private void Load(InputBuildContext context) - { - context.info.loaderCount++; - - Terrain item = GetTerrain(context); - - if (!item) - { - context.Log(string.Format("No terrain found using {0} terrain data.", terrainData.name) - , this); - } - else - { - context.Load(item); - context.Log(string.Format("Loaded the {0} terrain object.", terrainData.name), this); - } - } - - private void Compile(InputBuildContext context) - { - context.info.compilerCount++; - - InputGeometryCompiler compiler = context.geomCompiler; - List items = context.components; - List areas = context.areas; - - for (int i = 0; i < items.Count; i++) - { - Component item = items[i]; - - if (item is Terrain) - { - Terrain terrain = (Terrain)item; - - if (terrain.terrainData != terrainData) - continue; - - TriangleMesh mesh = TerrainUtil.TriangulateSurface(terrain, mResolution); - byte[] lareas = NMGen.CreateAreaBuffer(mesh.triCount, areas[i]); - - if (compiler.AddTriangles(mesh, lareas)) - { - string msg = string.Format("Compiled the {0} terrain surface. Triangles: {1}" - , terrain.name, mesh.triCount); - - context.Log(msg, this); - } - else - { - string msg = - string.Format("Compiler rejected mesh for the {0} terrain.", terrain.name); - - context.LogError(msg, this); - - return; - } - - if (includeTrees) - { - int before = compiler.TriCount; - - TerrainUtil.TriangluateTrees(terrain, areas[i], compiler); - - string msg = string.Format("Compiled the {0} terrain trees. Triangles: {1}" - , terrain.name, compiler.TriCount - before); - - context.Log(msg, this); - } - - break; - } - } - } -} diff --git a/critterai/.svn/pristine/28/28c46a7febabc4d696ab3d7f28dd182aee5b1fec.svn-base b/critterai/.svn/pristine/28/28c46a7febabc4d696ab3d7f28dd182aee5b1fec.svn-base deleted file mode 100644 index 83bda870..00000000 --- a/critterai/.svn/pristine/28/28c46a7febabc4d696ab3d7f28dd182aee5b1fec.svn-base +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - The final step in the NMGen build process is to create the navigation mesh. As a minimum you must have PolyMesh data. - DetailMesh and ConnectionSet data are optional. - - - - See the topic for the general creation process. This topic will cover two - helpful extensions. - - - - -
- - Creating Tile Data - - - - - Before you can create a navigation mesh you need to convert your source data into tile data. There are various ways of doing this. - - - - One method is to use the - - M:org.critterai.nmbuild.NMBuild.GetBuildData(org.critterai.nmgen.BuildContext,System.Int32,System.Int32,org.critterai.nmgen.PolyMeshData,org.critterai.nmgen.PolyMeshDetailData,org.critterai.nmbuild.ConnectionSet,System.Boolean) - utility method. - - - - // Example: Using the tile build data utility method. - - BuildContext logger = new BuildContext(); - - NavmeshTileBuildData tbd = NMBuild.GetBuildData( - logger - tileX, tileZ // The tile location. (0, 0) for single tile meshes. - , polyData // A PolyMeshData object. - , detailData // Optional PolyMeshDetailData object. - , connections // Optional ConnectionSet object. - , true); - - if (tbd == null) - { - // Perform error handling. - // The build context will contain error messages. - } - - // Use the build data to create the navigation mesh... - - - - Another method is to use the the T:org.critterai.nmbuild.TileBuildTask class to create the tile data. This method - is especially useful if you are building a multi-tile navigation mesh or performing background builds. - - - - // Example: Using the tile build task. - - TileBuildTask task = TileBuildTask.Create( - tileX, tileZ // The tile location. (0, 0) for single tile meshes. - , polyData // A PolyMeshData object. - , detailData // Optional PolyMeshDetailData object. - , connections // Optional ConnectionSet object. - , false // Is the task tread-safe? Not applicable in this case. - , 0); // Task priority. Not applicable in this case. - - task.Run(); - - if (task.TaskState == BuildTaskState.Aborted) - { - // Perform error handling. - // Check task messages for details. - } - - // Get the tile assets. - TileBuildAssets tassets = task.Result; - - // Use the tile data to build the navigation mesh... - - - - -
- -
- - Creating the Navigation Mesh - - - - Once you have the tile data you can use one of two methods to create the final navigation mesh. - - - // Example: Create a single tile mesh. - - // Where 'buildData' is a NavmeshTileBuildData object. - - Navmesh navmesh; - NavStatus status = Navmesh.Create(buildData, out nm))); - - if ((status & NavStatus.Success) == 0) - { - // Perform error handling. - } - - // Use the navitgation mesh... - - - - - - // Example: Create an empty mesh, then add tiles. - - // Where 'tiles' is a list containing NavmeshTileData objects. - - NavmeshParams nconfig = new NavmeshParams(meshOrigin - , tileSetWidth, tileSetDepth - , tiles.Count - , maxPolysPerTile); - - Navmesh navmesh; - - NavStatus status = Navmesh.Create(nconfig, out navmesh) - - if ((status & NavStatus.Success) == 0) - { - // Perform error handling. - } - - // Add the tiles to the navigation mesh. - foreach (NavmeshTileData tile in tiles) - { - // Note: Allowing the navigation mesh to assign the tile reference. - uint trash; - navmesh.AddTile(tile, Navmesh.NullTile, out trash); - } - - // Use the navigation mesh. - - - - -
- - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshParams - T:org.critterai.nav.NavmeshTileBuildData - T:org.critterai.nav.NavmeshTileData - T:org.critterai.nmbuild.TileBuildTask - T:org.critterai.nmbuild.TileBuildAssets - - - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/2a/2a033bcfb9e87a7e015dff327ddffe9e08186c9c.svn-base b/critterai/.svn/pristine/2a/2a033bcfb9e87a7e015dff327ddffe9e08186c9c.svn-base deleted file mode 100644 index ad0ce6ce..00000000 --- a/critterai/.svn/pristine/2a/2a033bcfb9e87a7e015dff327ddffe9e08186c9c.svn-base +++ /dev/null @@ -1,885 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.MathUtil.EPSILON_STD; - -/** - * Represents a mutable 2-dimensional vector. - *

Contains various static operations applicable to 2D vectors.

- *

This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, no divide by zero checks, etc.

- *

All operations support the use of the same object reference in multiple arguments. - * For example: Vector2.multiply(myVector, 5, myVector) will function - * the same as myVector.multiply(5)

- *

Instances of this class are not thread safe. Static operations are thread safe.

- */ -public class Vector2 -{ - - /** - * The x-value for the vector (x, y). - */ - public float x; - - /** - * The y-value for the vector (x, y). - */ - public float y; - - /** - * Constructor for the vector (0.0, 0.0). (Default) - */ - public Vector2() - { - x = 0.0f; - y = 0.0f; - } - - /** - * Constructor. - * @param x The x-value for the vector (x, y). - * @param y The y-value for the vector (x, y). - */ - public Vector2(float x, float y) - { - this.x = x; - this.y = y; - } - - /** - * Adds the provided vector to this vector. - *

The values of this vector are mutated.

- * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector2 add(float x, float y) - { - this.x += x; - this.y += y; - return this; - } - - /** - * Adds the provided vector to this vector. - *

The values of this vector are mutated.

- * @param v The vector to add to this vector. - * @return A reference to this vector. - */ - public Vector2 add(Vector2 v) - { - return add(v.x, v.y); - } - - /** - * Divides this vector by the provided value. - *

The values of this vector are mutated.

- * @param byValue The value to divide the elements of this vector by. - * @return A reference to this vector. - */ - public Vector2 divide(float byValue) - { - this.x /= byValue; - this.y /= byValue; - return this; - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return The dot product of this vector and the provided vector. - * @see Wikipedia- Dot Product - */ - public float dot(float x, float y) - { - return (this.x * x) + (this.y * y); - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param v The vector. - * @return The dot product of this vector and the provided vector. - * @see Wikipedia- Dot Product - */ - public float dot(Vector2 v) - { - return (this.x * v.x) + (this.y * v.y); - } - - /** - * Determines whether or not this vector is equal to the provided vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(float x, float y) - { - - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(x) - || Float.floatToIntBits(this.y) != Float.floatToIntBits(y)) - return false; - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof Vector2)) - return false; - Vector2 other = (Vector2) obj; - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.getX())) - return false; - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.getY())) - return false; - return true; - } - - /** - * Determines whether or not this vector is equal to the provided vector. - *

This operation is slightly faster than the {@link #equals(Object)} form.

- * @param v The vector to compare to. (A value of null will result in a runtime error.) - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(Vector2 v) - { - return equals(v.x, v.y); - } - - /** - * The x-value for this vector. - * @return The x-value for the vector (x, y). - */ - public float getX() { return x; } - - /** - * The y-value for this vector. - * @return The y-value for the vector (x, y). - */ - public float getY() { return y; } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(x); - result = prime * result + Float.floatToIntBits(y); - return result; - } - - /** - * Returns TRUE if the length of the provided vector is zero. - * @return TRUE if the length of the provided vector is zero. Otherwise FALSE. - */ - public boolean isZeroLength() - { - return (x == 0 && y == 0); - } - - /** - * Returns the square of the vector's length. (length * length) - * @return The square of the vector's length. - */ - public float lengthSq() - { - return (x * x) + (y * y); - } - - /** - * Multiplies (scales) this vector by the provided value. - *

The values of this vector are mutated.

- * @param byValue The value to multiply the elements of this vector by. - * @return A reference to this vector. - */ - public Vector2 multiply(float byValue) - { - this.x *= byValue; - this.y *= byValue; - return this; - } - - /** - * Normalizes this vector such that its length is one. - *

The values of this vector are mutated.

- *

WARNING: This is a costly operation.

- * @return A reference to this vector. - */ - public Vector2 normalize() - { - float length = (float)Math.sqrt((x * x) + (y * y)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - - return this; - } - - /** - * Reverses the direction of the vector. - * @return A reference to this vector. - */ - public Vector2 reverse() - { - x = -x; - y = -y; - return this; - } - - /** - * Rotates the vector counter-clockwise by the specified angle. - *

The values of this vector are mutated.

- *

This is a non-trivial operation.

- * @param angle Angle of counter-clockwise rotation. (In Radians.) - * @return A reference to this vector. - */ - public Vector2 rotate(float angle) - { - float ca = (float)Math.cos(angle); - float sa = (float)Math.sin(angle); - float tx = (x * ca) - (y * sa); - y = (x * sa) + (y * ca); - x = tx; - return this; - } - - /** - * Scales the vector to the provided length. - *

The values of this vector are mutated.

- *

WARNING: This is a costly operation.

- * @param length The length to scale the vector to. - * @return A reference to this vector. - */ - public Vector2 scaleTo(float length) - { - if (length == 0 || isZeroLength()) - { - x = 0; - y = 0; - return this; - } - return multiply(length / (float)(Math.sqrt((x * x) + (y * y)))); - } - - /** - * Sets the values of this vector. - * @param x The x-value for the vector (x, y). - * @param y The y-value for the vector (x, y). - * @return A reference to this vector. - */ - public Vector2 set(float x, float y) - { - this.x = x; - this.y = y; - return this; - } - - /** - * Sets the values of this vector to match the provided vector. - * @param v The vector to match this vector to. - * @return A reference to this vector. - */ - public Vector2 set(Vector2 v) - { - this.x = v.x; - this.y = v.y; - return this; - } - - /** - * Sets the x-value of this vector. - * @param value The new the x-value for the vector (x, y). - */ - public void setX(float value) { x = value; } - - /** - * Sets the y-value for the vector (x, y). - * @param value The new the y-value for the vector (x, y). - */ - public void setY(float value) { y = value; } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of this vector. - *

The vectors are considered equal if the following condition is met: - * (vx >= x - tolerance && vx <= x + tolerance) - * && (vy >= y - tolerance && vy <= y + tolerance)

- * @param vx The x-value for the vector (vx, vy). - * @param vy The y-value for the vector (vx, vy). - * @param tolerance The tolerance to use for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(float vx, float vy, float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < x - tolerance || vx > x + tolerance) - return false; - if (vy < y - tolerance || vy > y + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of this vector. - *

The vectors are considered equal if the following condition is met: - * (v.x >= x - tolerance && v.x <= x + tolerance) - * && (v.y >= y - tolerance && v.y <= y + tolerance)

- * @param v The vector to compare against. - * @param tolerance The tolerance for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(Vector2 v, float tolerance) - { - return sloppyEquals(v.x, v.y, tolerance); - } - - /** - * Subtracts the provided vector from this vector. (this - providedVector) - *

The values of this vector are mutated.

- * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector2 subtract(float x, float y) - { - this.x -= x; - this.y -= y; - return this; - } - - /** - * Subtracts the provided vector from this vector. (this - v) - *

The values of this vector are mutated.

- * @param v The vector to subtract from this vector. - * @return A reference to this vector. - */ - public Vector2 subtract(Vector2 v) - { - return subtract(v.x, v.y); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { return "(" + x + ", " + y + ")"; } - - /** - * Truncates the length of this vector to the provided value. - *

The values of this vector are mutated.

- *

If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

- *

If the vector's length is shorter than the provided value, the vector - * is not changed.

- *

WARNING: This is a potentially costly operation.

- * @param maxLength The maximum allowed length of the resulting vector. - * @return A reference to this vector. - */ - public Vector2 truncateLength(float maxLength) - { - if (isZeroLength()) - return this; - if (maxLength == 0) - { - set(0, 0); - return this; - } - float mlsq = maxLength * maxLength; - float csq = (x * x) + (y * y); - if (csq > mlsq) - multiply((float)(maxLength / Math.sqrt(csq))); - return this; - } - - /** - * Adds the vectors (ux, uy) and (vx, vy). - * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(float ux, float uy, float vx, float vy, Vector2 out) - { - out.set(ux + vx, uy + vy); - return out; - } - - /** - * Adds the value to both elements of the vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param value The value to add to both of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(float x, float y, float value, Vector2 out) - { - out.set(x + value, y + value); - return out; - } - - /** - * Adds the value to both elements of the vector. - * @param v The vector to add the value to. - * @param value The value to add to both of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(Vector2 v, float value, Vector2 out) - { - return add(v.x, v.y, value, out); - } - - /** - * Adds the two provided vectors. - * @param u Vector to add. - * @param v Vector to add. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(Vector2 u, Vector2 v, Vector2 out) - { - return add(u.x, u.y, v.x, v.y, out); - } - - /** - * Divides both elements of the vector by the provided value. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 divide(float x, float y, float byValue, Vector2 out) - { - out.set(x / byValue, y / byValue); - return out; - } - - /** - * Divides both elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 divide(Vector2 v, float byValue, Vector2 out) - { - return divide(v.x, v.y, byValue, out); - } - - /** - * Returns the dot products of the provided vectors. - *

If you need to the dot product of two vector objects, use {@link #dot(Vector2)}.

- * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @return The dot product of the provided vectors. - * @see Wikipedia- Dot Product - */ - public static float dot(float ux, float uy, float vx, float vy) - { - return (ux * vx) + (uy * vy); - } - - /** - * Derives the normalized direction vector for the vector pointing from point A (ax, ay) to - * point B (bx, by). - *

WARNING: The out array size and validity of the outIndex are not checked.

- *

WARNING: This is a costly operation.

- * @param ax The x-value for the starting point A (ax, ay). - * @param ay The y-value for the starting point A (ax, ay). - * @param bx The x-value for the end point B (bx, by). - * @param by The y-value for the end point B (bx, by). - * @param out The array to load the result into in the form (x, y). - * @param outIndex The vector index to load the result into. (Stride = 2. So insertion location - * will be outIndex*2.) - * @return A reference to the out argument. - */ - public static float[] getDirectionAB(float ax, float ay - , float bx, float by - , float[] out - , int outIndex) - { - // Subtract. - float x = bx - ax; - float y = by - ay; - - // Normalize. - float length = (float)Math.sqrt((x * x) + (y * y)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - - out[outIndex*2] = x; - out[outIndex*2+1] = y; - - return out; - } - - /** - * Derives the normalized direction vector for the vector pointing from point A (ax, ay) to - * point B (bx, by). - *

WARNING: This is a costly operation.

- * @param ax The x-value for the starting point A (ax, ay). - * @param ay The y-value for the starting point A (ax, ay). - * @param bx The x-value for the end point B (bx, by). - * @param by The y-value for the end point B (bx, by). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 getDirectionAB(float ax, float ay - , float bx, float by - , Vector2 out) - { - // Subtract. - out.x = bx - ax; - out.y = by - ay; - - // Normalize. - float length = (float)Math.sqrt((out.x * out.x) + (out.y * out.y)); - if (length <= EPSILON_STD) - length = 1; - - out.x /= length; - out.y /= length; - - if (Math.abs(out.x) < EPSILON_STD) - out.x = 0; - if (Math.abs(out.y) < EPSILON_STD) - out.y = 0; - - return out; - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param ax The x-value of the point (ax, ay). - * @param ay The y-value of the point (ax, ay). - * @param bx The x-value of the point (bx, by). - * @param by The y-value of the point (bx, by). - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(float ax, float ay, float bx, float by) - { - float dx = ax - bx; - float dy = ay - by; - return (dx * dx + dy * dy); - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param a Point A - * @param b Point B - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(Vector2 a, Vector2 b) - { - return getDistanceSq(a.x, a.y, b.x, b.y); - } - - /** - * Returns the square of the length of the vector. (length * length) - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return The square of the length of the vector. - */ - public static float getLengthSq(float x, float y) - { - return (x * x + y * y); - } - - /** - * Multiplies both elements of the vector by the provided value. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 multiply(float x, float y, float byValue, Vector2 out) - { - out.set(x * byValue, y * byValue); - return out; - } - - /** - * Multiplies both elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 multiply(Vector2 v, float byValue, Vector2 out) - { - return multiply(v.x, v.y, byValue, out); - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

WARNING: This is a costly operation.

- * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 normalize(float x, float y, Vector2 out) - { - float length = (float)Math.sqrt(getLengthSq(x, y)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - - out.set(x, y); - - return out; - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

WARNING: This is a costly operation.

- * @param v The vector to normalize. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 normalize(Vector2 v, Vector2 out) - { - return normalize(v.x, v.y, out); - } - - /** - * Rotates the vector counter-clockwise by the specified angle. - *

This is a non-trivial operation.

- * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param angle Angle of counter-clockwise rotation. (In Radians.) - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 rotate(float x, float y, float angle, Vector2 out) - { - float ca = (float)Math.cos(angle); - float sa = (float)Math.sin(angle); - out.set((x * ca) - (y * sa), (x * sa) + (y * ca)); - return out; - } - - /** - * Rotates the vector counter-clockwise by the specified angle. - *

This is a non-trivial operation.

- * @param v The vector to rotate. - * @param angle Angle of counter-clockwise rotation. (In Radians.) - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 rotate(Vector2 v, float angle, Vector2 out) - { - return rotate(v.x, v.y, angle, out); - } - - /** - * Scales the vector to the provided length. - *

WARNING: This is a costly operation.

- * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 scaleTo(float x, float y, float length, Vector2 out) - { - if (length == 0 || (x == 0 && y == 0)) - { - out.set(0, 0); - return out; - } - return multiply(x, y - , (length / (float)(Math.sqrt(getLengthSq(x, y)))), out); - } - - /** - * Scales the vector to the provided length. - *

WARNING: This is a costly operation.

- * @param v The vector to scale. - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 scaleTo(Vector2 v, float length, Vector2 out) - { - return scaleTo(v.x, v.y, length, out); - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance. - *

The vectors are considered equal if the following condition is met: - * (vx >= ux - tolerance && vx <= ux + tolerance) - * && (vy >= uy - tolerance && vy <= uy + tolerance)

- * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float ux, float uy, float vx, float vy, float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < ux - tolerance || vx > ux + tolerance) - return false; - if (vy < uy - tolerance || vy > uy + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance. - *

The vectors are considered equal if the following condition is met: - * (v.x >= u.x - tolerance && v.x <= u.x + tolerance) - * && (v.y >= u.y - tolerance && v.y <= u.y + tolerance)

- * @param u Vector v - * @param v Vector u - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(Vector2 u, Vector2 v, float tolerance) - { - return sloppyEquals(u.x, u.y, v.x, v.y, tolerance); - } - - /** - * Subtracts vector (vx, vy) from vector (ux, uy) - * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 subtract(float ux, float uy, float vx, float vy, Vector2 out) - { - out.set(ux - vx, uy - vy); - return out; - } - - /** - * Subtracts two vectors. (u - v) - * @param u Vector to be subtracted from. - * @param v Vector to subtract. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 subtract(Vector2 u, Vector2 v, Vector2 out) - { - return subtract(u.x, u.y, v.x, v.y, out); - } - - /** - * Truncates the length of the vector to the provided value. - *

If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

- *

If the vector's length is shorter than the provided value, the vector - * is not changed.

- *

WARNING: This is a potentially costly operation.

- * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 truncateLength(float x, float y, float maxLength, Vector2 out) - { - if (maxLength == 0 || (x == 0 && y == 0)) - { - out.set(0, 0); - return out; - } - float mlsq = maxLength * maxLength; - float csq = getLengthSq(x, y); - if (csq <= mlsq) - { - out.set(x, y); - return out; - } - return multiply(x, y, (float)(maxLength / Math.sqrt(csq)), out); - } - - /** - * Truncates the length of the vector to the provided value. - *

If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

- *

If the vector's length is shorter than the provided value, the vector - * is not changed.

- *

WARNING: This is a potentially costly operation.

- * @param v The vector to truncate. - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 truncateLength(Vector2 v, float maxLength, Vector2 out) - { - return truncateLength(v.x, v.y, maxLength, out); - } - -} diff --git a/critterai/.svn/pristine/2a/2a44a14f10030146551bb0aaf2863fc5c931a79f.svn-base b/critterai/.svn/pristine/2a/2a44a14f10030146551bb0aaf2863fc5c931a79f.svn-base deleted file mode 100644 index 996786a8..00000000 Binary files a/critterai/.svn/pristine/2a/2a44a14f10030146551bb0aaf2863fc5c931a79f.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/2a/2a583944115ac4c7d454bc0a1585d8297b0ba487.svn-base b/critterai/.svn/pristine/2a/2a583944115ac4c7d454bc0a1585d8297b0ba487.svn-base deleted file mode 100644 index 0a293d8f..00000000 --- a/critterai/.svn/pristine/2a/2a583944115ac4c7d454bc0a1585d8297b0ba487.svn-base +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * Unit tests for all classes in the org.critterai.math package. - */ -@RunWith(Suite.class) -@SuiteClasses( {MathUtilTests.class - , Vector2Tests.class - , Vector3Tests.class}) -public class AllTests { } diff --git a/critterai/.svn/pristine/2a/2a5ede59eec25e27d061d90d1c98b403e94b9e1a.svn-base b/critterai/.svn/pristine/2a/2a5ede59eec25e27d061d90d1c98b403e94b9e1a.svn-base deleted file mode 100644 index e6681992..00000000 --- a/critterai/.svn/pristine/2a/2a5ede59eec25e27d061d90d1c98b403e94b9e1a.svn-base +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(OFMConnectionCompiler))] -public sealed class OFMConnectionCompilerEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - OFMConnectionCompiler targ = (OFMConnectionCompiler)target; - - EditorGUILayout.Separator(); - - GUILayout.Label("Priority: " + targ.Priority); - - EditorGUILayout.Separator(); - - GUILayout.Box("Input Build Processor\n\n" - + "Loads and compiles the " + typeof(OFMConnection).Name + " components in the scene." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Compiler : Connection", false, NMBEditorUtil.CompilerGroup)] - static void CreateAsset() - { - OFMConnectionCompiler item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/2a/2ad1b254a0f0586e926423410987d62b348df0d7.svn-base b/critterai/.svn/pristine/2a/2ad1b254a0f0586e926423410987d62b348df0d7.svn-base deleted file mode 100644 index d2340f53..00000000 --- a/critterai/.svn/pristine/2a/2ad1b254a0f0586e926423410987d62b348df0d7.svn-base +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using org.critterai.interop; -using org.critterai.nmgen.rcn; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Represents a polygon mesh suitable for use in building a a navigation mesh. - /// - /// - /// - /// Warning: The serializable attribute and interface will be removed in v0.5. Use - /// instead. - /// - /// - /// Represents a mesh of potentially overlapping convex polygons of between three and - /// vertices. The mesh exists within the context of an - /// axis-aligned bounding box (AABB) with vertices laid out in an evenly spaced grid based - /// on xz-plane and y-axis cells. - /// - /// - /// This class is moslty opaque. The class provides the ability to - /// inspect and update the content. - /// - /// - /// This class is not compatible with Unity serialization. The - /// method can be used for serialization within Unity. - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - /// - [Serializable] - public sealed class PolyMesh - : ManagedObject, ISerializable - { - /// - /// Represents an index that does not point to anything. - /// - public const ushort NullIndex = 0xffff; - - // Serialization key. - private const string DataKey = "d"; - - internal PolyMeshEx root = new PolyMeshEx(); - - private int mMaxVerts = 0; - private float mWalkableHeight = 0; - private float mWalkableStep = 0; - private float mWalkableRadius = 0; - - /// - /// The number of vertices in the vertex array. - /// - public int VertCount { get { return root.vertCount; } } - - /// - /// The number of polygons defined by the mesh. - /// - public int PolyCount { get { return root.polyCount; } } - - /// - /// The maximum number of vertices per polygon. - /// - /// - /// - /// Individual polygons can vary in size from three to this number of vertices. - /// - /// - public int MaxVertsPerPoly { get { return root.maxVertsPerPoly; } } - - /// - /// The world space minimum bounds of the mesh's AABB. - /// - /// The minimum bounds of the mesh. - public Vector3 BoundsMin { get { return root.boundsMin; } } - - /// - /// The world space maximum bounds of the mesh's AABB. - /// - /// The maximum bounds of the mesh. - public Vector3 BoundsMax { get { return root.boundsMax; } } - - /// - /// The xz-plane size of the cells that form the mesh field. - /// - public float XZCellSize { get { return root.xzCellSize; } } - - /// - /// The y-axis size of the cells that form the mesh field. - /// - public float YCellSize { get { return root.yCellSize; } } - - /// - /// The minimum floor to 'ceiling' height used to build the polygon mesh. [Units: World] - /// - public float WalkableHeight { get { return mWalkableHeight; } } - - /// - /// The radius used to erode the walkable area of the mesh. [Units: World] - /// - public float WalkableRadius { get { return mWalkableRadius; } } - - /// - /// The maximum traversable ledge height used to build the polygon mesh. [Units: World] - /// - public float WalkableStep { get { return mWalkableStep; } } - - /// - /// The maximum number of vertices the vertex buffer can hold. - /// - public int MaxVerts { get { return mMaxVerts; } } - - /// - /// The maximum number of polygons the polygon buffer can hold. - /// - public int MaxPolys { get { return root.maxPolys; } } - - /// - /// The AABB border size applied during the build of the mesh. [Units: XZCellSize] - /// - public int BorderSize { get { return root.borderSize; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public override bool IsDisposed - { - get { return (root.polys == IntPtr.Zero); } - } - - private PolyMesh(AllocType resourceType) - : base(resourceType) - { - } - - private PolyMesh(SerializationInfo info, StreamingContext context) - : base(AllocType.External) - { - // Note: Version compatability is handled by the interop call; - - byte[] rawData = (byte[])info.GetValue(DataKey, typeof(byte[])); - - PolyMeshEx.rcpmBuildSerializedData(rawData - , rawData.Length - , ref root - , ref mMaxVerts - , ref mWalkableHeight - , ref mWalkableRadius - , ref mWalkableStep); - } - - private PolyMesh(int maxVerts, int maxPolys, int maxVertsPerPoly) - : base(AllocType.Local) - { - if (maxVerts < 3 - || maxPolys < 1 - || maxVertsPerPoly < 3 - || maxVertsPerPoly > NMGen.MaxAllowedVertsPerPoly) - { - return; - } - - mMaxVerts = maxVerts; - root.maxPolys = maxPolys; - root.maxVertsPerPoly = maxVertsPerPoly; - - int size = sizeof(ushort) * mMaxVerts * 3; - root.verts = UtilEx.GetBuffer(size, true); - - size = sizeof(ushort) * root.maxPolys * 2 - * root.maxVertsPerPoly; - root.polys = UtilEx.GetBuffer(size, true); - - size = sizeof(ushort) * root.maxPolys; - root.regions = UtilEx.GetBuffer(size, true); - root.flags = UtilEx.GetBuffer(size, true); - - size = sizeof(byte) * root.maxPolys; - root.areas = UtilEx.GetBuffer(size, true); - } - - /// - /// Destructor. - /// - ~PolyMesh() - { - RequestDisposal(); - } - - /// - /// Frees all resources and marks the object as disposed. - /// - public override void RequestDisposal() - { - if (!IsDisposed) - { - if (ResourceType == AllocType.Local) - { - Marshal.FreeHGlobal(root.areas); - Marshal.FreeHGlobal(root.flags); - Marshal.FreeHGlobal(root.polys); - Marshal.FreeHGlobal(root.regions); - Marshal.FreeHGlobal(root.verts); - } - else if (ResourceType == AllocType.External) - PolyMeshEx.rcpmFreeMeshData(ref root); - - root.Reset(); - mMaxVerts = 0; - mWalkableHeight = 0; - mWalkableStep = 0; - - } - } - - /// - /// Loads the data into the mesh buffers, overwriting existing content. - /// - /// The data to load. - /// True if the load was successful. - public bool Load(PolyMeshData data) - { - int vcount = (data.verts == null || data.vertCount < 3 ? - 0 : data.vertCount); - int pcount = (data.polys == null || data.polyCount < 1 ? - 0 : data.polyCount); - - if (pcount == 0 || pcount > root.maxPolys - || vcount == 0 || vcount > mMaxVerts - || data.xzCellSize < NMGen.MinCellSize - || data.yCellSize < NMGen.MinCellSize - || data.walkableHeight - < NMGen.MinWalkableHeight * NMGen.MinCellSize - || data.walkableStep < 0 - || data.walkableRadius < 0 - || data.borderSize < 0 - || data.polys.Length - < (pcount * 2 * root.maxVertsPerPoly) - || data.verts.Length < (vcount * 3) - || (data.areas != null && data.areas.Length < pcount) - || (data.regions != null - && data.regions.Length < pcount) - || (data.flags != null && data.flags.Length < pcount)) - { - return false; - } - - root.polyCount = pcount; - root.vertCount = vcount; - root.xzCellSize = data.xzCellSize; - root.yCellSize = data.yCellSize; - mWalkableHeight = data.walkableHeight; - mWalkableRadius = data.walkableRadius; - mWalkableStep = data.walkableStep; - root.borderSize = data.borderSize; - - root.boundsMin = data.boundsMin; - root.boundsMax = data.boundsMax; - - UtilEx.Copy(data.verts, 0, root.verts, root.vertCount * 3); - - UtilEx.Copy(data.polys - , 0 - , root.polys - , root.polyCount * 2 * root.maxVertsPerPoly); - - if (data.regions == null) - UtilEx.ZeroMemory(root.regions, sizeof(ushort) * root.polyCount); - else - UtilEx.Copy(data.regions, 0, root.regions, root.polyCount); - - if (data.flags == null) - UtilEx.ZeroMemory(root.flags, sizeof(ushort) * root.polyCount); - else - UtilEx.Copy(data.flags, 0, root.flags, root.polyCount); - - if (data.areas == null) - UtilEx.ZeroMemory(root.areas, sizeof(byte) * root.polyCount); - else - Marshal.Copy(data.areas, 0, root.areas, root.polyCount); - - return true; - } - - /// - /// Gets the data from the mesh buffers. - /// - /// - /// - /// This method is useful for extracting mesh data so it can be inspected or altered - /// and reloaded. - /// - /// - /// - /// If true, includes the unused buffer space. Otherwise only the used buffer data is - /// returned. - /// - /// The data from the mesh buffers. - public PolyMeshData GetData(bool includeBuffer) - { - int mp = (includeBuffer ? root.maxPolys : root.polyCount); - int mv = (includeBuffer ? mMaxVerts : root.vertCount); - - PolyMeshData buffer = new PolyMeshData(mv - , mp - , root.maxVertsPerPoly); - - FillData(buffer); - - return buffer; - } - - /// - /// Loads the data from the mesh buffers into the data object. - /// - /// - /// - /// A new buffer will be returned if the buffer argument is null. - /// - /// - /// The buffer will be automatically resized if it is too small to hold the result. - /// - /// - /// Only the used portions of the mesh buffers are copied. - /// - /// - /// A buffer to load the data into. - /// A reference to the mesh data. - public PolyMeshData GetData(PolyMeshData buffer) - { - if (IsDisposed) - return null; - if (buffer == null) - return GetData(true); - - if (!buffer.CanFit(root.vertCount - , root.polyCount - , root.maxVertsPerPoly)) - { - buffer.Resize(mMaxVerts, root.maxPolys, root.maxVertsPerPoly); - } - - FillData(buffer); - - return buffer; - } - - private void FillData(PolyMeshData buffer) - { - buffer.maxVertsPerPoly = root.maxVertsPerPoly; - buffer.boundsMax = BoundsMax; - buffer.boundsMin = BoundsMin; - buffer.yCellSize = root.yCellSize; - buffer.xzCellSize = root.xzCellSize; - buffer.polyCount = root.polyCount; - buffer.vertCount = root.vertCount; - buffer.walkableStep = mWalkableStep; - buffer.walkableHeight = mWalkableHeight; - buffer.walkableRadius = mWalkableRadius; - buffer.borderSize = root.borderSize; - - UtilEx.Copy(root.polys - , buffer.polys - , root.polyCount * 2 * root.maxVertsPerPoly); - Marshal.Copy(root.areas, buffer.areas, 0, root.polyCount); - UtilEx.Copy(root.flags, buffer.flags, root.polyCount); - UtilEx.Copy(root.regions, buffer.regions, root.polyCount); - - UtilEx.Copy(root.verts, buffer.verts, root.vertCount * 3); - } - - /// - /// Gets a serialized version of the mesh that can be used to - /// recreate it later. - /// - /// - /// True if serialized data should include the full buffer size. Otherwise the unused - /// portion of the buffers will removed and the smallest possible serialized data returned. - /// - /// A serialized version of the mesh. - public byte[] GetSerializedData(bool includeBuffer) - { - if (IsDisposed) - return null; - - // Design note: This is implemented using an interop call - // rather than local code bacause it is much more easier to - // serialize in C++ than it is in C#. - - IntPtr ptr = IntPtr.Zero; - int dataSize = 0; - - if (!PolyMeshEx.rcpmGetSerializedData(ref root - , mMaxVerts - , mWalkableHeight - , mWalkableRadius - , mWalkableStep - , includeBuffer - , ref ptr - , ref dataSize)) - { - return null; - } - - byte[] result = UtilEx.ExtractArrayByte(ptr, dataSize); - - NMGenEx.nmgFreeSerializationData(ref ptr); - - return result; - } - - /// - /// Gets serialization data for the object. - /// - /// - /// - /// Will always include the unused buffer space. (No compression.) - /// - /// - /// Serialization information. - /// Serialization context. - public void GetObjectData(SerializationInfo info - , StreamingContext context) - { - /* - * Design Notes: - * - * Default serialization security is OK. - * Validation and versioning is handled by GetSerializedData(). - */ - - byte[] rawData = GetSerializedData(true); - - if (rawData == null) - return; - - info.AddValue(DataKey, rawData); - } - - /// - /// Builds polygon mesh from the provided contours. - /// - /// - /// - /// The values of the CellSize-based parameters will be converted to world units. - /// - /// - /// The context to use for the operation. - /// The contours to use to build the mesh. - /// - /// The maximum allowed vertices for a polygon. - /// [Limits: 3 <= value <= ] - /// - /// - /// The walkable height used to build the contour data. - /// [Limit: >= ] [Units: YCellSize] - /// - /// - /// The radius used to erode the walkable area covered by the contours. - /// [Limit: >= 0] [Units: XZCellSize] - /// - /// - /// The walkable step used to build - /// the contour data. [Limit: >= 0] [Units: YCellSize] - /// The generated polygon mesh, or null if there were errors. - public static PolyMesh Build(BuildContext context, ContourSet contours - , int maxVertsPerPoly, int walkableHeight, int walkableRadius, int walkableStep) - { - if (context == null || contours == null) - return null; - - PolyMesh result = new PolyMesh(AllocType.External); - - if (!PolyMeshEx.rcpmBuildFromContourSet(context.root - , contours.root - , maxVertsPerPoly - , ref result.root - , ref result.mMaxVerts)) - { - return null; - } - - result.mWalkableHeight = walkableHeight * contours.YCellSize; - result.mWalkableRadius = walkableRadius * contours.XZCellSize; - result.mWalkableStep = walkableStep * contours.YCellSize; - - return result; - } - - /// - /// Creates a polygon mesh from the data generated by the - /// method. - /// - /// The serialized mesh data. - /// The new polygon mesh, or null on error. - public static PolyMesh Create(byte[] serializedMesh) - { - PolyMesh result = new PolyMesh(AllocType.External); - - if (PolyMeshEx.rcpmBuildSerializedData(serializedMesh - , serializedMesh.Length - , ref result.root - , ref result.mMaxVerts - , ref result.mWalkableHeight - , ref result.mWalkableRadius - , ref result.mWalkableStep)) - { - return result; - } - - return null; - } - - /// - /// Constructs an object with all buffers allocated and - /// ready to load with data. (See: ) - /// - /// - /// The maximum veritices the vertex buffer can hold. [Limit: >= 3] - /// - /// - /// The maximum polygons the polygon buffer can hold. [Limit: > 0] - /// - /// - /// The maximum allowed vertices for a polygon. - /// [Limits: 3 <= value <= ] - /// - /// The new polygon mesh, or null on error. - public static PolyMesh Create(int maxVerts, int maxPolys, int maxVertsPerPoly) - { - if (maxVerts < 3 - || maxPolys < 1 - || maxVertsPerPoly < 3 - || maxVertsPerPoly > NMGen.MaxAllowedVertsPerPoly) - { - return null; - } - - return new PolyMesh(maxVerts, maxPolys, maxVertsPerPoly); - } - } -} diff --git a/critterai/.svn/pristine/2c/2c5f7333b32183598752bd86709f0941d04f2f96.svn-base b/critterai/.svn/pristine/2c/2c5f7333b32183598752bd86709f0941d04f2f96.svn-base deleted file mode 100644 index e003bf60..00000000 --- a/critterai/.svn/pristine/2c/2c5f7333b32183598752bd86709f0941d04f2f96.svn-base +++ /dev/null @@ -1,376 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include "DetourCommon.h" - -////////////////////////////////////////////////////////////////////////////////////////// - -float dtSqrt(float x) -{ - return sqrtf(x); -} - -void dtClosestPtPointTriangle(float* closest, const float* p, - const float* a, const float* b, const float* c) -{ - // Check if P in vertex region outside A - float ab[3], ac[3], ap[3]; - dtVsub(ab, b, a); - dtVsub(ac, c, a); - dtVsub(ap, p, a); - float d1 = dtVdot(ab, ap); - float d2 = dtVdot(ac, ap); - if (d1 <= 0.0f && d2 <= 0.0f) - { - // barycentric coordinates (1,0,0) - dtVcopy(closest, a); - return; - } - - // Check if P in vertex region outside B - float bp[3]; - dtVsub(bp, p, b); - float d3 = dtVdot(ab, bp); - float d4 = dtVdot(ac, bp); - if (d3 >= 0.0f && d4 <= d3) - { - // barycentric coordinates (0,1,0) - dtVcopy(closest, b); - return; - } - - // Check if P in edge region of AB, if so return projection of P onto AB - float vc = d1*d4 - d3*d2; - if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) - { - // barycentric coordinates (1-v,v,0) - float v = d1 / (d1 - d3); - closest[0] = a[0] + v * ab[0]; - closest[1] = a[1] + v * ab[1]; - closest[2] = a[2] + v * ab[2]; - return; - } - - // Check if P in vertex region outside C - float cp[3]; - dtVsub(cp, p, c); - float d5 = dtVdot(ab, cp); - float d6 = dtVdot(ac, cp); - if (d6 >= 0.0f && d5 <= d6) - { - // barycentric coordinates (0,0,1) - dtVcopy(closest, c); - return; - } - - // Check if P in edge region of AC, if so return projection of P onto AC - float vb = d5*d2 - d1*d6; - if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) - { - // barycentric coordinates (1-w,0,w) - float w = d2 / (d2 - d6); - closest[0] = a[0] + w * ac[0]; - closest[1] = a[1] + w * ac[1]; - closest[2] = a[2] + w * ac[2]; - return; - } - - // Check if P in edge region of BC, if so return projection of P onto BC - float va = d3*d6 - d5*d4; - if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) - { - // barycentric coordinates (0,1-w,w) - float w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); - closest[0] = b[0] + w * (c[0] - b[0]); - closest[1] = b[1] + w * (c[1] - b[1]); - closest[2] = b[2] + w * (c[2] - b[2]); - return; - } - - // P inside face region. Compute Q through its barycentric coordinates (u,v,w) - float denom = 1.0f / (va + vb + vc); - float v = vb * denom; - float w = vc * denom; - closest[0] = a[0] + ab[0] * v + ac[0] * w; - closest[1] = a[1] + ab[1] * v + ac[1] * w; - closest[2] = a[2] + ab[2] * v + ac[2] * w; -} - -bool dtIntersectSegmentPoly2D(const float* p0, const float* p1, - const float* verts, int nverts, - float& tmin, float& tmax, - int& segMin, int& segMax) -{ - static const float EPS = 0.00000001f; - - tmin = 0; - tmax = 1; - segMin = -1; - segMax = -1; - - float dir[3]; - dtVsub(dir, p1, p0); - - for (int i = 0, j = nverts-1; i < nverts; j=i++) - { - float edge[3], diff[3]; - dtVsub(edge, &verts[i*3], &verts[j*3]); - dtVsub(diff, p0, &verts[j*3]); - const float n = dtVperp2D(edge, diff); - const float d = dtVperp2D(dir, edge); - if (fabsf(d) < EPS) - { - // S is nearly parallel to this edge - if (n < 0) - return false; - else - continue; - } - const float t = n / d; - if (d < 0) - { - // segment S is entering across this edge - if (t > tmin) - { - tmin = t; - segMin = j; - // S enters after leaving polygon - if (tmin > tmax) - return false; - } - } - else - { - // segment S is leaving across this edge - if (t < tmax) - { - tmax = t; - segMax = j; - // S leaves before entering polygon - if (tmax < tmin) - return false; - } - } - } - - return true; -} - -float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t) -{ - float pqx = q[0] - p[0]; - float pqz = q[2] - p[2]; - float dx = pt[0] - p[0]; - float dz = pt[2] - p[2]; - float d = pqx*pqx + pqz*pqz; - t = pqx*dx + pqz*dz; - if (d > 0) t /= d; - if (t < 0) t = 0; - else if (t > 1) t = 1; - dx = p[0] + t*pqx - pt[0]; - dz = p[2] + t*pqz - pt[2]; - return dx*dx + dz*dz; -} - -void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts) -{ - tc[0] = 0.0f; - tc[1] = 0.0f; - tc[2] = 0.0f; - for (int j = 0; j < nidx; ++j) - { - const float* v = &verts[idx[j]*3]; - tc[0] += v[0]; - tc[1] += v[1]; - tc[2] += v[2]; - } - const float s = 1.0f / nidx; - tc[0] *= s; - tc[1] *= s; - tc[2] *= s; -} - -bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h) -{ - float v0[3], v1[3], v2[3]; - dtVsub(v0, c,a); - dtVsub(v1, b,a); - dtVsub(v2, p,a); - - const float dot00 = dtVdot2D(v0, v0); - const float dot01 = dtVdot2D(v0, v1); - const float dot02 = dtVdot2D(v0, v2); - const float dot11 = dtVdot2D(v1, v1); - const float dot12 = dtVdot2D(v1, v2); - - // Compute barycentric coordinates - const float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); - const float u = (dot11 * dot02 - dot01 * dot12) * invDenom; - const float v = (dot00 * dot12 - dot01 * dot02) * invDenom; - - // The (sloppy) epsilon is needed to allow to get height of points which - // are interpolated along the edges of the triangles. - static const float EPS = 1e-4f; - - // If point lies inside the triangle, return interpolated ycoord. - if (u >= -EPS && v >= -EPS && (u+v) <= 1+EPS) - { - h = a[1] + v0[1]*u + v1[1]*v; - return true; - } - - return false; -} - -/// @par -/// -/// All points are projected onto the xz-plane, so the y-values are ignored. -bool dtPointInPolygon(const float* pt, const float* verts, const int nverts) -{ - // TODO: Replace pnpoly with triArea2D tests? - int i, j; - bool c = false; - for (i = 0, j = nverts-1; i < nverts; j = i++) - { - const float* vi = &verts[i*3]; - const float* vj = &verts[j*3]; - if (((vi[2] > pt[2]) != (vj[2] > pt[2])) && - (pt[0] < (vj[0]-vi[0]) * (pt[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) ) - c = !c; - } - return c; -} - -bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts, - float* ed, float* et) -{ - // TODO: Replace pnpoly with triArea2D tests? - int i, j; - bool c = false; - for (i = 0, j = nverts-1; i < nverts; j = i++) - { - const float* vi = &verts[i*3]; - const float* vj = &verts[j*3]; - if (((vi[2] > pt[2]) != (vj[2] > pt[2])) && - (pt[0] < (vj[0]-vi[0]) * (pt[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) ) - c = !c; - ed[j] = dtDistancePtSegSqr2D(pt, vj, vi, et[j]); - } - return c; -} - -static void projectPoly(const float* axis, const float* poly, const int npoly, - float& rmin, float& rmax) -{ - rmin = rmax = dtVdot2D(axis, &poly[0]); - for (int i = 1; i < npoly; ++i) - { - const float d = dtVdot2D(axis, &poly[i*3]); - rmin = dtMin(rmin, d); - rmax = dtMax(rmax, d); - } -} - -inline bool overlapRange(const float amin, const float amax, - const float bmin, const float bmax, - const float eps) -{ - return ((amin+eps) > bmax || (amax-eps) < bmin) ? false : true; -} - -/// @par -/// -/// All vertices are projected onto the xz-plane, so the y-values are ignored. -bool dtOverlapPolyPoly2D(const float* polya, const int npolya, - const float* polyb, const int npolyb) -{ - const float eps = 1e-4f; - - for (int i = 0, j = npolya-1; i < npolya; j=i++) - { - const float* va = &polya[j*3]; - const float* vb = &polya[i*3]; - const float n[3] = { vb[2]-va[2], 0, -(vb[0]-va[0]) }; - float amin,amax,bmin,bmax; - projectPoly(n, polya, npolya, amin,amax); - projectPoly(n, polyb, npolyb, bmin,bmax); - if (!overlapRange(amin,amax, bmin,bmax, eps)) - { - // Found separating axis - return false; - } - } - for (int i = 0, j = npolyb-1; i < npolyb; j=i++) - { - const float* va = &polyb[j*3]; - const float* vb = &polyb[i*3]; - const float n[3] = { vb[2]-va[2], 0, -(vb[0]-va[0]) }; - float amin,amax,bmin,bmax; - projectPoly(n, polya, npolya, amin,amax); - projectPoly(n, polyb, npolyb, bmin,bmax); - if (!overlapRange(amin,amax, bmin,bmax, eps)) - { - // Found separating axis - return false; - } - } - return true; -} - -// Returns a random point in a convex polygon. -// Adapted from Graphics Gems article. -void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas, - const float s, const float t, float* out) -{ - // Calc triangle araes - float areasum = 0.0f; - for (int i = 2; i < npts; i++) { - areas[i] = dtTriArea2D(&pts[0], &pts[(i-1)*3], &pts[i*3]); - areasum += dtMax(0.001f, areas[i]); - } - // Find sub triangle weighted by area. - const float thr = s*areasum; - float acc = 0.0f; - float u = 0.0f; - int tri = 0; - for (int i = 2; i < npts; i++) { - const float dacc = areas[i]; - if (thr >= acc && thr < (acc+dacc)) - { - u = (thr - acc) / dacc; - tri = i; - break; - } - acc += dacc; - } - - float v = dtSqrt(t); - - const float a = 1 - v; - const float b = (1 - u) * v; - const float c = u * v; - const float* pa = &pts[0]; - const float* pb = &pts[(tri-1)*3]; - const float* pc = &pts[tri*3]; - - out[0] = a*pa[0] + b*pb[0] + c*pc[0]; - out[1] = a*pa[1] + b*pb[1] + c*pc[1]; - out[2] = a*pa[2] + b*pb[2] + c*pc[2]; -} - diff --git a/critterai/.svn/pristine/2d/2d40ce814a65cee0468121d18362c3eddc90bd3e.svn-base b/critterai/.svn/pristine/2d/2d40ce814a65cee0468121d18362c3eddc90bd3e.svn-base deleted file mode 100644 index f26bf12b..00000000 --- a/critterai/.svn/pristine/2d/2d40ce814a65cee0468121d18362c3eddc90bd3e.svn-base +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2010-2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; - -namespace org.critterai -{ - /// - /// Provides various math related constants and utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class MathUtil - { - /// - /// A standard epsilon value. (Minimum positive value.) - /// - public const float Epsilon = 0.00001f; - - /// - /// A standard tolerance value. - /// - public const float Tolerance = 0.0001f; - - /// - /// Determines whether the values are within the specified tolerance of each other. - /// - /// The a-value to compare against the b-value. - /// The b-value to compare against the a-value. - /// The tolerance to use for the comparison. - /// True if the values are within the specified tolerance of each other. - public static bool SloppyEquals(float a, float b, float tolerance) - { - return !(b < a - tolerance || b > a + tolerance); - } - - /// - /// Clamps the value to a positive non-zero value. - /// - /// The value to clamp. - /// - /// The value clamped to a minimum of the smallest possible positive value greater - /// than zero. - /// - public static float ClampToPositiveNonZero(float value) - { - return Math.Max(float.Epsilon, value); - } - - /// - /// Clamps the value to the specified range. The clamp is inclusive of the minimum and - /// maximum. - /// - /// The value to clamp. - /// The minimum allowed value. - /// The maximum allowed value. - /// The value clamped to the specified range. - public static int Clamp(int value, int minimum, int maximum) - { - return (value < minimum ? minimum : - (value > maximum ? maximum : value)); - } - - /// - /// Returns the maximum value in the list of values. - /// - /// The values to search. - /// The maximum value in the list of values. - public static float Max(params float[] values) - { - float result = values[0]; - for (int i = 1; i < values.Length; i++) - result = Math.Max(result, values[i]); - return result; - } - - /// - /// Returns the minimum value in the list of values. - /// - /// The values to search. - /// The minimum value in the list of values. - public static float Min(params float[] values) - { - float result = values[0]; - for (int i = 1; i < values.Length; i++) - result = Math.Min(result, values[i]); - return result; - } - } -} diff --git a/critterai/.svn/pristine/2d/2d7b28bcc51a9167ab3954e7191a145d3984df51.svn-base b/critterai/.svn/pristine/2d/2d7b28bcc51a9167ab3954e7191a145d3984df51.svn-base deleted file mode 100644 index 2a21961f..00000000 --- a/critterai/.svn/pristine/2d/2d7b28bcc51a9167ab3954e7191a145d3984df51.svn-base +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents a span within the cell column of a heightfield. - * Spans represent one or more contiguous voxels. - * @see Introduction to Heightfields - */ -public final class HeightSpan -{ - - /* - * Recast Reference: rcSpan in Recast.h - */ - - private int mMinimum; - private int mMaximum; - private int mFlags = 0; - private HeightSpan mNext = null; - - /** - * Constructor - * @param min The minimum increment of the span. - * (Usually the height increment.) - * @param max The maximum increment of the span. - * (Usually the height increment.) - * @param flags The span flags. - * @throws IllegalArgumentException If the minimum is greater than or - * equal to the maximum. - */ - public HeightSpan(int min, int max, int flags) - throws IllegalArgumentException - { - if (min > max) - throw new IllegalArgumentException( - "Minimum is greater than or equal to the maximum."); - mMinimum = min; - mMaximum = max; - mFlags = flags; - } - - /** - * The flags for the span. - * @return The flags for the span. - */ - public int flags() { return mFlags; } - - /** - * The span maximum. - * @return The span maximum. - */ - public int max() { return mMaximum; } - - /** - * The span minimum. - * @return The span minimum. - */ - public int min() { return mMinimum; } - - /** - * The next span in the column. (Usually above the current span.) - * @return The next span in the column. Or null if there is no next span. - */ - public HeightSpan next() { return mNext; } - - /** - * Set the flags for the span. - * @param value The new flags for the span. - */ - public void setFlags(int value) { mFlags = value; } - - /** - * Sets the span maximum. - *

Auto-clamps the value to ({@link #min()} + 1).

- * @param value The new maximum. - */ - public void setMax(int value) - { - if (value <= mMinimum) - mMaximum = mMinimum + 1; - else - mMaximum = value; - } - - /** - * Sets the span minimum. - *

Auto-clamps the value to ({@link #max()} - 1).

- * @param value The new minimum. - */ - public void setMin(int value) - { - if (value >= mMaximum) - mMinimum = mMaximum - 1; - else - mMinimum = value; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() - { - return mMinimum + "->" + mMaximum + ", Flags: " + mFlags; - } - - /** - * Set the next span value. - * @param value The new next span. (null is a valid value.) - */ - void setNext(HeightSpan value) { mNext = value; } - -} diff --git a/critterai/.svn/pristine/2e/2e25bc4d92fd9f29a75e62e484e6550fb768c69f.svn-base b/critterai/.svn/pristine/2e/2e25bc4d92fd9f29a75e62e484e6550fb768c69f.svn-base deleted file mode 100644 index 6a3d3382..00000000 --- a/critterai/.svn/pristine/2e/2e25bc4d92fd9f29a75e62e484e6550fb768c69f.svn-base +++ /dev/null @@ -1,142 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOUTPATHCORRIDOR_H -#define DETOUTPATHCORRIDOR_H - -#include "DetourNavMeshQuery.h" - -/// Represents a dynamic polygon corridor used to plan agent movement. -/// @ingroup crowd, detour -class dtPathCorridor -{ - float m_pos[3]; - float m_target[3]; - - dtPolyRef* m_path; - int m_npath; - int m_maxPath; - -public: - dtPathCorridor(); - ~dtPathCorridor(); - - /// Allocates the corridor's path buffer. - /// @param[in] maxPath The maximum path size the corridor can handle. - /// @return True if the initialization succeeded. - bool init(const int maxPath); - - /// Resets the path corridor to the specified position. - /// @param[in] ref The polygon reference containing the position. - /// @param[in] pos The new position in the corridor. [(x, y, z)] - void reset(dtPolyRef ref, const float* pos); - - /// Finds the corners in the corridor from the position toward the target. (The straightened path.) - /// @param[out] cornerVerts The corner vertices. [(x, y, z) * cornerCount] [Size: <= maxCorners] - /// @param[out] cornerFlags The flag for each corner. [(flag) * cornerCount] [Size: <= maxCorners] - /// @param[out] cornerPolys The polygon reference for each corner. [(polyRef) * cornerCount] - /// [Size: <= @p maxCorners] - /// @param[in] maxCorners The maximum number of corners the buffers can hold. - /// @param[in] navquery The query object used to build the corridor. - /// @param[in] filter The filter to apply to the operation. - /// @return The number of corners returned in the corner buffers. [0 <= value <= @p maxCorners] - int findCorners(float* cornerVerts, unsigned char* cornerFlags, - dtPolyRef* cornerPolys, const int maxCorners, - dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - /// Attempts to optimize the path if the specified point is visible from the current position. - /// @param[in] next The point to search toward. [(x, y, z]) - /// @param[in] pathOptimizationRange The maximum range to search. [Limit: > 0] - /// @param[in] navquery The query object used to build the corridor. - /// @param[in] filter The filter to apply to the operation. - void optimizePathVisibility(const float* next, const float pathOptimizationRange, - dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - /// Attempts to optimize the path using a local area search. (Partial replanning.) - /// @param[in] navquery The query object used to build the corridor. - /// @param[in] filter The filter to apply to the operation. - bool optimizePathTopology(dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - bool moveOverOffmeshConnection(dtPolyRef offMeshConRef, dtPolyRef* refs, - float* startPos, float* endPos, - dtNavMeshQuery* navquery); - - bool trimInvalidPath(dtPolyRef safeRef, const float* safePos, - dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - /// Checks the current corridor path to see if its polygon references remain valid. - /// @param[in] maxLookAhead The number of polygons from the beginning of the corridor to search. - /// @param[in] navquery The query object used to build the corridor. - /// @param[in] filter The filter to apply to the operation. - bool isValid(const int maxLookAhead, dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - /// Moves the position from the current location to the desired location, adjusting the corridor - /// as needed to reflect the change. - /// @param[in] npos The desired new position. [(x, y, z)] - /// @param[in] navquery The query object used to build the corridor. - /// @param[in] filter The filter to apply to the operation. - void movePosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - /// Moves the target from the curent location to the desired location, adjusting the corridor - /// as needed to reflect the change. - /// @param[in] npos The desired new target position. [(x, y, z)] - /// @param[in] navquery The query object used to build the corridor. - /// @param[in] filter The filter to apply to the operation. - void moveTargetPosition(const float* npos, dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - /// Loads a new path and target into the corridor. - /// @param[in] target The target location within the last polygon of the path. [(x, y, z)] - /// @param[in] path The path corridor. [(polyRef) * @p npolys] - /// @param[in] npath The number of polygons in the path. - void setCorridor(const float* target, const dtPolyRef* polys, const int npath); - - /// Gets the current position within the corridor. (In the first polygon.) - /// @return The current position within the corridor. - inline const float* getPos() const { return m_pos; } - - /// Gets the current target within the corridor. (In the last polygon.) - /// @return The current target within the corridor. - inline const float* getTarget() const { return m_target; } - - /// The polygon reference id of the first polygon in the corridor, the polygon containing the position. - /// @return The polygon reference id of the first polygon in the corridor. (Or zero if there is no path.) - inline dtPolyRef getFirstPoly() const { return m_npath ? m_path[0] : 0; } - - /// The polygon reference id of the last polygon in the corridor, the polygon containing the target. - /// @return The polygon reference id of the last polygon in the corridor. (Or zero if there is no path.) - inline dtPolyRef getLastPoly() const { return m_npath ? m_path[m_npath-1] : 0; } - - /// The corridor's path. - /// @return The corridor's path. [(polyRef) * #getPathCount()] - inline const dtPolyRef* getPath() const { return m_path; } - - /// The number of polygons in the current corridor path. - /// @return The number of polygons in the current corridor path. - inline int getPathCount() const { return m_npath; } -}; - -int dtMergeCorridorStartMoved(dtPolyRef* path, const int npath, const int maxPath, - const dtPolyRef* visited, const int nvisited); - -int dtMergeCorridorEndMoved(dtPolyRef* path, const int npath, const int maxPath, - const dtPolyRef* visited, const int nvisited); - -int dtMergeCorridorStartShortcut(dtPolyRef* path, const int npath, const int maxPath, - const dtPolyRef* visited, const int nvisited); - -#endif // DETOUTPATHCORRIDOR_H diff --git a/critterai/.svn/pristine/30/3065ed9f9fca63f7e0db3cd7bc19812a4b337ac1.svn-base b/critterai/.svn/pristine/30/3065ed9f9fca63f7e0db3cd7bc19812a4b337ac1.svn-base deleted file mode 100644 index 8ff6211e..00000000 --- a/critterai/.svn/pristine/30/3065ed9f9fca63f7e0db3cd7bc19812a4b337ac1.svn-base +++ /dev/null @@ -1,154 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOUROBSTACLEAVOIDANCE_H -#define DETOUROBSTACLEAVOIDANCE_H - -struct dtObstacleCircle -{ - float p[3]; ///< Position of the obstacle - float vel[3]; ///< Velocity of the obstacle - float dvel[3]; ///< Velocity of the obstacle - float rad; ///< Radius of the obstacle - float dp[3], np[3]; ///< Use for side selection during sampling. -}; - -struct dtObstacleSegment -{ - float p[3], q[3]; ///< End points of the obstacle segment - bool touch; -}; - - -class dtObstacleAvoidanceDebugData -{ -public: - dtObstacleAvoidanceDebugData(); - ~dtObstacleAvoidanceDebugData(); - - bool init(const int maxSamples); - void reset(); - void addSample(const float* vel, const float ssize, const float pen, - const float vpen, const float vcpen, const float spen, const float tpen); - - void normalizeSamples(); - - inline int getSampleCount() const { return m_nsamples; } - inline const float* getSampleVelocity(const int i) const { return &m_vel[i*3]; } - inline float getSampleSize(const int i) const { return m_ssize[i]; } - inline float getSamplePenalty(const int i) const { return m_pen[i]; } - inline float getSampleDesiredVelocityPenalty(const int i) const { return m_vpen[i]; } - inline float getSampleCurrentVelocityPenalty(const int i) const { return m_vcpen[i]; } - inline float getSamplePreferredSidePenalty(const int i) const { return m_spen[i]; } - inline float getSampleCollisionTimePenalty(const int i) const { return m_tpen[i]; } - -private: - int m_nsamples; - int m_maxSamples; - float* m_vel; - float* m_ssize; - float* m_pen; - float* m_vpen; - float* m_vcpen; - float* m_spen; - float* m_tpen; -}; - -dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData(); -void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr); - - -static const int DT_MAX_PATTERN_DIVS = 32; ///< Max numver of adaptive divs. -static const int DT_MAX_PATTERN_RINGS = 4; ///< Max number of adaptive rings. - -struct dtObstacleAvoidanceParams -{ - float velBias; - float weightDesVel; - float weightCurVel; - float weightSide; - float weightToi; - float horizTime; - unsigned char gridSize; ///< grid - unsigned char adaptiveDivs; ///< adaptive - unsigned char adaptiveRings; ///< adaptive - unsigned char adaptiveDepth; ///< adaptive -}; - -class dtObstacleAvoidanceQuery -{ -public: - dtObstacleAvoidanceQuery(); - ~dtObstacleAvoidanceQuery(); - - bool init(const int maxCircles, const int maxSegments); - - void reset(); - - void addCircle(const float* pos, const float rad, - const float* vel, const float* dvel); - - void addSegment(const float* p, const float* q); - - int sampleVelocityGrid(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, float* nvel, - const dtObstacleAvoidanceParams* params, - dtObstacleAvoidanceDebugData* debug = 0); - - int sampleVelocityAdaptive(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, float* nvel, - const dtObstacleAvoidanceParams* params, - dtObstacleAvoidanceDebugData* debug = 0); - - inline int getObstacleCircleCount() const { return m_ncircles; } - const dtObstacleCircle* getObstacleCircle(const int i) { return &m_circles[i]; } - - inline int getObstacleSegmentCount() const { return m_nsegments; } - const dtObstacleSegment* getObstacleSegment(const int i) { return &m_segments[i]; } - -private: - - void prepare(const float* pos, const float* dvel); - - float processSample(const float* vcand, const float cs, - const float* pos, const float rad, - const float* vel, const float* dvel, - dtObstacleAvoidanceDebugData* debug); - - dtObstacleCircle* insertCircle(const float dist); - dtObstacleSegment* insertSegment(const float dist); - - dtObstacleAvoidanceParams m_params; - float m_invHorizTime; - float m_vmax; - float m_invVmax; - - int m_maxCircles; - dtObstacleCircle* m_circles; - int m_ncircles; - - int m_maxSegments; - dtObstacleSegment* m_segments; - int m_nsegments; -}; - -dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery(); -void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr); - - -#endif // DETOUROBSTACLEAVOIDANCE_H diff --git a/critterai/.svn/pristine/30/30a12f546f3393c890696a7696a59bddad9e395c.svn-base b/critterai/.svn/pristine/30/30a12f546f3393c890696a7696a59bddad9e395c.svn-base deleted file mode 100644 index 7de2025f..00000000 --- a/critterai/.svn/pristine/30/30a12f546f3393c890696a7696a59bddad9e395c.svn-base +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(DefaultAreaDef))] -public sealed class DefaultAreaDefEditor - : Editor -{ - private CAINavEditorSettingsEditor.AreaGUIControl mAreaControl; - - void OnEnable() - { - mAreaControl = CAINavEditorSettingsEditor.CreateAreaControl("Default Area"); - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - DefaultAreaDef targ = (DefaultAreaDef)target; - - EditorGUILayout.Separator(); - - GUILayout.Label("Priority: " + targ.Priority); - - EditorGUILayout.Separator(); - - targ.DefaultArea = mAreaControl.OnGUI(targ.DefaultArea); - - EditorGUILayout.Separator(); - - GUILayout.Box( - "Input Build Processor\n\nApplies the area to all components in the build." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Area Definition : Default", false, NMBEditorUtil.AreaGroup)] - static void CreateAsset() - { - DefaultAreaDef item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/31/317aa9d965a24ee66651c91c7d269afb05292bdd.svn-base b/critterai/.svn/pristine/31/317aa9d965a24ee66651c91c7d269afb05292bdd.svn-base deleted file mode 100644 index e445fbdb..00000000 --- a/critterai/.svn/pristine/31/317aa9d965a24ee66651c91c7d269afb05292bdd.svn-base +++ /dev/null @@ -1,682 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNAVMESH_H -#define DETOURNAVMESH_H - -#include "DetourAlloc.h" -#include "DetourStatus.h" - -// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef. -// It is also recommended that you change dtHashRef() to a proper 64-bit hash. - -/// A handle to a polygon within a navigation mesh tile. -/// @ingroup detour -typedef unsigned int dtPolyRef; - -/// A handle to a tile within a navigation mesh. -/// @ingroup detour -typedef unsigned int dtTileRef; - -/// The maximum number of vertices per navigation polygon. -/// @ingroup detour -static const int DT_VERTS_PER_POLYGON = 6; - -/// @{ -/// @name Tile Serialization Constants -/// These constants are used to detect whether a navigation tile's data -/// and state format is compatible with the current build. -/// - -/// A magic number used to detect compatibility of navigation tile data. -static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; - -/// A version number used to detect compatibility of navigation tile data. -static const int DT_NAVMESH_VERSION = 7; - -/// A magic number used to detect the compatibility of navigation tile states. -static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; - -/// A version number used to detect compatibility of navigation tile states. -static const int DT_NAVMESH_STATE_VERSION = 1; - -/// @} - -/// A flag that indicates that an entity links to an external entity. -/// (E.g. A polygon edge is a portal that links to another polygon.) -static const unsigned short DT_EXT_LINK = 0x8000; - -/// A value that indicates the entity does not link to anything. -static const unsigned int DT_NULL_LINK = 0xffffffff; - -/// A flag that indicates that an off-mesh connection can be traversed in both directions. (Is bidirectional.) -static const unsigned int DT_OFFMESH_CON_BIDIR = 1; - -/// The maximum number of user defined area ids. -/// @ingroup detour -static const int DT_MAX_AREAS = 64; - -/// Tile flags used for various functions and fields. -/// For an example, see dtNavMesh::addTile(). -enum dtTileFlags -{ - /// The navigation mesh owns the tile memory and is responsible for freeing it. - DT_TILE_FREE_DATA = 0x01, -}; - -/// Vertex flags returned by dtNavMeshQuery::findStraightPath. -enum dtStraightPathFlags -{ - DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position in the path. - DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position in the path. - DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection. -}; - -/// Flags representing the type of a navigation mesh polygon. -enum dtPolyTypes -{ - /// The polygon is a standard convex polygon that is part of the surface of the mesh. - DT_POLYTYPE_GROUND = 0, - /// The polygon is an off-mesh connection consisting of two vertices. - DT_POLYTYPE_OFFMESH_CONNECTION = 1, -}; - - -/// Defines a polyogn within a dtMeshTile object. -/// @ingroup detour -struct dtPoly -{ - /// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.) - unsigned int firstLink; - - /// The indices of the polygon's vertices. - /// The actual vertices are located in dtMeshTile::verts. - unsigned short verts[DT_VERTS_PER_POLYGON]; - - /// Packed data representing neighbor polygons references and flags for each edge. - unsigned short neis[DT_VERTS_PER_POLYGON]; - - /// The user defined polygon flags. - unsigned short flags; - - /// The number of vertices in the polygon. - unsigned char vertCount; - - /// The bit packed area id and polygon type. - /// @note Use the structure's set and get methods to acess this value. - unsigned char areaAndtype; - - /// Sets the user defined area id. [Limit: < #DT_MAX_AREAS] - inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); } - - /// Sets the polygon type. (See: #dtPolyTypes.) - inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); } - - /// Gets the user defined area id. - inline unsigned char getArea() const { return areaAndtype & 0x3f; } - - /// Gets the polygon type. (See: #dtPolyTypes) - inline unsigned char getType() const { return areaAndtype >> 6; } -}; - -/// Defines the location of detail sub-mesh data within a dtMeshTile. -struct dtPolyDetail -{ - unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array. - unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array. - unsigned char vertCount; ///< The number of vertices in the sub-mesh. - unsigned char triCount; ///< The number of triangles in the sub-mesh. -}; - -/// Defines a link between polygons. -/// @note This structure is rarely if ever used by the end user. -/// @see dtMeshTile -struct dtLink -{ - dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.) - unsigned int next; ///< Index of the next link. - unsigned char edge; ///< Index of the polygon edge that owns this link. - unsigned char side; ///< If a boundary link, defines on which side the link is. - unsigned char bmin; ///< If a boundary link, defines the minimum sub-edge area. - unsigned char bmax; ///< If a boundary link, defines the maximum sub-edge area. -}; - -/// Bounding volume node. -/// @note This structure is rarely if ever used by the end user. -/// @see dtMeshTile -struct dtBVNode -{ - unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)] - unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)] - int i; ///< The node's index. (Negative for escape sequence.) -}; - -/// Defines an navigation mesh off-mesh connection within a dtMeshTile object. -/// An off-mesh connection is a user defined traversable connection made up to two vertices. -struct dtOffMeshConnection -{ - /// The endpoints of the connection. [(ax, ay, az, bx, by, bz)] - float pos[6]; - - /// The radius of the endpoints. [Limit: >= 0] - float rad; - - /// The polygon reference of the connection within the tile. - unsigned short poly; - - /// Link flags. - /// @note These are not the connection's user defined flags. Those are assigned via the - /// connection's dtPoly definition. These are link flags used for internal purposes. - unsigned char flags; - - /// End point side. - unsigned char side; - - /// The id of the offmesh connection. (User assigned when the navigation mesh is built.) - unsigned int userId; -}; - -/// Provides high level information related to a dtMeshTile object. -/// @ingroup detour -struct dtMeshHeader -{ - int magic; ///< Tile magic number. (Used to identify the data format.) - int version; ///< Tile data format version number. - int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer) - int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer) - int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer) - unsigned int userId; ///< The user defined id of the tile. - int polyCount; ///< The number of polygons in the tile. - int vertCount; ///< The number of vertices in the tile. - int maxLinkCount; ///< The number of allocated links. - int detailMeshCount; ///< The number of sub-meshes in the detail mesh. - - /// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.) - int detailVertCount; - - int detailTriCount; ///< The number of triangles in the detail mesh. - int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.) - int offMeshConCount; ///< The number of off-mesh connections. - int offMeshBase; ///< The index of the first polygon which is an off-mesh connection. - float walkableHeight; ///< The height of the agents using the tile. - float walkableRadius; ///< The radius of the agents using the tile. - float walkableClimb; ///< The maximum climb height of the agents using the tile. - float bmin[3]; ///< The minimum bounds of the tile's AABB. [(x, y, z)] - float bmax[3]; ///< The maximum bounds of the tile's AABB. [(x, y, z)] - - /// The bounding volume quantization factor. - float bvQuantFactor; -}; - -/// Defines a navigation mesh tile. -/// @ingroup detour -struct dtMeshTile -{ - unsigned int salt; ///< Counter describing modifications to the tile. - - unsigned int linksFreeList; ///< Index to the next free link. - dtMeshHeader* header; ///< The tile header. - dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount] - float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount] - dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount] - dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount] - - /// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount] - float* detailVerts; - - /// The detail mesh's triangles. [(vertA, vertB, vertC) * dtMeshHeader::detailTriCount] - unsigned char* detailTris; - - /// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount] - /// (Will be null if bounding volumes are disabled.) - dtBVNode* bvTree; - - dtOffMeshConnection* offMeshCons; ///< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount] - - unsigned char* data; ///< The tile data. (Not directly accessed under normal situations.) - int dataSize; ///< Size of the tile data. - int flags; ///< Tile flags. (See: #dtTileFlags) - dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid. -}; - -/// Configuration parameters used to define multi-tile navigation meshes. -/// The values are used to allocate space during the initialization of a navigation mesh. -/// @see dtNavMesh::init() -/// @ingroup detour -struct dtNavMeshParams -{ - float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)] - float tileWidth; ///< The width of each tile. (Along the x-axis.) - float tileHeight; ///< The height of each tile. (Along the z-axis.) - int maxTiles; ///< The maximum number of tiles the navigation mesh can contain. - int maxPolys; ///< The maximum number of polygons each tile can contain. -}; - -/// A navigation mesh based on tiles of convex polygons. -/// @ingroup detour -class dtNavMesh -{ -public: - dtNavMesh(); - ~dtNavMesh(); - - /// @{ - /// @name Initialization and Tile Management - - /// Initializes the navigation mesh for tiled use. - /// @param[in] params Initialization parameters. - /// @return The status flags for the operation. - dtStatus init(const dtNavMeshParams* params); - - /// Initializes the navigation mesh for single tile use. - /// @param[in] data Data of the new tile. (See: #dtCreateNavMeshData) - /// @param[in] dataSize The data size of the new tile. - /// @param[in] flags The tile flags. (See: #dtTileFlags) - /// @return The status flags for the operation. - /// @see dtCreateNavMeshData - dtStatus init(unsigned char* data, const int dataSize, const int flags); - - /// The navigation mesh initialization params. - const dtNavMeshParams* getParams() const; - - /// Adds a tile to the navigation mesh. - /// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData) - /// @param[in] dataSize Data size of the new tile mesh. - /// @param[in] flags Tile flags. (See: #dtTileFlags) - /// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0] - /// @param[out] result The tile reference. (If the tile was succesfully added.) [opt] - /// @return The status flags for the operation. - dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result); - - /// Removes the specified tile from the navigation mesh. - /// @param[in] ref The reference of the tile to remove. - /// @param[out] data Data associated with deleted tile. - /// @param[out] dataSize Size of the data associated with deleted tile. - /// @return The status flags for the operation. - dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize); - - /// @} - - /// @{ - /// @name Query Functions - - /// Calculates the tile grid location for the specified world position. - /// @param[in] pos The world position for the query. [(x, y, z)] - /// @param[out] tx The tile's x-location. (x, y) - /// @param[out] ty The tile's y-location. (x, y) - void calcTileLoc(const float* pos, int* tx, int* ty) const; - - /// Gets the tile at the specified grid location. - /// @param[in] x The tile's x-location. (x, y, layer) - /// @param[in] y The tile's y-location. (x, y, layer) - /// @param[in] layer The tile's layer. (x, y, layer) - /// @return The tile, or null if the tile does not exist. - const dtMeshTile* getTileAt(const int x, const int y, const int layer) const; - - /// Gets all tiles at the specified grid location. (All layers.) - /// @param[in] x The tile's x-location. (x, y) - /// @param[in] y The tile's y-location. (x, y) - /// @param[out] tiles A pointer to an array of tiles that will hold the result. - /// @param[in] maxTiles The maximum tiles the tiles parameter can hold. - /// @return The number of tiles returned in the tiles array. - int getTilesAt(const int x, const int y, - dtMeshTile const** tiles, const int maxTiles) const; - - /// Gets the tile reference for the tile at specified grid location. - /// @param[in] x The tile's x-location. (x, y, layer) - /// @param[in] y The tile's y-location. (x, y, layer) - /// @param[in] layer The tile's layer. (x, y, layer) - /// @return The tile reference of the tile, or 0 if there is none. - dtTileRef getTileRefAt(int x, int y, int layer) const; - - /// Gets the tile reference for the specified tile. - /// @param[in] tile The tile. - /// @return The tile reference of the tile. - dtTileRef getTileRef(const dtMeshTile* tile) const; - - /// Gets the tile for the specified tile reference. - /// @param[in] ref The tile reference of the tile to retrieve. - /// @return The tile for the specified reference, or null if the - /// reference is invalid. - const dtMeshTile* getTileByRef(dtTileRef ref) const; - - /// The maximum number of tiles supported by the navigation mesh. - /// @return The maximum number of tiles supported by the navigation mesh. - int getMaxTiles() const; - - /// Gets the tile at the specified index. - /// @param[in] i The tile index. [Limit: 0 >= index < #getMaxTiles()] - /// @return The tile at the specified index. - const dtMeshTile* getTile(int i) const; - - /// Gets the tile and polygon for the specified polygon reference. - /// @param[in] ref The reference for the a polygon. - /// @param[out] tile The tile containing the polygon. - /// @param[out] poly The polygon. - /// @return The status flags for the operation. - dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; - - /// Returns the tile and polygon for the specified polygon reference. - /// @param[in] ref A known valid reference for a polygon. - /// @param[out] tile The tile containing the polygon. - /// @param[out] poly The polygon. - void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; - - /// Checks the validity of a polygon reference. - /// @param[in] ref The polygon reference to check. - /// @return True if polygon reference is valid for the navigation mesh. - bool isValidPolyRef(dtPolyRef ref) const; - - /// Gets the polygon reference for the tile's base polygon. - /// @param[in] tile The tile. - /// @return The polygon reference for the base polygon in the specified tile. - dtPolyRef getPolyRefBase(const dtMeshTile* tile) const; - - /// Gets the endpoints for an off-mesh connection, ordered by "direction of travel". - /// @param[in] prevRef The reference of the polygon before the connection. - /// @param[in] polyRef The reference of the off-mesh connection polygon. - /// @param[out] startPos The start position of the off-mesh connection. [(x, y, z)] - /// @param[out] endPos The end position of the off-mesh connection. [(x, y, z)] - /// @return The status flags for the operation. - dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const; - - /// Gets the specified off-mesh connection. - /// @param[in] ref The polygon reference of the off-mesh connection. - /// @return The specified off-mesh connection, or null if the polygon reference is not valid. - const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const; - - /// @} - - /// @{ - /// @name State Management - /// These functions do not effect #dtTileRef or #dtPolyRef's. - - /// Sets the user defined flags for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[in] flags The new flags for the polygon. - /// @return The status flags for the operation. - dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags); - - /// Gets the user defined flags for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[out] resultFlags The polygon flags. - /// @return The status flags for the operation. - dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const; - - /// Sets the user defined area for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[in] area The new area id for the polygon. [Limit: < #DT_MAX_AREAS] - /// @return The status flags for the operation. - dtStatus setPolyArea(dtPolyRef ref, unsigned char area); - - /// Gets the user defined area for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[out] resultArea The area id for the polygon. - /// @return The status flags for the operation. - dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const; - - /// Gets the size of the buffer required by #storeTileState to store the specified tile's state. - /// @param[in] tile The tile. - /// @return The size of the buffer required to store the state. - int getTileStateSize(const dtMeshTile* tile) const; - - /// Stores the non-structural state of the tile in the specified buffer. (Flags, area ids, etc.) - /// @param[in] tile The tile. - /// @param[out] data The buffer to store the tile's state in. - /// @param[in] maxDataSize The size of the data buffer. [Limit: >= #getTileStateSize] - /// @return The status flags for the operation. - dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const; - - /// Restores the state of the tile. - /// @param[in] tile The tile. - /// @param[in] data The new state. (Obtained from #storeTileState.) - /// @param[in] maxDataSize The size of the state within the data buffer. - /// @return The status flags for the operation. - dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize); - - /// @} - - /// @{ - /// @name Encoding and Decoding - /// These functions are generally meant for internal use only. - - /// Derives a standard polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] salt The tile's salt value. - /// @param[in] it The index of the tile. - /// @param[in] ip The index of the polygon within the tile. - inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const - { - return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip; - } - - /// Decodes a standard polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference to decode. - /// @param[out] salt The tile's salt value. - /// @param[out] it The index of the tile. - /// @param[out] ip The index of the polygon within the tile. - /// @see #encodePolyId - inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const - { - const dtPolyRef saltMask = ((dtPolyRef)1<> (m_polyBits+m_tileBits)) & saltMask); - it = (unsigned int)((ref >> m_polyBits) & tileMask); - ip = (unsigned int)(ref & polyMask); - } - - /// Extracts a tile's salt value from the specified polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference. - /// @see #encodePolyId - inline unsigned int decodePolyIdSalt(dtPolyRef ref) const - { - const dtPolyRef saltMask = ((dtPolyRef)1<> (m_polyBits+m_tileBits)) & saltMask); - } - - /// Extracts the tile's index from the specified polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference. - /// @see #encodePolyId - inline unsigned int decodePolyIdTile(dtPolyRef ref) const - { - const dtPolyRef tileMask = ((dtPolyRef)1<> m_polyBits) & tileMask); - } - - /// Extracts the polygon's index (within its tile) from the specified polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference. - /// @see #encodePolyId - inline unsigned int decodePolyIdPoly(dtPolyRef ref) const - { - const dtPolyRef polyMask = ((dtPolyRef)1<header->bvQuantFactor; -const dtBVNode* n = &tile->bvTree[i]; -if (n->i >= 0) -{ - // This is a leaf node. - float worldMinX = tile->header->bmin[0] + n->bmin[0]*cs; - float worldMinY = tile->header->bmin[0] + n->bmin[1]*cs; - // Etc... -} -@endcode - -@struct dtMeshTile -@par - -Tiles generally only exist within the context of a dtNavMesh object. - -Some tile content is optional. For example, a tile may not contain any -off-mesh connections. In this case the associated pointer will be null. - -If a detail mesh exists it will share vertices with the base polygon mesh. -Only the vertices unique to the detail mesh will be stored in #detailVerts. - -@warning Tiles returned by a dtNavMesh object are not guarenteed to be populated. -For example: The tile at a location might not have been loaded yet, or may have been removed. -In this case, pointers will be null. So if in doubt, check the polygon count in the -tile's header to determine if a tile has polygons defined. - -@var float dtOffMeshConnection::pos[6] -@par - -For a properly built navigation mesh, vertex A will always be within the bounds of the mesh. -Vertex B is not required to be within the bounds of the mesh. - -*/ diff --git a/critterai/.svn/pristine/31/31e64f76d9fbb92f37ad649668eb3bf9b4f76e40.svn-base b/critterai/.svn/pristine/31/31e64f76d9fbb92f37ad649668eb3bf9b4f76e40.svn-base deleted file mode 100644 index d98d5866..00000000 Binary files a/critterai/.svn/pristine/31/31e64f76d9fbb92f37ad649668eb3bf9b4f76e40.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/32/328360cbd6eb05e52b0706ea85557de30a79b532.svn-base b/critterai/.svn/pristine/32/328360cbd6eb05e52b0706ea85557de30a79b532.svn-base deleted file mode 100644 index a1c253d0..00000000 --- a/critterai/.svn/pristine/32/328360cbd6eb05e52b0706ea85557de30a79b532.svn-base +++ /dev/null @@ -1,1112 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Hashtable; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Builds an open heightfield from the solid data contained by an - * {@link SolidHeightfield}. It does this by locating and creating spans - * representing the area above spans within the source field that have a - * specified flag. - *

Options are provided to generate neighbor, distance field, and - * region information for the open span data

- *

Example of a fully formed open heightfield. (I.e. With region - * information.) Only the floor of the spans is shown.

- *

- * - *

- * @see Introduction to Height Fields - * @see Region Generation - * @see OpenHeightfield - * @see OpenHeightSpan - */ -public final class OpenHeightfieldBuilder -{ - - /* - * Design notes: - * - * Recast references: - * rcBuildCompactHeightfield in Recast.cpp - * rcBuildDistanceField in RecastRegion.cpp - * rcBuildRegions in RecastRegion.cpp - * - * Configuration getters won't be added until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private final int mMinTraversableHeight; - private final int mMaxTraversableStep; - private final int mSmoothingThreshold; - private final int mTraversableAreaBorderSize; - private final int mFilterFlags; - private final boolean mUseConservativeExpansion; - - private final ArrayList mRegionAlgorithms - = new ArrayList(); - - /** - * Constructor - * - * @param minTraversableHeight Represents the minimum floor to ceiling - * height that will still allow the floor area to be considered walkable. - *

Permits detection of overhangs in the geometry which make the - * geometry below become unwalkable.

- *

Constraints: > 0

- * - * @param maxTraversableStep Represents the maximum ledge height that - * is considered to still be walkable. - *

Prevents minor deviations in height from improperly showing as - * obstructions. Permits detection of stair-like structures, curbs, etc. - *

- *

Constraints: >= 0

- * - * @param traversableAreaBorderSize Represents the closest any part - * of the navmesh can get to an obstruction in the source mesh. - *

Usually set to the maximum bounding radius of entities utilizing - * the navmesh for navigation decisions.

- *

Constraints: >= 0

- * - * @param smoothingThreshold The amount of smoothing to be performed - * when generating the distance field. - *

This value impacts region formation and border detection. A higher - * value results in generally larger regions and larger border sizes. - * A value of zero will disable smoothing.

- *

Constraints: 0 <= value <= 4

- * - * @param filterFlags The flags used to determine which spans from the - * source {@link SolidHeightfield} should be used to build the - * {@link OpenHeightfield}. Only those spans which whose flags - * exactly match the filter flag will be considered for inclusion in - * the generated open field. - *

Note: Spans from the source field which do not match the filter - * flags are still taken into account as height obstructions.

- * - * @param useConservativeExpansion Applies extra algorithms to regions - * to help prevent poorly formed regions from forming. - *

If the navigation mesh is missing sections that should be present, - * then enabling this feature will likely fix the problem

- *

Enabling this feature significantly increased processing cost.

- * - * @param regionAlgorithms A list of the algorithms to run after - * initial region generation is complete. The algorithms will be run - * in the order of the list. - */ - public OpenHeightfieldBuilder(int minTraversableHeight - , int maxTraversableStep - , int traversableAreaBorderSize - , int smoothingThreshold - , int filterFlags - , boolean useConservativeExpansion - , ArrayList regionAlgorithms) - { - mMaxTraversableStep = Math.max(0, maxTraversableStep); - mMinTraversableHeight = Math.max(1, minTraversableHeight); - mTraversableAreaBorderSize = Math.max(0, traversableAreaBorderSize); - mFilterFlags = filterFlags; - mSmoothingThreshold = Math.min(4, Math.max(0, smoothingThreshold)); - mUseConservativeExpansion = useConservativeExpansion; - if (regionAlgorithms != null) - mRegionAlgorithms.addAll(regionAlgorithms); - } - - /** - * Performs a smoothing pass on the distance field data. - *

This operation depends on distance field information. So the - * {@link #generateDistanceField(OpenHeightfield)} operation must be - * run before this operation.

- *

This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

- * @param field A populated open height field with distance field data - * already generated. - */ - public void blurDistanceField(OpenHeightfield field) - { - // TODO: DOC: Need to find source documentation. - // The basic process is to combine a span's original distance with - // that of its neighbors. - - if (field == null) - return; - - // Reference: Neighbor searches and nomenclature. - // http://www.critterai.org/?q=nmgen_hfintro#nsearch - - if (mSmoothingThreshold <= 0) - // Not configured to perform smoothing. Exit early. - return; - - // TODO: EVAL: Try to optimize out this hash table. - /* - * Holds information on the final blurred distance for each span. - * Key = span - * Value = new blurred distance. - */ - final Hashtable blurResults - = new Hashtable(field.spanCount()); - - // Loop through all spans. - final OpenHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - final int origDist = span.distanceToBorder(); - if (origDist <= mSmoothingThreshold) - { - // This span is at the minimum threshold. - // Add it to the results and continue to next span. - blurResults.put(span, mSmoothingThreshold); - continue; - } - - int workingDist = origDist; - // Loop through neighbors. - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); // axis-neighbor. - if (nSpan == null) - // No neighbor on this side. Self buff using own - // original distance. - workingDist += origDist * 2; - else - { - // Neighbor on this side. Add its distance to the - // current span. - workingDist += nSpan.distanceToBorder(); - // Get diagonal neighbor. - nSpan = nSpan.getNeighbor((dir+1) & 0x3); - if (nSpan == null) - // No diagonal neighbor. Self buff using own - // original distance. - workingDist += origDist; - else - // Has diagonal neighbor. Add its distance to - // the current span. - workingDist += nSpan.distanceToBorder(); - } - } - // Adjust and store the result. - // Don't know the why behind this specific formula. - blurResults.put(span, ((workingDist + 5) / 9)); - } - - // Replace the original distance information with the new - // distance information. - for (OpenHeightSpan span : blurResults.keySet()) - { - span.setDistanceToBorder(blurResults.get(span)); - } - - // Reset the known min/max border distance. This will force a - // recalculation if the values are needed later. - field.clearBorderDistanceBounds(); - } - - /** - * Builds an {@link OpenHeightfield} from the provided - * {@link SolidHeightfield} based on the configuration settings. - * @param sourceField The solid field to derive the open field from. - * @param performFullGeneration If TRUE, neighbor link, distance field - * (including blurring), - * and region information will be generated. If FALSE, only the spans - * will be generated. - */ - public OpenHeightfield build(SolidHeightfield sourceField - , boolean performFullGeneration) - { - if (sourceField == null) - return null; - - // Construct the open field object. - OpenHeightfield result = new OpenHeightfield(sourceField.boundsMin() - , sourceField.boundsMax() - , sourceField.cellSize() - , sourceField.cellHeight()); - - // Loop through all solid field grid locations. - for (int depthIndex = 0 - ; depthIndex < sourceField.depth() - ; depthIndex++) - { - for (int widthIndex = 0 - ; widthIndex < sourceField.width() - ; widthIndex++) - { - // The lowest span in this column. - OpenHeightSpan baseSpan = null; - // The last span processed in this column. - OpenHeightSpan previousSpan = null; - // Climb up the list of spans at this grid location. - // A loop will only occur if the grid location has at least - // one span. - for (HeightSpan span = - sourceField.getData(widthIndex, depthIndex) - ; span != null - ; span = span.next()) - { - // Ignore spans that do not match the filter flags. - if (span.flags() != mFilterFlags) - continue; - - /* - * Determine the open space between this span and the next - * higher span. Note that the flag of the ceiling span - * does not matter. All spans matter when it comes to - * this step. - */ - int floor = span.max(); - int ceiling = (span.next() != null ? - span.next().max() : Integer.MAX_VALUE); - - // Add the span. - // Note that the original span flags are being discarded. - OpenHeightSpan oSpan = new OpenHeightSpan(floor - , (ceiling - floor)); - if (baseSpan == null) - // This is the first span created at this grid location. - baseSpan = oSpan; - if (previousSpan != null) - // There is a span at a lower location in this grid - // location. Link the lower (previous) span to this - // span. - previousSpan.setNext(oSpan); - previousSpan = oSpan; - result.incrementSpanCount(); - } - if (baseSpan != null) - { - // There is one or more spans at this grid location. - // Add the first span in the chain to the spans hash. - result.addData(widthIndex, depthIndex, baseSpan); - } - } - } - - if (performFullGeneration) - { - // Need to perform a full generation. - generateNeighborLinks(result); - generateDistanceField(result); - blurDistanceField(result); - generateRegions(result); - } - - return result; - - } - - /** - * Generates distance field information. - * The {@link OpenHeightSpan#distanceToBorder()} information is generated - * for all spans in the field. - *

A boundary is a span with a missing neighbor. It will always have - * a distance value of zero. A span is not a boundary if is has 4 neighbors. - * Its boundary distance value will be higher the further it is from a - * boundary span.

- *

All distance values are relative and do not represent explicit - * distance values (such as grid unit distance). The algorithm which is - * used results in an approximation only. It is not exhaustive.

- *

This operation depends on neighbor information. So the - * {@link #generateNeighborLinks(OpenHeightfield)} operation must be - * run before this operation.

- *

This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

- *

The data generated by this operation is required by - * {@link #blurDistanceField(OpenHeightfield)} and - * {@link #generateRegions(OpenHeightfield)}

- * @param field A field with spans and neighbor information already - * generated. - */ - public void generateDistanceField(OpenHeightfield field) - { - - // TODO: DOC: Need to find source documentation for this algorithm. - - if (field == null) - return; - - // Reference: Neighbor searches and nomenclature. - // http://www.critterai.org/?q=nmgen_hfintro#nsearch - - // Enumerated values for border distance: - - // Represents a border span. The value for a border span will never be - // changed during any stage. - final int BORDER = 0; - - // Represents an uninitialized non-border span. - // All non-border spans will have this value going into pass 1. - // No span will have this value by the end of pass 1. - final int NEEDS_INIT = Integer.MAX_VALUE; - - /* - * Initialization pass. - * Loop through each span. - * Set distance to BORDER for boundary spans. (Spans with less than - * 4 known neighbors.) - * Set distance to NEEDS_INIT for non-boundary spans. - */ - final OpenHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - // Perform 8-neighbor search. If any neighbor is missing, this - // is a border. - boolean isBorder = false; - for (int dir = 0; dir < 4; dir++) - { - final OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null - || nSpan.getNeighbor(dir == 3 ? 0 : dir + 1) == null) - { - // Either this axis-neighbor or the diagonal-neighbor - // associated with it is missing. This is a border span. - isBorder = true; - break; - } - } - if (isBorder) - // Mark as a border span. - span.setDistanceToBorder(BORDER); - else - // Marks as a non-border span that needs initialization. - span.setDistanceToBorder(NEEDS_INIT); - } - - /* - * The next two phases basically check the neighbors of a span and - * set the span's distance field to be slightly greater than the - * neighbor with the lowest border distance. Distance is increased - * slightly more for diagonal-neighbors than for axis-neighbors. - * - * Example: - * Span.dist = 5 // Current estimated distance from border. - * Neighor1.dist = 3 - * Neighor2.dist = 1 <- Neighbor with lowest border distance. - * Neighor3.dist = 2 - * Neighor4.dist = 4 - * Then set Span.dist = Neighbor2.dist + 2 - * - * See the first pass (below) for comments that detail the algorithm. - */ - - /* - * Pass 1 - * During this pass, the following neighbors are checked: - * (-1, 0) (-1, -1) (0, -1) (1, -1) - * - * There is a special case during this pass since non-border spans may - * have a value of NEEDS_INIT: If a neighbor's border distance is not - * known, then it is treated at if it is a border span. - * - * By the end of this pass, no spans will have the value NEEDS_INIT - * since all non-border spans will have a neighbor that forces - * its value to change. - */ - - // Loop through all spans. - iter.reset(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - int dist = span.distanceToBorder(); - if (dist == BORDER) - // This is a border cell. Skip it. - continue; - // This span is guaranteed to have 4 axis neighbors. - // (-1, 0) Guaranteed to exist. - OpenHeightSpan nSpan = span.getNeighbor(0); - int ndist = nSpan.distanceToBorder(); - /* - * At this point, dist is guaranteed to equal NEEDS_INIT. - * (This is the first time this span has been selected for - * change.) So the value of dist will always have its value set - * to slightly higher than this first neighbor. - */ - if (ndist == NEEDS_INIT) - // Don't know how far from border this neighbor is. - // Default to slightly away from the border. - dist = 1; - else - // Set to slightly further from the border than this neighbor. - dist = ndist + 2; - // (-1, -1) Diagonal. Not guaranteed to exist. - nSpan = nSpan.getNeighbor(3); - if (nSpan != null) - { - // There is a diagonal neighbor. - ndist = nSpan.distanceToBorder(); - if (ndist == NEEDS_INIT) - // Don't know how far from border this neighbor is. - // Default to slightly away from the border. - ndist = 2; - else - // Set to slightly further from the border than - // this neighbor. - ndist += 3; - if (ndist < dist) - /* - * This neighbor is closer to the border than - * previously detected neighbors. Use this neighbor's - * increment. (I.e. Slightly further from border than - * this neighbor.) - */ - dist = ndist; - } - nSpan = span.getNeighbor(3); // (0, -1) Guaranteed to exist. - ndist = nSpan.distanceToBorder(); - if (ndist == NEEDS_INIT) - // Don't know how far from border this neighbor is. - // Default to slightly away from the border. - ndist = 1; - else - // Set to slightly further from the border than this neighbor. - ndist += 2; - if (ndist < dist) - // This neighbor is closer to the border than previously - // detected neighbors. Use this neighbor's increment. - // (I.e. Slightly further from border than this neighbor.) - dist = ndist; - // (1, -1) Diagonal. Not guaranteed to exist. - nSpan = nSpan.getNeighbor(2); - // More of the same. So no new comments. - if (nSpan != null) - { - ndist = nSpan.distanceToBorder(); - if (ndist == NEEDS_INIT) - ndist = 2; - else - ndist += 3; - if (ndist < dist) - dist = ndist; - } - // At this point, dist will contain this shortest estimated - // distance. Set the span to this value. - span.setDistanceToBorder(dist); - } - - /* - * Pass 2 - * During this pass, the following neighbors are checked: - * (1, 0) (1, 1) (0, 1) (-1, 1) - * - * Besides checking different neighbors, this pass performs its - * grid search in reverse order. - * - * This pass does the same thing as the first pass, but is much - * simpler because it doesn't need to handle the NEEDS_INIT special - * case. - * - * Minimal commenting is provided since nothing new is happening - * here that isn't already described in the the previous pass. - */ - - // Loop through all spans in reverse order. The looping method is - // slightly more complex since the standard iterator cannot be used. - for (int depthIndex = field.depth() - 1; depthIndex >= 0; depthIndex--) - { - for (int widthIndex = field.width() - 1 - ; widthIndex >= 0 - ; widthIndex--) - { - // Loop through all spans in the current grid location. - for (OpenHeightSpan span = - field.getData(widthIndex, depthIndex) - ; span != null - ; span = span.next()) - { - int dist = span.distanceToBorder(); - if (dist == BORDER) continue; // Border cells never change. - OpenHeightSpan nSpan = span.getNeighbor(2); // (1, 0) - int ndist = nSpan.distanceToBorder(); - ndist = nSpan.distanceToBorder() + 2; - if (ndist < dist) - dist = ndist; - nSpan = nSpan.getNeighbor(1); // (1, 1) - if (nSpan != null) - { - ndist = nSpan.distanceToBorder() + 3; - if (ndist < dist) - dist = ndist; - } - nSpan = span.getNeighbor(1); // (0, 1) - ndist = nSpan.distanceToBorder(); - ndist = nSpan.distanceToBorder() + 2; - if (ndist < dist) - dist = ndist; - nSpan = nSpan.getNeighbor(0); // (-1, 1) - if (nSpan != null) - { - ndist = nSpan.distanceToBorder() + 3; - if (ndist < dist) - dist = ndist; - } - span.setDistanceToBorder(dist); - } - } - } - - // Reset the known min/max border distance. This will force a - // recalculation if the values are needed later. - field.clearBorderDistanceBounds(); - - } - - /** - * Generates axis-neighbor link information for all spans in the field. - * This information is required for algorithms which perform neighbor - * searches. - *

After this operation is run, the - * {@link OpenHeightSpan#getNeighbor(int)} operation can be used for - * neighbor searches.

- *

This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

- *

The data generated by this operation is required by - * {@link #generateDistanceField(OpenHeightfield)}

- * @param field A field already loaded with span information. - * @see Neighbor Searches - */ - public void generateNeighborLinks(OpenHeightfield field) - { - if (field == null) - return; - - // Loop through all spans and generate neighbor information. - OpenHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - // Loop through all neighbor grid locations and check to see if - // any of their spans are accessible from this span. - for (int dir = 0; dir < 4; dir++) - { - // Get the neighbor offset for this direction. - final int nWidthIndex = - (iter.widthIndex() + BoundedField.getDirOffsetWidth(dir)); - final int nDepthIndex = - (iter.depthIndex() + BoundedField.getDirOffsetDepth(dir)); - /* - * Loop through all spans in the neighbor grid location. - * Note: Because of the way solid heightfields are built, only - * one span in each neighbor column can ever meet the - * conditions to be a neighbor of the current span. - */ - for (OpenHeightSpan nSpan = - field.getData(nWidthIndex, nDepthIndex) - ; nSpan != null - ; nSpan = nSpan.next()) - { - // Select the floor, current or neighbor span, that is - // higher. - int maxFloor = Math.max(span.floor(), nSpan.floor()); - // Select the ceiling, current or neighbor span, this is - // lower. - int minCeiling = Math.min(span.ceiling(), nSpan.ceiling()); - /* - * The above values are used to determine if the the gap - * formed by the two spans is large enough for agents to - * walk through? E.g. Without bumping its head on anything. - */ - if ((minCeiling - maxFloor) >= mMinTraversableHeight - && Math.abs(nSpan.floor() - span.floor()) - <= mMaxTraversableStep) - { - // There is space to walk between current and neighbor - // span, and the step up/down between this and - // neighbor span is acceptable. - span.setNeighbor(dir, nSpan); - break; - } - } - } - } - - } - - /** - * Groups spans into contiguous regions using an watershed based algorithm. - *

This operation depends on neighbor and distance field information. - * So the {@link #generateNeighborLinks(OpenHeightfield)} and - * {@link #generateDistanceField(OpenHeightfield)} operations must be - * run before this operation.

- *

This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

- * @param field A field with span, neighbor, and distance information - * fully generated. - */ - public void generateRegions(OpenHeightfield field) - { - if (field == null) - return; - /* - * Watershed Algorithm - * - * Reference: http://en.wikipedia.org/wiki/Watershed_%28algorithm%29 - * A good visualization: - * http://artis.imag.fr/Publications/2003/HDS03/ (PDF) - * - * Summary: - * - * This algorithm utilizes the span.distanceToBorder() value, which - * is generated by the generateDistanceField() operation. - * - * Using the watershed analogy, the spans which are furthest from - * a border (highest distance to border) represent the lowest points - * in the watershed. A border span represents the highest possible - * water level. - * - * The main loop iterates, starting at the lowest point in the - * watershed, then incrementing with each loop until the highest - * allowed water level is reached. This slowly "floods" the spans - * starting at the lowest points. - * - * (Remember: From this algorithm's point of view "lower" refers - * to distance from a border, not height within the heightfield.) - * - * During each iteration of the loop, spans that are below the - * current water level are located and an attempt is made to either - * add them to exiting regions or create new regions from them. - * - * During the region expansion phase, if a newly flooded span - * borders on an existing region, it is usually added to the region. - * - * Any newly flooded span that survives the region expansion phase - * is used as a seed for a new region. - * - * At the end of the main loop, a final region expansion is - * performed which should catch any stray spans that escaped region - * assignment during the main loop. - */ - - /* - * Represents the minimum distance to an obstacle that is considered - * traversable. I.e. Can't traverse spans closer than this distance - * to a border. This provides a way of artificially capping the - * height to which watershed flooding can occur. - * I.e. Don't let the algorithm flood all the way to the actual border. - * - * We add the minimum border distance to take into account the - * blurring algorithm which can result in a border span having a - * border distance > 0. - * - */ - final int minDist = - mTraversableAreaBorderSize + field.minBorderDistance(); - - // TODO: EVAL: Figure out why this iteration limit is needed. - final int expandIterations = 4 + (mTraversableAreaBorderSize * 2); - - /* - * This value represents the current distance from the border which - * is to be searched. The search starts at the maximum distance then - * moves toward zero. (Toward borders.) - * - * This number will always be divisible by 2. - */ - int dist = (field.maxBorderDistance() - 1) & ~1; - - /* - * Contains a list of spans that are considered to be flooded and - * therefore are ready to be processed. This list may contain nulls - * at certain points in the process. Nulls indicate spans that were - * initially in the list but have been successfully added to a region. - * The initial size is arbitrary. - */ - final ArrayList floodedSpans = - new ArrayList(1024); - - /* - * A predefined stack for use in the flood operation. Its content - * has no meaning outside the new region flooding operation. - * (Saves on object creation time.) - */ - final ArrayDeque workingStack = - new ArrayDeque(1024); - - final OpenHeightFieldIterator iter = field.dataIterator(); - - // Zero is reserved for the null-region. So initializing to 1. - int nextRegionID = 1; - - /* - * Search until the current distance reaches the minimum allowed - * distance. - * - * Note: This loop will not necessarily complete all region - * assignments. This is OK since a final region assignment step - * occurs after the loop iteration is complete. - */ - while (dist > minDist) - { - - // Find all spans that are at or below the current "water level" - // and are not already assigned to a region. Add these spans to - // the flooded span list for processing. - iter.reset(); - floodedSpans.clear(); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (span.regionID() == NULL_REGION - && span.distanceToBorder() >= dist) - // The span is not already assigned a region and is - // below the current "water level". So the span can be - // considered for region assignment. - floodedSpans.add(span); - } - - if (nextRegionID > 1) - { - // At least one region has already been created, so first - // try to put the newly flooded spans into existing regions. - if (dist > 0) - expandRegions(floodedSpans, expandIterations); - else - expandRegions(floodedSpans, -1); - } - - // Create new regions for all spans that could not be added to - // existing regions. - for (OpenHeightSpan span : floodedSpans) - { - if (span == null || span.regionID() != 0) - // This span was assigned to a newly created region - // during an earlier iteration of this loop. - // So it can be skipped. - continue; - // Fill to slightly more than the current "water level". - // This improves efficiency of the algorithm. - int fillTo = Math.max(dist - 2, minDist); - if (floodNewRegion(span, fillTo, nextRegionID, workingStack)) - // A new region was successfully generated. - nextRegionID++; - } - - // Increment the "water level" by 2, clamping at 0. - dist = Math.max(dist - 2, 0); - - } - - // Find all spans that haven't been assigned regions by the main loop. - // (Up to the minimum distance.) - iter.reset(); - floodedSpans.clear(); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (span.distanceToBorder() >= - minDist && span.regionID() == NULL_REGION) - // Not a border or null region span. Should be in a region. - floodedSpans.add(span); - } - - // Perform a final expansion of existing regions. - // Allow more iterations than normal for this last expansion. - if (minDist > 0) - expandRegions(floodedSpans, expandIterations * 8); - else - expandRegions(floodedSpans, -1); - - field.setRegionCount(nextRegionID); - - // Run the post processing algorithms. - for (IOpenHeightFieldAlgorithm algorithm : mRegionAlgorithms) - { - algorithm.apply(field); - } - - } - - /** - * Attempts to find the most appropriate regions to attach spans to. - *

Any spans successfully attached to a region will have their list - * entry set to null. So any non-null entries in the list will be spans - * for which a region could not be determined.

- * @param inoutSpans As input, the list of spans available for formation - * of new regions. As output, the spans that could not be assigned - * to new regions. - * @param maxIterations If set to -1, will iterate through completion. - */ - private void expandRegions(ArrayList inoutSpans - , int maxIterations) - { - if (inoutSpans.size() == 0) - return; // No spans available to process. - - int iterCount = 0; - while(true) - { - /* - * The number of spans in the working list that have been - * successfully processed or could not be processed successfully - * for some reason. - * This value controls when iteration ends. - */ - int skipped = 0; - - // Loop through all spans in the working list. - for (int iSpan = 0; iSpan < inoutSpans.size(); iSpan++) - { - OpenHeightSpan span = inoutSpans.get(iSpan); - if (span == null) - { - // The span originally at this index location has - // already been successfully assigned a region. Nothing - // else to do with it. - skipped++; - continue; - } - // Default to unassigned. - int spanRegion = NULL_REGION; - // Default to highest possible distance. - int regionCenterDist = Integer.MAX_VALUE; - /* - * Search through this span's axis-neighbors. - * Reference: Neighbor searches - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - */ - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null) - // No neighbor at this location. - continue; - // There is a neighbor at this location. - if (nSpan.regionID() > NULL_REGION) - { - /* - * This neighbor span belongs to a region. - */ - if (nSpan.distanceToRegionCore() + 2 < regionCenterDist) - { - /* - * This neighbor is closer to its region core - * than previously detected neighbors. - */ - int sameRegionCount = 0; - if (mUseConservativeExpansion) - { - /* - * Check to ensure that this neighbor has - * at least two other neighbors in its region. - * This makes sure that adding this span to - * this neighbor's region will not result - * in a single width line of voxels. - */ - for (int ndir = 0; ndir < 4; ndir++) - { - OpenHeightSpan nnSpan = - nSpan.getNeighbor(ndir); - if (nnSpan == null) - // No diagonal-neighbor. - continue; - // There is a diagonal-neighbor - if (nnSpan.regionID() == nSpan.regionID()) - // This neighbor has a neighbor in - // the same region. - sameRegionCount++; - } - } - if (!mUseConservativeExpansion - || sameRegionCount > 1) - { - /* - * Either conservative expansion is turned off, - * or it is on and this neighbor's region is - * acceptable for the current span. - * Choose this neighbor's region. - * Set the current distance to center as - * slightly further than this neighbor. - */ - spanRegion = nSpan.regionID(); - regionCenterDist = - nSpan.distanceToRegionCore() + 2; - } - } - } - } - if (spanRegion != NULL_REGION) - { - // Found a suitable region for this span to belong to. - // Mark this index as having been processed. - inoutSpans.set(iSpan, null); - span.setRegionID(spanRegion); - span.setDistanceToRegionCore(regionCenterDist); - } - else - // Could not find an existing region for this span. - skipped++; - } - - if (skipped == inoutSpans.size()) - // All spans have either been processed or could not be - // processed during the last cycle. - break; - - if (maxIterations != -1) - { - iterCount++; - if (iterCount > maxIterations) - // Reached the iteration limit. - break; - } - - } - - } - - /** - * Creates a new region surrounding a span, adding neighbor spans to the - * new region as appropriate. - *

The new region creation will fail if the root span is on the - * border of an existing region.

- *

All spans added to the new region as part of this process become - * "core" spans with a distance to region core of zero.

- * @param rootSpan The span used to seed the new region. - * @param fillToDist The watershed distance to flood to. - * @param regionID The region ID to use for the new region. - * (If creation is successful.) - * @param workingStack A stack used internally. The content is - * cleared before use. Its content has no meaning outside of - * this operation. - * @return TRUE if a new region was created. Otherwise FALSE. - */ - private static boolean floodNewRegion(OpenHeightSpan rootSpan - , int fillToDist - , int regionID - , ArrayDeque workingStack) - { - workingStack.clear(); - // TODO: EVAL: Change this into a working argument? - // Don't want unneeded object creation. - ArrayList workingList = - new ArrayList(); - // See stack and list. - workingStack.push(rootSpan); - workingList.add(rootSpan); - rootSpan.setRegionID(regionID); // Seed with region id. - rootSpan.setDistanceToRegionCore(0); // Set as center of region. - - int regionSize = 0; - - while (workingStack.size() > 0) - { - - OpenHeightSpan span = workingStack.pop(); - - /* - * Check regions of neighbor spans. - * - * If any neighbor is found to have a region assigned, then - * the current span can't be in the new region. - * (Want standard flooding algorithm to handle deciding which - * region this span should go in.) - * - * Up to 8 neighbors are checked. - * - * Reference: Neighbor searches. - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - */ - boolean isOnRegionBorder = false; - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null) - // No neighbor in this direction. - continue; - - // Check this axis-neighbor. - if (nSpan.regionID() != NULL_REGION - && nSpan.regionID() != regionID) - { - // Current span borders the null region or another region. - // No need to check rest of neighbors. - isOnRegionBorder = true; - break; - } - - // Check the diagonal-neighbor. - nSpan = nSpan.getNeighbor((dir+1) & 0x3); - if (nSpan != null - && nSpan.regionID() != NULL_REGION - && nSpan.regionID() != regionID) - { - // Current span borders the null region or another region. - // No need to check rest of neighbors. - isOnRegionBorder = true; - break; - } - } - if (isOnRegionBorder) - { - // Current span borders the null region or another region. - // Can't be part of the new region. - span.setRegionID(NULL_REGION); - continue; - } - - regionSize++; - - // If got this far, we know the current span is part of the new - // region. Now check its neighbors to see if they should be - // assigned to this new region. - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null - && nSpan.distanceToBorder() >= fillToDist - && nSpan.regionID() == 0) - { - // This neighbor does not have a region assignment and - // it is within the allowed fill range. Set it as a - // candidate for this new region. - nSpan.setRegionID(regionID); - nSpan.setDistanceToRegionCore(0); - workingStack.push(nSpan); - workingList.add(nSpan); - } - } - } - - return (regionSize > 0); - } - -} diff --git a/critterai/.svn/pristine/32/328cf8a1104c1b6f17387d09da95fffdd882d7ab.svn-base b/critterai/.svn/pristine/32/328cf8a1104c1b6f17387d09da95fffdd882d7ab.svn-base deleted file mode 100644 index d69032e0..00000000 --- a/critterai/.svn/pristine/32/328cf8a1104c1b6f17387d09da95fffdd882d7ab.svn-base +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Represents local corner data for a path within a path corridor. - /// (Generated during path straightening.) - /// - /// - /// - /// When path straightening occurs on a path corridor, the waypoints can include corners lying - /// on the vertex of a polygon's solid wall segment. These are the vertices included in this - /// data structure. - /// - /// - /// If path straightening does not result in any corners (e.g. path end point is visible) then - /// the will be zero. So can't be used to - /// detect 'no path'. - /// - /// - /// Certain methods which take objects of this type require a fixed buffer size equal to - /// . So be careful when initializing and using objects of - /// this type. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class CornerData - { - /* - * Design note: - * - * Implemented as a class to permit use as a buffer. - * - * The layout is designed for efficent marshalling on the native side - * of interop. That's why the Vector and poly refs are separated - * rather than using NavmeshPoint; - * - */ - - /// - /// The the buffer size required for the object used for interop method calls. - /// - public const int MarshalBufferSize = 4; - - /// - /// The corner vertices. [Length: ] - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = MarshalBufferSize)] - public Vector3[] verts; - - /// - /// The 's for each corner. - /// [Length: ] - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = MarshalBufferSize)] - public WaypointFlag[] flags; - - /// - /// The polygon references for each corner. [Length: ] - /// - /// - /// - /// The reference is for the polygon being entered at the corner. - /// - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = MarshalBufferSize)] - public uint[] polyRefs; - - /// - /// Number of corners in the local path. [Limits: 0 <= value <= maxCorners] - /// - public int cornerCount = 0; - - /// - /// The corner for the specified index. - /// - /// The corner index. [Limit: <= - /// The corner point. - public NavmeshPoint this[int index] - { - get - { - return new NavmeshPoint(polyRefs[index], verts[index]); - } - } - - /// - /// The maximum number of corners the buffers can hold. - /// - public int MaxCorners { get { return polyRefs.Length; } } - - /// - /// Creates an object with buffers sized for use with interop method calls. - /// ( = ) - /// - public CornerData() - { - verts = new Vector3[MarshalBufferSize]; - flags = new WaypointFlag[MarshalBufferSize]; - polyRefs = new uint[MarshalBufferSize]; - } - - /// - /// Creates an object with a non-standard buffer size. - /// - /// The maximum number of corners the buffers can hold. - public CornerData(int maxCorners) - { - verts = new Vector3[maxCorners]; - flags = new WaypointFlag[maxCorners]; - polyRefs = new uint[maxCorners]; - } - - /// - /// Copies the contents of the corner buffers from the source to destination. - /// - /// - /// - /// Data will be lost if the destination buffers are too small to hold the corners - /// contained by the source. - /// - /// - /// The object to copy from. - /// The object to copy to. - public static void Copy(CornerData source, CornerData desitation) - { - int size = Math.Min(source.MaxCorners, desitation.MaxCorners); - - Array.Copy(source.flags, desitation.flags, size); - Array.Copy(source.polyRefs, desitation.polyRefs, size); - Array.Copy(source.verts, desitation.verts, size); - desitation.cornerCount = Math.Min(size, source.cornerCount); - } - - /// - /// Validates the structure of the the corner buffers. (No content validation is performed.) - /// - /// The buffer to validate. - /// True if the buffer must be sized for marshalling. - /// True if the structure of the corner buffers is valid. - public static bool IsValid(CornerData buffer, bool forMarshalling) - { - if (buffer.flags == null - || buffer.polyRefs == null - || buffer.verts == null) - { - return false; - } - - int size = (forMarshalling ? MarshalBufferSize : buffer.MaxCorners); - - if (size == 0) - return false; - - if (buffer.flags.Length == size - && buffer.polyRefs.Length == size - && buffer.verts.Length == 3 * size) - { - return true; - } - - return false; - } - } -} diff --git a/critterai/.svn/pristine/32/32b3fc261bbd732f91fdfc5099e468e40c4ef4f7.svn-base b/critterai/.svn/pristine/32/32b3fc261bbd732f91fdfc5099e468e40c4ef4f7.svn-base deleted file mode 100644 index 3516e273..00000000 --- a/critterai/.svn/pristine/32/32b3fc261bbd732f91fdfc5099e468e40c4ef4f7.svn-base +++ /dev/null @@ -1,71 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336} - Library - Properties - org.critterai - cai-nmbuild - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - ..\bin\Release\cai-nmbuild.xml - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - processors\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - {42218E47-156D-46ff-84E0-119D47B0E4EB} - cai-nav - - - {9DFC1FE0-6469-4a04-AB13-9EAC59087802} - cai-nmgen - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/33/33580e1b0ec51ae0cd130aafd78bebddbffad3a3.svn-base b/critterai/.svn/pristine/33/33580e1b0ec51ae0cd130aafd78bebddbffad3a3.svn-base deleted file mode 100644 index b73fabab..00000000 --- a/critterai/.svn/pristine/33/33580e1b0ec51ae0cd130aafd78bebddbffad3a3.svn-base +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.*; -import static org.critterai.math.geom.Polygon3.*; - -import org.critterai.math.Vector3; -import org.critterai.math.geom.Polygon3; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Polygon3} class. - */ -public class Polygon3Tests { - - private static final float AX = -2; - private static final float AY = -2; - private static final float AZ = 1; - private static final float BX = -1; - private static final float BY = 0; - private static final float BZ = 2; - private static final float CX = 0; - private static final float CY = 2; - private static final float CZ = 2; - private static final float DX = 1; - private static final float DY = 4; - private static final float DZ = 1; - private static final float EX = 1; - private static final float EY = 4; - private static final float EZ = 0; - private static final float FX = 0; - private static final float FY = 2; - private static final float FZ = -1; - private static final float GX = -1; - private static final float GY = 0; - private static final float GZ = -1; - private static final float HX = -2; - private static final float HY = -2; - private static final float HZ = 0; - private static final float JX = 2; - private static final float JY = 6; - private static final float JZ = 1; - private static final float KX = -4; - private static final float KY = 0; - private static final float KZ = 2; - - private static final float CENX = -0.5f; - private static final float CENY = 1.0f; - private static final float CENZ = 0.5f; - - private float[] mVerts; - - @Before - public void setUp() throws Exception - { - mVerts = new float[10*3]; - mVerts[0] = KX; // Padding - mVerts[1] = KY; - mVerts[2] = KZ; - mVerts[3] = AX; // Start of poly - mVerts[4] = AY; - mVerts[5] = AZ; - mVerts[6] = BX; - mVerts[7] = BY; - mVerts[8] = BZ; - mVerts[9] = CX; - mVerts[10] = CY; - mVerts[11] = CZ; - mVerts[12] = DX; - mVerts[13] = DY; - mVerts[14] = DZ; - mVerts[15] = EX; // J insertion point. - mVerts[16] = EY; - mVerts[17] = EZ; - mVerts[18] = FX; - mVerts[19] = FY; - mVerts[20] = FZ; - mVerts[21] = GX; - mVerts[22] = GY; - mVerts[23] = GZ; - mVerts[24] = HX; - mVerts[25] = HY; - mVerts[26] = HZ; // End of poly - mVerts[27] = KX; // Padding and centroid storage location. - mVerts[28] = KY; - mVerts[29] = KZ; - } - - @Test - public void testIsConvexStandardTrue() - { - assertTrue(isConvex(mVerts, 1, 8)); - } - - @Test - public void testIsConvexStandardFalse() - { - mVerts[15] = JX; - mVerts[16] = JY; - mVerts[17] = JZ; - assertFalse(isConvex(mVerts, 1, 8)); - } - - @Test - public void testIsConvexVerticalTrue() - { - for (int p = 1; p < mVerts.length; p += 3) - { - mVerts[p] = mVerts[p+1]; - mVerts[p+1] = -2; - } - assertTrue(isConvex(mVerts, 1, 8)); - } - - @Test - public void testIsConvexVerticalFalse() - { - mVerts[15] = JX; - mVerts[16] = JY; - mVerts[17] = JZ; - for (int p = 1; p < mVerts.length; p += 3) - { - mVerts[p] = mVerts[p+1]; - mVerts[p+1] = -2; - } - assertFalse(isConvex(mVerts, 1, 8)); - } - - @Test - public void testGetCentroidArray() - { - assertTrue(mVerts == getCentroid(mVerts, 1, 8, mVerts, 9)); - assertTrue(mVerts[27] == CENX); - assertTrue(mVerts[28] == CENY); - assertTrue(mVerts[29] == CENZ); - } - - @Test - public void testGetCentroidVector3() - { - Vector3 v = new Vector3(5, 5, 5); // Needs to be seeded with non-zero. - assertTrue(v == getCentroid(mVerts, 1, 8, v)); - assertTrue(v.x == CENX); - assertTrue(v.y == CENY); - assertTrue(v.z == CENZ); - } - - @Test - public void testGetCentroidFloatList() - { - Vector3 v = new Vector3(5, 5, 5); // Needs to be seeded with non-zero. - assertTrue(v == getCentroid(v - , AX, AY, AZ - , BX, BY, BZ - , CX, CY, CZ - , DX, DY, DZ - , EX, EY, EZ - , FX, FY, FZ - , GX, GY, GZ - , HX, HY, HZ)); - assertTrue(v.x == CENX); - assertTrue(v.y == CENY); - assertTrue(v.z == CENZ); - } - -} diff --git a/critterai/.svn/pristine/33/3360deb2bb510f440a80d1772fc8f27fc3fde38b.svn-base b/critterai/.svn/pristine/33/3360deb2bb510f440a80d1772fc8f27fc3fde38b.svn-base deleted file mode 100644 index b856b702..00000000 --- a/critterai/.svn/pristine/33/3360deb2bb510f440a80d1772fc8f27fc3fde38b.svn-base +++ /dev/null @@ -1,477 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNAVMESHQUERY_H -#define DETOURNAVMESHQUERY_H - -#include "DetourNavMesh.h" -#include "DetourStatus.h" - - -// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter. -// On certain platforms indirect or virtual function call is expensive. The default -// setting is to use non-virtual functions, the actual implementations of the functions -// are declared as inline for maximum speed. - -//#define DT_VIRTUAL_QUERYFILTER 1 - -/// Defines polygon filtering and traversal costs for navigation mesh query operations. -/// @ingroup detour -class dtQueryFilter -{ - float m_areaCost[DT_MAX_AREAS]; ///< Cost per area type. (Used by default implementation.) - unsigned short m_includeFlags; ///< Flags for polygons that can be visited. (Used by default implementation.) - unsigned short m_excludeFlags; ///< Flags for polygons that should not be visted. (Used by default implementation.) - -public: - dtQueryFilter(); - - /// Returns true if the polygon can be visited. (I.e. Is traversable.) - /// @param[in] ref The reference id of the polygon test. - /// @param[in] tile The tile containing the polygon. - /// @param[in] poly The polygon to test. -#ifdef DT_VIRTUAL_QUERYFILTER - virtual bool passFilter(const dtPolyRef ref, - const dtMeshTile* tile, - const dtPoly* poly) const; -#else - bool passFilter(const dtPolyRef ref, - const dtMeshTile* tile, - const dtPoly* poly) const; -#endif - - /// Returns cost to move from the beginning to the end of a line segment - /// that is fully contained within a polygon. - /// @param[in] pa The start position on the edge of the previous and current polygon. [(x, y, z)] - /// @param[in] pb The end position on the edge of the current and next polygon. [(x, y, z)] - /// @param[in] prevRef The reference id of the previous polygon. [opt] - /// @param[in] prevTile The tile containing the previous polygon. [opt] - /// @param[in] prevPoly The previous polygon. [opt] - /// @param[in] curRef The reference id of the current polygon. - /// @param[in] curTile The tile containing the current polygon. - /// @param[in] curPoly The current polygon. - /// @param[in] nextRef The refernece id of the next polygon. [opt] - /// @param[in] nextTile The tile containing the next polygon. [opt] - /// @param[in] nextPoly The next polygon. [opt] -#ifdef DT_VIRTUAL_QUERYFILTER - virtual float getCost(const float* pa, const float* pb, - const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, - const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, - const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; -#else - float getCost(const float* pa, const float* pb, - const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, - const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, - const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; -#endif - - /// @name Getters and setters for the default implementation data. - ///@{ - - /// Returns the traversal cost of the area. - /// @param[in] i The id of the area. - /// @returns The traversal cost of the area. - inline float getAreaCost(const int i) const { return m_areaCost[i]; } - - /// Sets the traversal cost of the area. - /// @param[in] i The id of the area. - /// @param[in] cost The new cost of traversing the area. - inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; } - - /// Returns the include flags for the filter. - /// Any polygons that include one or more of these flags will be - /// included in the operation. - inline unsigned short getIncludeFlags() const { return m_includeFlags; } - - /// Sets the include flags for the filter. - /// @param[in] flags The new flags. - inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; } - - /// Returns the exclude flags for the filter. - /// Any polygons that include one ore more of these flags will be - /// excluded from the operation. - inline unsigned short getExcludeFlags() const { return m_excludeFlags; } - - /// Sets the exclude flags for the filter. - /// @param[in] flags The new flags. - inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; } - - ///@} - -}; - -/// Provides the ability to perform pathfinding related queries against -/// a navigation mesh. -/// @ingroup detour -class dtNavMeshQuery -{ -public: - dtNavMeshQuery(); - ~dtNavMeshQuery(); - - /// Initializes the query object. - /// @param[in] nav Pointer to the dtNavMesh object to use for all queries. - /// @param[in] maxNodes Maximum number of search nodes. [Limits: 0 < value <= 65536] - /// @returns The status flags for the query. - dtStatus init(const dtNavMesh* nav, const int maxNodes); - - /// @name Standard Pathfinding Functions - // /@{ - - /// Finds a path from the start polygon to the end polygon. - /// @param[in] startRef The refrence id of the start polygon. - /// @param[in] endRef The reference id of the end polygon. - /// @param[in] startPos A position within the start polygon. [(x, y, z)] - /// @param[in] endPos A position within the end polygon. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) - /// [(polyRef) * @p pathCount] - /// @param[out] pathCount The number of polygons returned in the @p path array. - /// @param[in] maxPath The maximum number of polygons the @p path array can hold. [Limit: >= 1] - dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter, - dtPolyRef* path, int* pathCount, const int maxPath) const; - - /// Finds the straight path from the start to the end position within the polygon corridor. - /// @param[in] startPos Path start position. [(x, y, z)] - /// @param[in] endPos Path end position. [(x, y, z)] - /// @param[in] path An array of polygon references that represent the path corridor. - /// @param[in] pathSize The number of polygons in the @p path array. - /// @param[out] straightPath Points describing the straight path. [(x, y, z) * @p straightPathCount]. - /// @param[out] straightPathFlags Flags describing each point. (See: #dtStraightPathFlags) [opt] - /// @param[out] straightPathRefs The reference id of the polygon that is being entered at each point. [opt] - /// @param[out] straightPathCount The number of points in the straight path. - /// @param[in] maxStraightPath The maximum number of points the straight path arrays can hold. [Limit: > 0] - /// @returns The status flags for the query. - dtStatus findStraightPath(const float* startPos, const float* endPos, - const dtPolyRef* path, const int pathSize, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath) const; - - ///@} - /// @name Sliced Pathfinding Functions - /// Common use case: - /// -# Call initSlicedFindPath() to initialize the sliced path query. - /// -# Call updateSlicedFindPath() until it returns complete. - /// -# Call finalizeSlicedFindPath() to get the path. - ///@{ - - /// Intializes a sliced path query. - /// @param[in] startRef The refrence id of the start polygon. - /// @param[in] endRef The reference id of the end polygon. - /// @param[in] startPos A position within the start polygon. [(x, y, z)] - /// @param[in] endPos A position within the end polygon. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @returns The status flags for the query. - dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter); - - /// Updates an in-progress sliced path query. - /// @param[in] maxIter The maximum number of iterations to perform. - /// @param[out] doneIters The actual number of iterations completed. [opt] - /// @returns The status flags for the query. - dtStatus updateSlicedFindPath(const int maxIter, int* doneIters); - - /// Finalizes and returns the results of a sliced path query. - /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) - /// [(polyRef) * @p pathCount] - /// @param[out] pathCount The number of polygons returned in the @p path array. - /// @param[in] maxPath The max number of polygons the path array can hold. [Limit: >= 1] - /// @returns The status flags for the query. - dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath); - - /// Finalizes and returns the results of an incomplete sliced path query, returning the path to the furthest - /// polygon on the existing path that was visited during the search. - /// @param[out] existing An array of polygon references for the existing path. - /// @param[out] existingSize The number of polygon in the @p existing array. - /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) - /// [(polyRef) * @p pathCount] - /// @param[out] pathCount The number of polygons returned in the @p path array. - /// @param[in] maxPath The max number of polygons the @p path array can hold. [Limit: >= 1] - /// @returns The status flags for the query. - dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, - dtPolyRef* path, int* pathCount, const int maxPath); - - ///@} - /// @name Dijkstra Search Functions - /// @{ - - /// Finds the polygons along the navigation graph that touch the specified circle. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] centerPos The center of the search circle. [(x, y, z)] - /// @param[in] radius The radius of the search circle. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultRef The reference ids of the polygons touched by the circle. [opt] - /// @param[out] resultParent The reference ids of the parent polygons for each result. - /// Zero if a result polygon has no parent. [opt] - /// @param[out] resultCost The search cost from @p centerPos to the polygon. [opt] - /// @param[out] resultCount The number of polygons found. [opt] - /// @param[in] maxResult The maximum number of polygons the result arrays can hold. - /// @returns The status flags for the query. - dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const; - - /// Finds the polygons along the naviation graph that touch the specified convex polygon. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] verts The vertices describing the convex polygon. (CCW) - /// [(x, y, z) * @p nverts] - /// @param[in] nverts The number of vertices in the polygon. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultRef The reference ids of the polygons touched by the search polygon. [opt] - /// @param[out] resultParent The reference ids of the parent polygons for each result. Zero if a - /// result polygon has no parent. [opt] - /// @param[out] resultCost The search cost from the centroid point to the polygon. [opt] - /// @param[out] resultCount The number of polygons found. - /// @param[in] maxResult The maximum number of polygons the result arrays can hold. - /// @returns The status flags for the query. - dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const; - - /// @} - /// @name Local Query Functions - ///@{ - - /// Finds the polygon nearest to the specified center point. - /// @param[in] center The center of the search box. [(x, y, z)] - /// @param[in] extents The search distance along each axis. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] nearestRef The reference id of the nearest polygon. - /// @param[out] nearestPt The nearest point on the polygon. [opt] [(x, y, z)] - /// @returns The status flags for the query. - dtStatus findNearestPoly(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* nearestRef, float* nearestPt) const; - - /// Finds polygons that overlap the search box. - /// @param[in] center The center of the search box. [(x, y, z)] - /// @param[in] extents The search distance along each axis. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] polys The reference ids of the polygons that overlap the query box. - /// @param[out] polyCount The number of polygons in the search result. - /// @param[in] maxPolys The maximum number of polygons the search result can hold. - /// @returns The status flags for the query. - dtStatus queryPolygons(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* polys, int* polyCount, const int maxPolys) const; - - /// Finds the non-overlapping navigation polygons in the local neighbourhood around the center position. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] centerPos The center of the query circle. [(x, y, z)] - /// @param[in] radius The radius of the query circle. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultRef The reference ids of the polygons touched by the circle. - /// @param[out] resultParent The reference ids of the parent polygons for each result. - /// Zero if a result polygon has no parent. [opt] - /// @param[out] resultCount The number of polygons found. - /// @param[in] maxResult The maximum number of polygons the result arrays can hold. - /// @returns The status flags for the query. - dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, - int* resultCount, const int maxResult) const; - - /// Moves from the start to the end position constrained to the navigation mesh. - /// @param[in] startRef The reference id of the start polygon. - /// @param[in] startPos A position of the mover within the start polygon. [(x, y, x)] - /// @param[in] endPos The desired end position of the mover. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultPos The result position of the mover. [(x, y, z)] - /// @param[out] visited The reference ids of the polygons visited during the move. - /// @param[out] visitedCount The number of polygons visited during the move. - /// @param[in] maxVisitedSize The maximum number of polygons the @p visited array can hold. - /// @returns The status flags for the query. - dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const; - - /// Casts a 'walkability' ray along the surface of the navigation mesh from - /// the start position toward the end position. - /// @param[in] startRef The reference id of the start polygon. - /// @param[in] startPos A position within the start polygon representing - /// the start of the ray. [(x, y, z)] - /// @param[in] endPos The position to cast the ray toward. [(x, y, z)] - /// @param[out] t The hit parameter. (FLT_MAX if no wall hit.) - /// @param[out] hitNormal The normal of the nearest wall hit. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] path The reference ids of the visited polygons. [opt] - /// @param[out] pathCount The number of visited polygons. [opt] - /// @param[in] maxPath The maximum number of polygons the @p path array can hold. - /// @returns The status flags for the query. - dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const; - - /// Finds the distance from the specified position to the nearest polygon wall. - /// @param[in] startRef The reference id of the polygon containing @p centerPos. - /// @param[in] centerPos The center of the search circle. [(x, y, z)] - /// @param[in] maxRadius The radius of the search circle. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] hitDist The distance to the nearest wall from @p centerPos. - /// @param[out] hitPos The nearest position on the wall that was hit. [(x, y, z)] - /// @param[out] hitNormal The normalized ray formed from the wall point to the - /// source point. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, - const dtQueryFilter* filter, - float* hitDist, float* hitPos, float* hitNormal) const; - - /// Returns the segments for the specified polygon, optionally including portals. - /// @param[in] ref The reference id of the polygon. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] segmentVerts The segments. [(ax, ay, az, bx, by, bz) * segmentCount] - /// @param[out] segmentRefs The reference ids of each segment's neighbor polygon. - /// Or zero if the segment is a wall. [opt] [(parentRef) * @p segmentCount] - /// @param[out] segmentCount The number of segments returned. - /// @param[in] maxSegments The maximum number of segments the result arrays can hold. - /// @returns The status flags for the query. - dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, - float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, - const int maxSegments) const; - - /// Returns random location on navmesh. - /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[in] frand Function returning a random number [0..1). - /// @param[out] randomRef The reference id of the random location. - /// @param[out] randomPt The random location. - /// @returns The status flags for the query. - dtStatus findRandomPoint(const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const; - - /// Returns random location on navmesh within the reach of specified location. - /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon. - /// The location is not exactly constrained by the circle, but it limits the visited polygons. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] centerPos The center of the search circle. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[in] frand Function returning a random number [0..1). - /// @param[out] randomRef The reference id of the random location. - /// @param[out] randomPt The random location. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float maxRadius, - const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const; - - /// Finds the closest point on the specified polygon. - /// @param[in] ref The reference id of the polygon. - /// @param[in] pos The position to check. [(x, y, z)] - /// @param[out] closest The closest point on the polygon. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const; - - /// Returns a point on the boundary closest to the source point if the source point is outside the - /// polygon's xz-bounds. - /// @param[in] ref The reference id to the polygon. - /// @param[in] pos The position to check. [(x, y, z)] - /// @param[out] closest The closest point. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const; - - /// Gets the height of the polygon at the provided position using the height detail. (Most accurate.) - /// @param[in] ref The reference id of the polygon. - /// @param[in] pos A position within the xz-bounds of the polygon. [(x, y, z)] - /// @param[out] height The height at the surface of the polygon. - /// @returns The status flags for the query. - dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const; - - /// @} - /// @name Miscellaneous Functions - /// @{ - - /// Returns true if the polygon reference is valid and passes the filter restrictions. - /// @param[in] ref The polygon reference to check. - /// @param[in] filter The filter to apply. - bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const; - - /// Returns true if the polygon reference is in the closed list. - /// @param[in] ref The reference id of the polygon to check. - /// @returns True if the polygon is in closed list. - bool isInClosedList(dtPolyRef ref) const; - - /// Gets the node pool. - /// @returns The node pool. - class dtNodePool* getNodePool() const { return m_nodePool; } - - /// Gets the navigation mesh the query object is using. - /// @return The navigation mesh the query object is using. - const dtNavMesh* getAttachedNavMesh() const { return m_nav; } - - /// @} - -private: - - /// Returns neighbour tile based on side. - dtMeshTile* getNeighbourTileAt(int x, int y, int side) const; - - /// Queries polygons within a tile. - int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter, - dtPolyRef* polys, const int maxPolys) const; - /// Find nearest polygon within a tile. - dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents, - const dtQueryFilter* filter, float* nearestPt) const; - /// Returns closest point on polygon. - void closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const; - - /// Returns portal points between two polygons. - dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, - unsigned char& fromType, unsigned char& toType) const; - dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* left, float* right) const; - - /// Returns edge mid point between two polygons. - dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const; - dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* mid) const; - - const dtNavMesh* m_nav; ///< Pointer to navmesh data. - - struct dtQueryData - { - dtStatus status; - struct dtNode* lastBestNode; - float lastBestNodeCost; - dtPolyRef startRef, endRef; - float startPos[3], endPos[3]; - const dtQueryFilter* filter; - }; - dtQueryData m_query; ///< Sliced query state. - - class dtNodePool* m_tinyNodePool; ///< Pointer to small node pool. - class dtNodePool* m_nodePool; ///< Pointer to node pool. - class dtNodeQueue* m_openList; ///< Pointer to open list queue. -}; - -/// Allocates a query object using the Detour allocator. -/// @return An allocated query object, or null on failure. -/// @ingroup detour -dtNavMeshQuery* dtAllocNavMeshQuery(); - -/// Frees the specified query object using the Detour allocator. -/// @param[in] query A query object allocated using #dtAllocNavMeshQuery -/// @ingroup detour -void dtFreeNavMeshQuery(dtNavMeshQuery* query); - -#endif // DETOURNAVMESHQUERY_H diff --git a/critterai/.svn/pristine/33/336ffd68fb075dfe63bc85ed8ea88f03628c03b9.svn-base b/critterai/.svn/pristine/33/336ffd68fb075dfe63bc85ed8ea88f03628c03b9.svn-base deleted file mode 100644 index 0ddcf5e0..00000000 Binary files a/critterai/.svn/pristine/33/336ffd68fb075dfe63bc85ed8ea88f03628c03b9.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/33/33ac27a3ae49789e6995c5288458a123ad3ec639.svn-base b/critterai/.svn/pristine/33/33ac27a3ae49789e6995c5288458a123ad3ec639.svn-base deleted file mode 100644 index ac09788b..00000000 --- a/critterai/.svn/pristine/33/33ac27a3ae49789e6995c5288458a123ad3ec639.svn-base +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents the a triangle mesh created by the navigation mesh generation - * process. - *

WARNING: The core data within this class is unprotected.

- *

- * - * - *

- */ -public final class TriangleMesh -{ - - /* - * Recast Reference: rcPolyMeshDetail in Recast.h - */ - - /** - * Vertices for the triangle mesh in the forma (x, y, z) - */ - public float[] vertices = null; - - /** - * Triangles in the mesh in the forma (vertAIndex, vertBIndex, vertCIndex) - * where the vertices are wrapped clockwise. - */ - public int[] indices = null; - - /** - * The region to which each triangle belongs. - *

Index corresponds to the indices array index.

- */ - public int[] triangleRegions = null; - - /** - * Gets the region ID associated with a triangle - * @param index The index of the triangle. - * @return The region ID of the triangle. Or -1 if the index is invalid. - */ - public int getTriangleRegion(int index) - { - if (index < 0 || index >= triangleRegions.length) - return -1; - return triangleRegions[index]; - } - - /** - * Gets the vertices for a particular triangle in the form - * (vertAx, vertAy, vertAz, vertBx, vertBy, vertBz, vertCx, vertCy, vertCz) - * @param index The index of the triangle to retrieve. - * @return The vertices in the specified triangle. Or null if the index is - * invalid. - */ - public float[] getTriangleVerts(int index) - { - - int pTriangle = index*3; - if (index < 0 || pTriangle >= indices.length) - return null; - - float[] result = new float[9]; - - for (int i = 0; i < 3; i++) - { - int pVert = indices[pTriangle+i]*3; - result[i*3] = vertices[pVert]; - result[i*3+1] = vertices[pVert+1]; - result[i*3+2] = vertices[pVert+2]; - } - - return result; - } - - /** - * The number of triangles in the mesh. - * @return The number of triangles in the mesh. - */ - public int triangleCount() - { - return (triangleRegions == null ? 0 : triangleRegions.length); - } - - /** - * The number of vertices in the mesh. - * @return The number of vertices in the mesh. - */ - public int vertCount() - { - return (vertices == null ? 0 : vertices.length / 3); - } - -} diff --git a/critterai/.svn/pristine/35/35e27c34cfde980e85341b66f697e38839ca5f67.svn-base b/critterai/.svn/pristine/35/35e27c34cfde980e85341b66f697e38839ca5f67.svn-base deleted file mode 100644 index 25f7c97c..00000000 --- a/critterai/.svn/pristine/35/35e27c34cfde980e85341b66f697e38839ca5f67.svn-base +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - The purpose of NMGen is to generate navigation meshes from arbitrary source geometry. Features fall into two categories: - Core and 'standard build'. - - - - The core features are located in the N:org.critterai.nmgen namespace and involve creating - simplified polygon mesh data from detailed triangle-based source geometry. You can code your own build process from scratch using these features, but it will - require a significant amount of work and detailed knowlege of all aspects of the process. - - - - The standard build process implements a flexible, extendable build process suitable for use at design time. It takes care of many of the mundane - details for you. Its features are implemented in the following namespaces: - - - Common extentions: N:org.critterai.nmbuild - - Unity extensions: N:org.critterai.nmbuild.u3d.editor - - The standard build process has three main steps which will be covered in detail throughout the rest of this section. - - - - Compile the input. - The NMGen Build. (Produces the polygon meshes.) - Create the navigation mesh. - - - - - - - CAINav uses the OpenGL coordinate system. - - - - - -

- - The Standard Build Process - - - - - - - -
- - - - - - - - - - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/36/362870cb5ee8cad43dad3cb2f7594f42f3732c43.svn-base b/critterai/.svn/pristine/36/362870cb5ee8cad43dad3cb2f7594f42f3732c43.svn-base deleted file mode 100644 index d8226a4e..00000000 --- a/critterai/.svn/pristine/36/362870cb5ee8cad43dad3cb2f7594f42f3732c43.svn-base +++ /dev/null @@ -1,194 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include -#include "DetourProximityGrid.h" -#include "DetourCommon.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" - - -dtProximityGrid* dtAllocProximityGrid() -{ - void* mem = dtAlloc(sizeof(dtProximityGrid), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtProximityGrid; -} - -void dtFreeProximityGrid(dtProximityGrid* ptr) -{ - if (!ptr) return; - ptr->~dtProximityGrid(); - dtFree(ptr); -} - - -inline int hashPos2(int x, int y, int n) -{ - return ((x*73856093) ^ (y*19349663)) & (n-1); -} - - -dtProximityGrid::dtProximityGrid() : - m_maxItems(0), - m_cellSize(0), - m_pool(0), - m_poolHead(0), - m_poolSize(0), - m_buckets(0), - m_bucketsSize(0) -{ -} - -dtProximityGrid::~dtProximityGrid() -{ - dtFree(m_buckets); - dtFree(m_pool); -} - -bool dtProximityGrid::init(const int poolSize, const float cellSize) -{ - dtAssert(poolSize > 0); - dtAssert(cellSize > 0.0f); - - m_cellSize = cellSize; - m_invCellSize = 1.0f / m_cellSize; - - // Allocate hashs buckets - m_bucketsSize = dtNextPow2(poolSize); - m_buckets = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_bucketsSize, DT_ALLOC_PERM); - if (!m_buckets) - return false; - - // Allocate pool of items. - m_poolSize = poolSize; - m_poolHead = 0; - m_pool = (Item*)dtAlloc(sizeof(Item)*m_poolSize, DT_ALLOC_PERM); - if (!m_pool) - return false; - - clear(); - - return true; -} - -void dtProximityGrid::clear() -{ - memset(m_buckets, 0xff, sizeof(unsigned short)*m_bucketsSize); - m_poolHead = 0; - m_bounds[0] = 0xffff; - m_bounds[1] = 0xffff; - m_bounds[2] = -0xffff; - m_bounds[3] = -0xffff; -} - -void dtProximityGrid::addItem(const unsigned short id, - const float minx, const float miny, - const float maxx, const float maxy) -{ - const int iminx = (int)floorf(minx * m_invCellSize); - const int iminy = (int)floorf(miny * m_invCellSize); - const int imaxx = (int)floorf(maxx * m_invCellSize); - const int imaxy = (int)floorf(maxy * m_invCellSize); - - m_bounds[0] = dtMin(m_bounds[0], iminx); - m_bounds[1] = dtMin(m_bounds[1], iminy); - m_bounds[2] = dtMax(m_bounds[2], imaxx); - m_bounds[3] = dtMax(m_bounds[3], imaxy); - - for (int y = iminy; y <= imaxy; ++y) - { - for (int x = iminx; x <= imaxx; ++x) - { - if (m_poolHead < m_poolSize) - { - const int h = hashPos2(x, y, m_bucketsSize); - const unsigned short idx = (unsigned short)m_poolHead; - m_poolHead++; - Item& item = m_pool[idx]; - item.x = (short)x; - item.y = (short)y; - item.id = id; - item.next = m_buckets[h]; - m_buckets[h] = idx; - } - } - } -} - -int dtProximityGrid::queryItems(const float minx, const float miny, - const float maxx, const float maxy, - unsigned short* ids, const int maxIds) const -{ - const int iminx = (int)floorf(minx * m_invCellSize); - const int iminy = (int)floorf(miny * m_invCellSize); - const int imaxx = (int)floorf(maxx * m_invCellSize); - const int imaxy = (int)floorf(maxy * m_invCellSize); - - int n = 0; - - for (int y = iminy; y <= imaxy; ++y) - { - for (int x = iminx; x <= imaxx; ++x) - { - const int h = hashPos2(x, y, m_bucketsSize); - unsigned short idx = m_buckets[h]; - while (idx != 0xffff) - { - Item& item = m_pool[idx]; - if ((int)item.x == x && (int)item.y == y) - { - // Check if the id exists already. - const unsigned short* end = ids + n; - unsigned short* i = ids; - while (i != end && *i != item.id) - ++i; - // Item not found, add it. - if (i == end) - { - if (n >= maxIds) - return n; - ids[n++] = item.id; - } - } - idx = item.next; - } - } - } - - return n; -} - -int dtProximityGrid::getItemCountAt(const int x, const int y) const -{ - int n = 0; - - const int h = hashPos2(x, y, m_bucketsSize); - unsigned short idx = m_buckets[h]; - while (idx != 0xffff) - { - Item& item = m_pool[idx]; - if ((int)item.x == x && (int)item.y == y) - n++; - idx = item.next; - } - - return n; -} diff --git a/critterai/.svn/pristine/36/3676790e485a7c103974cedfdaf4a1dcc5341a67.svn-base b/critterai/.svn/pristine/36/3676790e485a7c103974cedfdaf4a1dcc5341a67.svn-base deleted file mode 100644 index 1606b906..00000000 --- a/critterai/.svn/pristine/36/3676790e485a7c103974cedfdaf4a1dcc5341a67.svn-base +++ /dev/null @@ -1,3304 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include -#include "DetourNavMeshQuery.h" -#include "DetourNavMesh.h" -#include "DetourNode.h" -#include "DetourCommon.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include - -/// @class dtQueryFilter -/// -/// The Default Implementation -/// -/// At construction: All area costs default to 1.0. All flags are included -/// and none are excluded. -/// -/// If a polygon has both an include and an exclude flag, it will be excluded. -/// -/// The way filtering works, a navigation mesh polygon must have at least one flag -/// set to ever be considered by a query. So a polygon with no flags will never -/// be considered. -/// -/// Setting the include flags to 0 will result in all polygons being excluded. -/// -/// Custom Implementations -/// -/// DT_VIRTUAL_QUERYFILTER must be defined in order to extend this class. -/// -/// Implement a custom query filter by overriding the virtual passFilter() -/// and getCost() functions. If this is done, both functions should be as -/// fast as possible. Use cached local copies of data rather than accessing -/// your own objects where possible. -/// -/// Custom implementations do not need to adhere to the flags or cost logic -/// used by the default implementation. -/// -/// In order for A* searches to work properly, the cost should be proportional to -/// the travel distance. Implementing a cost modifier less than 1.0 is likely -/// to lead to problems during pathfinding. -/// -/// @see dtNavMeshQuery - -dtQueryFilter::dtQueryFilter() : - m_includeFlags(0xffff), - m_excludeFlags(0) -{ - for (int i = 0; i < DT_MAX_AREAS; ++i) - m_areaCost[i] = 1.0f; -} - -#ifdef DT_VIRTUAL_QUERYFILTER -bool dtQueryFilter::passFilter(const dtPolyRef /*ref*/, - const dtMeshTile* /*tile*/, - const dtPoly* poly) const -{ - return (poly->flags & m_includeFlags) != 0 && (poly->flags & m_excludeFlags) == 0; -} - -float dtQueryFilter::getCost(const float* pa, const float* pb, - const dtPolyRef /*prevRef*/, const dtMeshTile* /*prevTile*/, const dtPoly* /*prevPoly*/, - const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly, - const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const -{ - return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()]; -} -#else -inline bool dtQueryFilter::passFilter(const dtPolyRef /*ref*/, - const dtMeshTile* /*tile*/, - const dtPoly* poly) const -{ - return (poly->flags & m_includeFlags) != 0 && (poly->flags & m_excludeFlags) == 0; -} - -inline float dtQueryFilter::getCost(const float* pa, const float* pb, - const dtPolyRef /*prevRef*/, const dtMeshTile* /*prevTile*/, const dtPoly* /*prevPoly*/, - const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly, - const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const -{ - return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()]; -} -#endif - -static const float H_SCALE = 0.999f; // Search heuristic scale. - - -dtNavMeshQuery* dtAllocNavMeshQuery() -{ - void* mem = dtAlloc(sizeof(dtNavMeshQuery), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtNavMeshQuery; -} - -void dtFreeNavMeshQuery(dtNavMeshQuery* navmesh) -{ - if (!navmesh) return; - navmesh->~dtNavMeshQuery(); - dtFree(navmesh); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -/// @class dtNavMeshQuery -/// -/// For methods that support undersized buffers, if the buffer is too small -/// to hold the entire result set the return status of the method will include -/// the #DT_BUFFER_TOO_SMALL flag. -/// -/// Constant member functions can be used by multiple clients without side -/// effects. (E.g. No change to the closed list. No impact on an in-progress -/// sliced path query. Etc.) -/// -/// Walls and portals: A @e wall is a polygon segment that is -/// considered impassable. A @e portal is a passable segment between polygons. -/// A portal may be treated as a wall based on the dtQueryFilter used for a query. -/// -/// @see dtNavMesh, dtQueryFilter, #dtAllocNavMeshQuery(), #dtAllocNavMeshQuery() - -dtNavMeshQuery::dtNavMeshQuery() : - m_nav(0), - m_tinyNodePool(0), - m_nodePool(0), - m_openList(0) -{ - memset(&m_query, 0, sizeof(dtQueryData)); -} - -dtNavMeshQuery::~dtNavMeshQuery() -{ - if (m_tinyNodePool) - m_tinyNodePool->~dtNodePool(); - if (m_nodePool) - m_nodePool->~dtNodePool(); - if (m_openList) - m_openList->~dtNodeQueue(); - dtFree(m_tinyNodePool); - dtFree(m_nodePool); - dtFree(m_openList); -} - -/// @par -/// -/// Must be the first function called after construction, before other -/// functions are used. -/// -/// This function can be used multiple times. -dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) -{ - m_nav = nav; - - if (!m_nodePool || m_nodePool->getMaxNodes() < maxNodes) - { - if (m_nodePool) - { - m_nodePool->~dtNodePool(); - dtFree(m_nodePool); - m_nodePool = 0; - } - m_nodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(maxNodes, dtNextPow2(maxNodes/4)); - if (!m_nodePool) - return DT_FAILURE | DT_OUT_OF_MEMORY; - } - else - { - m_nodePool->clear(); - } - - if (!m_tinyNodePool) - { - m_tinyNodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(64, 32); - if (!m_tinyNodePool) - return DT_FAILURE | DT_OUT_OF_MEMORY; - } - else - { - m_tinyNodePool->clear(); - } - - // TODO: check the open list size too. - if (!m_openList || m_openList->getCapacity() < maxNodes) - { - if (m_openList) - { - m_openList->~dtNodeQueue(); - dtFree(m_openList); - m_openList = 0; - } - m_openList = new (dtAlloc(sizeof(dtNodeQueue), DT_ALLOC_PERM)) dtNodeQueue(maxNodes); - if (!m_openList) - return DT_FAILURE | DT_OUT_OF_MEMORY; - } - else - { - m_openList->clear(); - } - - return DT_SUCCESS; -} - -dtStatus dtNavMeshQuery::findRandomPoint(const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const -{ - dtAssert(m_nav); - - // Randomly pick one tile. Assume that all tiles cover roughly the same area. - const dtMeshTile* tile = 0; - float tsum = 0.0f; - for (int i = 0; i < m_nav->getMaxTiles(); i++) - { - const dtMeshTile* t = m_nav->getTile(i); - if (!t || !t->header) continue; - - // Choose random tile using reservoi sampling. - const float area = 1.0f; // Could be tile area too. - tsum += area; - const float u = frand(); - if (u*tsum <= area) - tile = t; - } - if (!tile) - return DT_FAILURE; - - // Randomly pick one polygon weighted by polygon area. - const dtPoly* poly = 0; - dtPolyRef polyRef = 0; - const dtPolyRef base = m_nav->getPolyRefBase(tile); - - float areaSum = 0.0f; - for (int i = 0; i < tile->header->polyCount; ++i) - { - const dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() != DT_POLYTYPE_GROUND) - continue; - // Must pass filter - const dtPolyRef ref = base | (dtPolyRef)i; - if (!filter->passFilter(ref, tile, p)) - continue; - - // Calc area of the polygon. - float polyArea = 0.0f; - for (int j = 2; j < p->vertCount; ++j) - { - const float* va = &tile->verts[p->verts[0]*3]; - const float* vb = &tile->verts[p->verts[j-1]*3]; - const float* vc = &tile->verts[p->verts[j]*3]; - polyArea += dtTriArea2D(va,vb,vc); - } - - // Choose random polygon weighted by area, using reservoi sampling. - areaSum += polyArea; - const float u = frand(); - if (u*areaSum <= polyArea) - { - poly = p; - polyRef = ref; - } - } - - if (!poly) - return DT_FAILURE; - - // Randomly pick point on polygon. - const float* v = &tile->verts[poly->verts[0]*3]; - float verts[3*DT_VERTS_PER_POLYGON]; - float areas[DT_VERTS_PER_POLYGON]; - dtVcopy(&verts[0*3],v); - for (int j = 1; j < poly->vertCount; ++j) - { - v = &tile->verts[poly->verts[j]*3]; - dtVcopy(&verts[j*3],v); - } - - const float s = frand(); - const float t = frand(); - - float pt[3]; - dtRandomPointInConvexPoly(verts, poly->vertCount, areas, s, t, pt); - - float h = 0.0f; - dtStatus status = getPolyHeight(polyRef, pt, &h); - if (dtStatusFailed(status)) - return status; - pt[1] = h; - - dtVcopy(randomPt, pt); - *randomRef = polyRef; - - return DT_SUCCESS; -} - -dtStatus dtNavMeshQuery::findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - const dtMeshTile* startTile = 0; - const dtPoly* startPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(startRef, &startTile, &startPoly); - if (!filter->passFilter(startRef, startTile, startPoly)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtStatus status = DT_SUCCESS; - - const float radiusSqr = dtSqr(radius); - float areaSum = 0.0f; - - const dtMeshTile* randomTile = 0; - const dtPoly* randomPoly = 0; - dtPolyRef randomPolyRef = 0; - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Place random locations on on ground. - if (bestPoly->getType() == DT_POLYTYPE_GROUND) - { - // Calc area of the polygon. - float polyArea = 0.0f; - for (int j = 2; j < bestPoly->vertCount; ++j) - { - const float* va = &bestTile->verts[bestPoly->verts[0]*3]; - const float* vb = &bestTile->verts[bestPoly->verts[j-1]*3]; - const float* vc = &bestTile->verts[bestPoly->verts[j]*3]; - polyArea += dtTriArea2D(va,vb,vc); - } - // Choose random polygon weighted by area, using reservoi sampling. - areaSum += polyArea; - const float u = frand(); - if (u*areaSum <= polyArea) - { - randomTile = bestTile; - randomPoly = bestPoly; - randomPolyRef = bestRef; - } - } - - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the circle is not touching the next polygon, skip it. - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - if (distSqr > radiusSqr) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - dtVlerp(neighbourNode->pos, va, vb, 0.5f); - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - neighbourNode->flags = DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - if (!randomPoly) - return DT_FAILURE; - - // Randomly pick point on polygon. - const float* v = &randomTile->verts[randomPoly->verts[0]*3]; - float verts[3*DT_VERTS_PER_POLYGON]; - float areas[DT_VERTS_PER_POLYGON]; - dtVcopy(&verts[0*3],v); - for (int j = 1; j < randomPoly->vertCount; ++j) - { - v = &randomTile->verts[randomPoly->verts[j]*3]; - dtVcopy(&verts[j*3],v); - } - - const float s = frand(); - const float t = frand(); - - float pt[3]; - dtRandomPointInConvexPoly(verts, randomPoly->vertCount, areas, s, t, pt); - - float h = 0.0f; - dtStatus stat = getPolyHeight(randomPolyRef, pt, &h); - if (dtStatusFailed(status)) - return stat; - pt[1] = h; - - dtVcopy(randomPt, pt); - *randomRef = randomPolyRef; - - return DT_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////////////////// - -/// @par -/// -/// Uses the detail polygons to find the surface height. (Most accurate.) -/// -/// @p pos does not have to be within the bounds of the polygon or navigation mesh. -/// -/// See closestPointOnPolyBoundary() for a limited but faster option. -/// -dtStatus dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const -{ - dtAssert(m_nav); - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - if (!tile) - return DT_FAILURE | DT_INVALID_PARAM; - - closestPointOnPolyInTile(tile, poly, pos, closest); - - return DT_SUCCESS; -} - -void dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, - const float* pos, float* closest) const -{ - const unsigned int ip = (unsigned int)(poly - tile->polys); - const dtPolyDetail* pd = &tile->detailMeshes[ip]; - - // TODO: The commented out version finds 'cylinder distance' instead of 'sphere distance' to the navmesh. - // Test and enable. -/* - // Clamp point to be inside the polygon. - float verts[DT_VERTS_PER_POLYGON*3]; - float edged[DT_VERTS_PER_POLYGON]; - float edget[DT_VERTS_PER_POLYGON]; - const int nv = poly->vertCount; - for (int i = 0; i < nv; ++i) - dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]); - - dtVcopy(closest, pos); - if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) - { - // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) - { - if (edged[i] < dmin) - { - dmin = edged[i]; - imin = i; - } - } - const float* va = &verts[imin*3]; - const float* vb = &verts[((imin+1)%nv)*3]; - dtVlerp(closest, va, vb, edget[imin]); - } - - // Find height at the location. - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - float h; - if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) - { - closest[1] = h; - break; - } - } -*/ - float closestDistSqr = FLT_MAX; - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - - float pt[3]; - dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]); - float d = dtVdistSqr(pos, pt); - - if (d < closestDistSqr) - { - dtVcopy(closest, pt); - closestDistSqr = d; - } - } -} - -/// @par -/// -/// Much faster than closestPointOnPoly(). -/// -/// If the provided position lies within the polygon's xz-bounds (above or below), -/// then @p pos and @p closest will be equal. -/// -/// The height of @p closest will be the polygon boundary. The height detail is not used. -/// -/// @p pos does not have to be within the bounds of the polybon or the navigation mesh. -/// -dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const -{ - dtAssert(m_nav); - - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - - // Collect vertices. - float verts[DT_VERTS_PER_POLYGON*3]; - float edged[DT_VERTS_PER_POLYGON]; - float edget[DT_VERTS_PER_POLYGON]; - int nv = 0; - for (int i = 0; i < (int)poly->vertCount; ++i) - { - dtVcopy(&verts[nv*3], &tile->verts[poly->verts[i]*3]); - nv++; - } - - bool inside = dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget); - if (inside) - { - // Point is inside the polygon, return the point. - dtVcopy(closest, pos); - } - else - { - // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) - { - if (edged[i] < dmin) - { - dmin = edged[i]; - imin = i; - } - } - const float* va = &verts[imin*3]; - const float* vb = &verts[((imin+1)%nv)*3]; - dtVlerp(closest, va, vb, edget[imin]); - } - - return DT_SUCCESS; -} - -/// @par -/// -/// Will return #DT_FAILURE if the provided position is outside the xz-bounds -/// of the polygon. -/// -dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* height) const -{ - dtAssert(m_nav); - - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - const float* v0 = &tile->verts[poly->verts[0]*3]; - const float* v1 = &tile->verts[poly->verts[1]*3]; - const float d0 = dtVdist(pos, v0); - const float d1 = dtVdist(pos, v1); - const float u = d0 / (d0+d1); - if (height) - *height = v0[1] + (v1[1] - v0[1]) * u; - return DT_SUCCESS; - } - else - { - const unsigned int ip = (unsigned int)(poly - tile->polys); - const dtPolyDetail* pd = &tile->detailMeshes[ip]; - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - float h; - if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) - { - if (height) - *height = h; - return DT_SUCCESS; - } - } - } - - return DT_FAILURE | DT_INVALID_PARAM; -} - -/// @par -/// -/// @note If the search box does not intersect any polygons the search will -/// return #DT_SUCCESS, but @p nearestRef will be zero. So if in doubt, check -/// @p nearestRef before using @p nearestPt. -/// -/// @warning This function is not suitable for large area searches. If the search -/// extents overlaps more than 128 polygons it may return an invalid result. -/// -dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* nearestRef, float* nearestPt) const -{ - dtAssert(m_nav); - - *nearestRef = 0; - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = 0; - if (dtStatusFailed(queryPolygons(center, extents, filter, polys, &polyCount, 128))) - return DT_FAILURE | DT_INVALID_PARAM; - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) - { - dtPolyRef ref = polys[i]; - float closestPtPoly[3]; - closestPointOnPoly(ref, center, closestPtPoly); - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) - { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; - } - } - - if (nearestRef) - *nearestRef = nearest; - - return DT_SUCCESS; -} - -dtPolyRef dtNavMeshQuery::findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents, - const dtQueryFilter* filter, float* nearestPt) const -{ - dtAssert(m_nav); - - float bmin[3], bmax[3]; - dtVsub(bmin, center, extents); - dtVadd(bmax, center, extents); - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = queryPolygonsInTile(tile, bmin, bmax, filter, polys, 128); - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) - { - dtPolyRef ref = polys[i]; - const dtPoly* poly = &tile->polys[m_nav->decodePolyIdPoly(ref)]; - float closestPtPoly[3]; - closestPointOnPolyInTile(tile, poly, center, closestPtPoly); - - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) - { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; - } - } - - return nearest; -} - -int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, - const dtQueryFilter* filter, - dtPolyRef* polys, const int maxPolys) const -{ - dtAssert(m_nav); - - if (tile->bvTree) - { - const dtBVNode* node = &tile->bvTree[0]; - const dtBVNode* end = &tile->bvTree[tile->header->bvNodeCount]; - const float* tbmin = tile->header->bmin; - const float* tbmax = tile->header->bmax; - const float qfac = tile->header->bvQuantFactor; - - // Calculate quantized box - unsigned short bmin[3], bmax[3]; - // dtClamp query box to world box. - float minx = dtClamp(qmin[0], tbmin[0], tbmax[0]) - tbmin[0]; - float miny = dtClamp(qmin[1], tbmin[1], tbmax[1]) - tbmin[1]; - float minz = dtClamp(qmin[2], tbmin[2], tbmax[2]) - tbmin[2]; - float maxx = dtClamp(qmax[0], tbmin[0], tbmax[0]) - tbmin[0]; - float maxy = dtClamp(qmax[1], tbmin[1], tbmax[1]) - tbmin[1]; - float maxz = dtClamp(qmax[2], tbmin[2], tbmax[2]) - tbmin[2]; - // Quantize - bmin[0] = (unsigned short)(qfac * minx) & 0xfffe; - bmin[1] = (unsigned short)(qfac * miny) & 0xfffe; - bmin[2] = (unsigned short)(qfac * minz) & 0xfffe; - bmax[0] = (unsigned short)(qfac * maxx + 1) | 1; - bmax[1] = (unsigned short)(qfac * maxy + 1) | 1; - bmax[2] = (unsigned short)(qfac * maxz + 1) | 1; - - // Traverse tree - const dtPolyRef base = m_nav->getPolyRefBase(tile); - int n = 0; - while (node < end) - { - const bool overlap = dtOverlapQuantBounds(bmin, bmax, node->bmin, node->bmax); - const bool isLeafNode = node->i >= 0; - - if (isLeafNode && overlap) - { - dtPolyRef ref = base | (dtPolyRef)node->i; - if (filter->passFilter(ref, tile, &tile->polys[node->i])) - { - if (n < maxPolys) - polys[n++] = ref; - } - } - - if (overlap || isLeafNode) - node++; - else - { - const int escapeIndex = -node->i; - node += escapeIndex; - } - } - - return n; - } - else - { - float bmin[3], bmax[3]; - int n = 0; - const dtPolyRef base = m_nav->getPolyRefBase(tile); - for (int i = 0; i < tile->header->polyCount; ++i) - { - const dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - // Must pass filter - const dtPolyRef ref = base | (dtPolyRef)i; - if (!filter->passFilter(ref, tile, p)) - continue; - // Calc polygon bounds. - const float* v = &tile->verts[p->verts[0]*3]; - dtVcopy(bmin, v); - dtVcopy(bmax, v); - for (int j = 1; j < p->vertCount; ++j) - { - v = &tile->verts[p->verts[j]*3]; - dtVmin(bmin, v); - dtVmax(bmax, v); - } - if (dtOverlapBounds(qmin,qmax, bmin,bmax)) - { - if (n < maxPolys) - polys[n++] = ref; - } - } - return n; - } -} - -/// @par -/// -/// If no polygons are found, the function will return #DT_SUCCESS with a -/// @p polyCount of zero. -/// -/// If @p polys is too small to hold the entire result set, then the array will -/// be filled to capacity. The method of choosing which polygons from the -/// full set are included in the partial result set is undefined. -/// -dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* polys, int* polyCount, const int maxPolys) const -{ - dtAssert(m_nav); - - float bmin[3], bmax[3]; - dtVsub(bmin, center, extents); - dtVadd(bmax, center, extents); - - // Find tiles the query touches. - int minx, miny, maxx, maxy; - m_nav->calcTileLoc(bmin, &minx, &miny); - m_nav->calcTileLoc(bmax, &maxx, &maxy); - - static const int MAX_NEIS = 32; - const dtMeshTile* neis[MAX_NEIS]; - - int n = 0; - for (int y = miny; y <= maxy; ++y) - { - for (int x = minx; x <= maxx; ++x) - { - const int nneis = m_nav->getTilesAt(x,y,neis,MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - n += queryPolygonsInTile(neis[j], bmin, bmax, filter, polys+n, maxPolys-n); - if (n >= maxPolys) - { - *polyCount = n; - return DT_SUCCESS | DT_BUFFER_TOO_SMALL; - } - } - } - } - *polyCount = n; - - return DT_SUCCESS; -} - -/// @par -/// -/// If the end polygon cannot be reached through the navigation graph, -/// the last polygon in the path will be the nearest the end polygon. -/// -/// If the path array is to small to hold the full result, it will be filled as -/// far as possible from the start polygon toward the end polygon. -/// -/// The start and end positions are used to calculate traversal costs. -/// (The y-values impact the result.) -/// -dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter, - dtPolyRef* path, int* pathCount, const int maxPath) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - *pathCount = 0; - - if (!startRef || !endRef) - return DT_FAILURE | DT_INVALID_PARAM; - - if (!maxPath) - return DT_FAILURE | DT_INVALID_PARAM; - - // Validate input - if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - if (startRef == endRef) - { - path[0] = startRef; - *pathCount = 1; - return DT_SUCCESS; - } - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, startPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = dtVdist(startPos, endPos) * H_SCALE; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtNode* lastBestNode = startNode; - float lastBestNodeCost = startNode->total; - - dtStatus status = DT_SUCCESS; - - while (!m_openList->empty()) - { - // Remove node from open list and put it in closed list. - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Reached the goal, stop searching. - if (bestNode->id == endRef) - { - lastBestNode = bestNode; - break; - } - - // Get current poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - dtPolyRef neighbourRef = bestTile->links[i].ref; - - // Skip invalid ids and do not expand back to where we came from. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Get neighbour poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - // If the node is visited the first time, calculate node position. - if (neighbourNode->flags == 0) - { - getEdgeMidPoint(bestRef, bestPoly, bestTile, - neighbourRef, neighbourPoly, neighbourTile, - neighbourNode->pos); - } - - // Calculate cost and heuristic. - float cost = 0; - float heuristic = 0; - - // Special case for last node. - if (neighbourRef == endRef) - { - // Cost - const float curCost = filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - const float endCost = filter->getCost(neighbourNode->pos, endPos, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly, - 0, 0, 0); - - cost = bestNode->cost + curCost + endCost; - heuristic = 0; - } - else - { - // Cost - const float curCost = filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - cost = bestNode->cost + curCost; - heuristic = dtVdist(neighbourNode->pos, endPos)*H_SCALE; - } - - const float total = cost + heuristic; - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - // The node is already visited and process, and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_CLOSED) && total >= neighbourNode->total) - continue; - - // Add or update the node. - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->cost = cost; - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - // Already in open, update node location. - m_openList->modify(neighbourNode); - } - else - { - // Put the node in open list. - neighbourNode->flags |= DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - - // Update nearest node to target so far. - if (heuristic < lastBestNodeCost) - { - lastBestNodeCost = heuristic; - lastBestNode = neighbourNode; - } - } - } - - if (lastBestNode->id != endRef) - status |= DT_PARTIAL_RESULT; - - // Reverse the path. - dtNode* prev = 0; - dtNode* node = lastBestNode; - do - { - dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); - node->pidx = m_nodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store path - node = prev; - int n = 0; - do - { - path[n++] = node->id; - if (n >= maxPath) - { - status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_nodePool->getNodeAtIdx(node->pidx); - } - while (node); - - *pathCount = n; - - return status; -} - -/// @par -/// -/// @warning Calling any non-slice methods before calling finalizeSlicedFindPath() -/// or finalizeSlicedFindPathPartial() may result in corrupted data! -/// -/// The @p filter pointer is stored and used for the duration of the sliced -/// path query. -/// -dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter) -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - // Init path state. - memset(&m_query, 0, sizeof(dtQueryData)); - m_query.status = DT_FAILURE; - m_query.startRef = startRef; - m_query.endRef = endRef; - dtVcopy(m_query.startPos, startPos); - dtVcopy(m_query.endPos, endPos); - m_query.filter = filter; - - if (!startRef || !endRef) - return DT_FAILURE | DT_INVALID_PARAM; - - // Validate input - if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - if (startRef == endRef) - { - m_query.status = DT_SUCCESS; - return DT_SUCCESS; - } - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, startPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = dtVdist(startPos, endPos) * H_SCALE; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - m_query.status = DT_IN_PROGRESS; - m_query.lastBestNode = startNode; - m_query.lastBestNodeCost = startNode->total; - - return m_query.status; -} - -dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) -{ - if (!dtStatusInProgress(m_query.status)) - return m_query.status; - - // Make sure the request is still valid. - if (!m_nav->isValidPolyRef(m_query.startRef) || !m_nav->isValidPolyRef(m_query.endRef)) - { - m_query.status = DT_FAILURE; - return DT_FAILURE; - } - - int iter = 0; - while (iter < maxIter && !m_openList->empty()) - { - iter++; - - // Remove node from open list and put it in closed list. - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Reached the goal, stop searching. - if (bestNode->id == m_query.endRef) - { - m_query.lastBestNode = bestNode; - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - m_query.status = DT_SUCCESS | details; - if (doneIters) - *doneIters = iter; - return m_query.status; - } - - // Get current poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(bestRef, &bestTile, &bestPoly))) - { - // The polygon has disappeared during the sliced query, fail. - m_query.status = DT_FAILURE; - if (doneIters) - *doneIters = iter; - return m_query.status; - } - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - { - if (dtStatusFailed(m_nav->getTileAndPolyByRef(parentRef, &parentTile, &parentPoly))) - { - // The polygon has disappeared during the sliced query, fail. - m_query.status = DT_FAILURE; - if (doneIters) - *doneIters = iter; - return m_query.status; - } - } - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - dtPolyRef neighbourRef = bestTile->links[i].ref; - - // Skip invalid ids and do not expand back to where we came from. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Get neighbour poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - if (!m_query.filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - m_query.status |= DT_OUT_OF_NODES; - continue; - } - - // If the node is visited the first time, calculate node position. - if (neighbourNode->flags == 0) - { - getEdgeMidPoint(bestRef, bestPoly, bestTile, - neighbourRef, neighbourPoly, neighbourTile, - neighbourNode->pos); - } - - // Calculate cost and heuristic. - float cost = 0; - float heuristic = 0; - - // Special case for last node. - if (neighbourRef == m_query.endRef) - { - // Cost - const float curCost = m_query.filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - const float endCost = m_query.filter->getCost(neighbourNode->pos, m_query.endPos, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly, - 0, 0, 0); - - cost = bestNode->cost + curCost + endCost; - heuristic = 0; - } - else - { - // Cost - const float curCost = m_query.filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - cost = bestNode->cost + curCost; - heuristic = dtVdist(neighbourNode->pos, m_query.endPos)*H_SCALE; - } - - const float total = cost + heuristic; - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - // The node is already visited and process, and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_CLOSED) && total >= neighbourNode->total) - continue; - - // Add or update the node. - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->cost = cost; - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - // Already in open, update node location. - m_openList->modify(neighbourNode); - } - else - { - // Put the node in open list. - neighbourNode->flags |= DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - - // Update nearest node to target so far. - if (heuristic < m_query.lastBestNodeCost) - { - m_query.lastBestNodeCost = heuristic; - m_query.lastBestNode = neighbourNode; - } - } - } - - // Exhausted all nodes, but could not find path. - if (m_openList->empty()) - { - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - m_query.status = DT_SUCCESS | details; - } - - if (doneIters) - *doneIters = iter; - - return m_query.status; -} - -dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath) -{ - *pathCount = 0; - - if (dtStatusFailed(m_query.status)) - { - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - return DT_FAILURE; - } - - int n = 0; - - if (m_query.startRef == m_query.endRef) - { - // Special case: the search starts and ends at same poly. - path[n++] = m_query.startRef; - } - else - { - // Reverse the path. - dtAssert(m_query.lastBestNode); - - if (m_query.lastBestNode->id != m_query.endRef) - m_query.status |= DT_PARTIAL_RESULT; - - dtNode* prev = 0; - dtNode* node = m_query.lastBestNode; - do - { - dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); - node->pidx = m_nodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store path - node = prev; - do - { - path[n++] = node->id; - if (n >= maxPath) - { - m_query.status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_nodePool->getNodeAtIdx(node->pidx); - } - while (node); - } - - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - - *pathCount = n; - - return DT_SUCCESS | details; -} - -dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, - dtPolyRef* path, int* pathCount, const int maxPath) -{ - *pathCount = 0; - - if (existingSize == 0) - { - return DT_FAILURE; - } - - if (dtStatusFailed(m_query.status)) - { - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - return DT_FAILURE; - } - - int n = 0; - - if (m_query.startRef == m_query.endRef) - { - // Special case: the search starts and ends at same poly. - path[n++] = m_query.startRef; - } - else - { - // Find furthest existing node that was visited. - dtNode* prev = 0; - dtNode* node = 0; - for (int i = existingSize-1; i >= 0; --i) - { - node = m_nodePool->findNode(existing[i]); - if (node) - break; - } - - if (!node) - { - return DT_FAILURE; - } - - // Reverse the path. - do - { - dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); - node->pidx = m_nodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store path - node = prev; - do - { - path[n++] = node->id; - if (n >= maxPath) - { - m_query.status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_nodePool->getNodeAtIdx(node->pidx); - } - while (node); - } - - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - - *pathCount = n; - - return DT_SUCCESS | details; -} - -/// @par -/// -/// This method peforms what is often called 'string pulling'. -/// -/// The start position is clamped to the first polygon in the path, and the -/// end position is clamped to the last. So the start and end positions should -/// normally be within or very near the first and last polygons respectively. -/// -/// The returned polygon references represent the reference id of the polygon -/// that is entered at the associated path position. The reference id associated -/// with the end point will always be zero. This allows, for example, matching -/// off-mesh link points to their representative polygons. -/// -/// If the provided result buffers are too small for the entire result set, -/// they will be filled as far as possible from the start toward the end -/// position. -/// -dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* endPos, - const dtPolyRef* path, const int pathSize, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath) const -{ - dtAssert(m_nav); - - *straightPathCount = 0; - - if (!maxStraightPath) - return DT_FAILURE | DT_INVALID_PARAM; - - if (!path[0]) - return DT_FAILURE | DT_INVALID_PARAM; - - int n = 0; - - // TODO: Should this be callers responsibility? - float closestStartPos[3]; - if (dtStatusFailed(closestPointOnPolyBoundary(path[0], startPos, closestStartPos))) - return DT_FAILURE | DT_INVALID_PARAM; - - // Add start point. - dtVcopy(&straightPath[n*3], closestStartPos); - if (straightPathFlags) - straightPathFlags[n] = DT_STRAIGHTPATH_START; - if (straightPathRefs) - straightPathRefs[n] = path[0]; - n++; - if (n >= maxStraightPath) - { - *straightPathCount = n; - return DT_SUCCESS | DT_BUFFER_TOO_SMALL; - } - - float closestEndPos[3]; - if (dtStatusFailed(closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos))) - return DT_FAILURE | DT_INVALID_PARAM; - - if (pathSize > 1) - { - float portalApex[3], portalLeft[3], portalRight[3]; - dtVcopy(portalApex, closestStartPos); - dtVcopy(portalLeft, portalApex); - dtVcopy(portalRight, portalApex); - int apexIndex = 0; - int leftIndex = 0; - int rightIndex = 0; - - unsigned char leftPolyType = 0; - unsigned char rightPolyType = 0; - - dtPolyRef leftPolyRef = path[0]; - dtPolyRef rightPolyRef = path[0]; - - for (int i = 0; i < pathSize; ++i) - { - float left[3], right[3]; - unsigned char fromType, toType; - - if (i+1 < pathSize) - { - // Next portal. - if (dtStatusFailed(getPortalPoints(path[i], path[i+1], left, right, fromType, toType))) - { - // Failed to get portal points, in practice this means that path[i+1] is invalid polygon. - // Clamp the end point to path[i], and return the path so far. - - if (dtStatusFailed(closestPointOnPolyBoundary(path[i], endPos, closestEndPos))) - { - // This should only happen when the first polygon is invalid. - return DT_FAILURE | DT_INVALID_PARAM; - } - - dtVcopy(&straightPath[n*3], closestEndPos); - if (straightPathFlags) - straightPathFlags[n] = 0; - if (straightPathRefs) - straightPathRefs[n] = path[i]; - n++; - - *straightPathCount = n; - - return DT_SUCCESS | DT_PARTIAL_RESULT | ((n >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); - } - - // If starting really close the portal, advance. - if (i == 0) - { - float t; - if (dtDistancePtSegSqr2D(portalApex, left, right, t) < dtSqr(0.001f)) - continue; - } - } - else - { - // End of the path. - dtVcopy(left, closestEndPos); - dtVcopy(right, closestEndPos); - - fromType = toType = DT_POLYTYPE_GROUND; - } - - // Right vertex. - if (dtTriArea2D(portalApex, portalRight, right) <= 0.0f) - { - if (dtVequal(portalApex, portalRight) || dtTriArea2D(portalApex, portalLeft, right) > 0.0f) - { - dtVcopy(portalRight, right); - rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0; - rightPolyType = toType; - rightIndex = i; - } - else - { - dtVcopy(portalApex, portalLeft); - apexIndex = leftIndex; - - unsigned char flags = 0; - if (!leftPolyRef) - flags = DT_STRAIGHTPATH_END; - else if (leftPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) - flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; - dtPolyRef ref = leftPolyRef; - - if (!dtVequal(&straightPath[(n-1)*3], portalApex)) - { - // Append new vertex. - dtVcopy(&straightPath[n*3], portalApex); - if (straightPathFlags) - straightPathFlags[n] = flags; - if (straightPathRefs) - straightPathRefs[n] = ref; - n++; - // If reached end of path or there is no space to append more vertices, return. - if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath) - { - *straightPathCount = n; - return DT_SUCCESS | ((n >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); - } - } - else - { - // The vertices are equal, update flags and poly. - if (straightPathFlags) - straightPathFlags[n-1] = flags; - if (straightPathRefs) - straightPathRefs[n-1] = ref; - } - - dtVcopy(portalLeft, portalApex); - dtVcopy(portalRight, portalApex); - leftIndex = apexIndex; - rightIndex = apexIndex; - - // Restart - i = apexIndex; - - continue; - } - } - - // Left vertex. - if (dtTriArea2D(portalApex, portalLeft, left) >= 0.0f) - { - if (dtVequal(portalApex, portalLeft) || dtTriArea2D(portalApex, portalRight, left) < 0.0f) - { - dtVcopy(portalLeft, left); - leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0; - leftPolyType = toType; - leftIndex = i; - } - else - { - dtVcopy(portalApex, portalRight); - apexIndex = rightIndex; - - unsigned char flags = 0; - if (!rightPolyRef) - flags = DT_STRAIGHTPATH_END; - else if (rightPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) - flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; - dtPolyRef ref = rightPolyRef; - - if (!dtVequal(&straightPath[(n-1)*3], portalApex)) - { - // Append new vertex. - dtVcopy(&straightPath[n*3], portalApex); - if (straightPathFlags) - straightPathFlags[n] = flags; - if (straightPathRefs) - straightPathRefs[n] = ref; - n++; - // If reached end of path or there is no space to append more vertices, return. - if (flags == DT_STRAIGHTPATH_END || n >= maxStraightPath) - { - *straightPathCount = n; - return DT_SUCCESS | ((n >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); - } - } - else - { - // The vertices are equal, update flags and poly. - if (straightPathFlags) - straightPathFlags[n-1] = flags; - if (straightPathRefs) - straightPathRefs[n-1] = ref; - } - - dtVcopy(portalLeft, portalApex); - dtVcopy(portalRight, portalApex); - leftIndex = apexIndex; - rightIndex = apexIndex; - - // Restart - i = apexIndex; - - continue; - } - } - } - } - - // If the point already exists, remove it and add reappend the actual end location. - if (n > 0 && dtVequal(&straightPath[(n-1)*3], closestEndPos)) - n--; - - // Add end point. - if (n < maxStraightPath) - { - dtVcopy(&straightPath[n*3], closestEndPos); - if (straightPathFlags) - straightPathFlags[n] = DT_STRAIGHTPATH_END; - if (straightPathRefs) - straightPathRefs[n] = 0; - n++; - } - - *straightPathCount = n; - - return DT_SUCCESS | ((n >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); -} - -/// @par -/// -/// This method is optimized for small delta movement and a small number of -/// polygons. If used for too great a distance, the result set will form an -/// incomplete path. -/// -/// @p resultPos will equal the @p endPos if the end is reached. -/// Otherwise the closest reachable position will be returned. -/// -/// @p resultPos is not projected onto the surface of the navigation -/// mesh. Use #getPolyHeight if this is needed. -/// -/// This method treats the end position in the same manner as -/// the #raycast method. (As a 2D point.) See that method's documentation -/// for details. -/// -/// If the @p visited array is too small to hold the entire result set, it will -/// be filled as far as possible from the start position toward the end -/// position. -/// -dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const -{ - dtAssert(m_nav); - dtAssert(m_tinyNodePool); - - *visitedCount = 0; - - // Validate input - if (!startRef) - return DT_FAILURE | DT_INVALID_PARAM; - if (!m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - dtStatus status = DT_SUCCESS; - - static const int MAX_STACK = 48; - dtNode* stack[MAX_STACK]; - int nstack = 0; - - m_tinyNodePool->clear(); - - dtNode* startNode = m_tinyNodePool->getNode(startRef); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_CLOSED; - stack[nstack++] = startNode; - - float bestPos[3]; - float bestDist = FLT_MAX; - dtNode* bestNode = 0; - dtVcopy(bestPos, startPos); - - // Search constraints - float searchPos[3], searchRadSqr; - dtVlerp(searchPos, startPos, endPos, 0.5f); - searchRadSqr = dtSqr(dtVdist(startPos, endPos)/2.0f + 0.001f); - - float verts[DT_VERTS_PER_POLYGON*3]; - - while (nstack) - { - // Pop front. - dtNode* curNode = stack[0]; - for (int i = 0; i < nstack-1; ++i) - stack[i] = stack[i+1]; - nstack--; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef curRef = curNode->id; - const dtMeshTile* curTile = 0; - const dtPoly* curPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(curRef, &curTile, &curPoly); - - // Collect vertices. - const int nverts = curPoly->vertCount; - for (int i = 0; i < nverts; ++i) - dtVcopy(&verts[i*3], &curTile->verts[curPoly->verts[i]*3]); - - // If target is inside the poly, stop search. - if (dtPointInPolygon(endPos, verts, nverts)) - { - bestNode = curNode; - dtVcopy(bestPos, endPos); - break; - } - - // Find wall edges and find nearest point inside the walls. - for (int i = 0, j = (int)curPoly->vertCount-1; i < (int)curPoly->vertCount; j = i++) - { - // Find links to neighbours. - static const int MAX_NEIS = 8; - int nneis = 0; - dtPolyRef neis[MAX_NEIS]; - - if (curPoly->neis[j] & DT_EXT_LINK) - { - // Tile border. - for (unsigned int k = curPoly->firstLink; k != DT_NULL_LINK; k = curTile->links[k].next) - { - const dtLink* link = &curTile->links[k]; - if (link->edge == j) - { - if (link->ref != 0) - { - const dtMeshTile* neiTile = 0; - const dtPoly* neiPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); - if (filter->passFilter(link->ref, neiTile, neiPoly)) - { - if (nneis < MAX_NEIS) - neis[nneis++] = link->ref; - } - } - } - } - } - else if (curPoly->neis[j]) - { - const unsigned int idx = (unsigned int)(curPoly->neis[j]-1); - const dtPolyRef ref = m_nav->getPolyRefBase(curTile) | idx; - if (filter->passFilter(ref, curTile, &curTile->polys[idx])) - { - // Internal edge, encode id. - neis[nneis++] = ref; - } - } - - if (!nneis) - { - // Wall edge, calc distance. - const float* vj = &verts[j*3]; - const float* vi = &verts[i*3]; - float tseg; - const float distSqr = dtDistancePtSegSqr2D(endPos, vj, vi, tseg); - if (distSqr < bestDist) - { - // Update nearest distance. - dtVlerp(bestPos, vj,vi, tseg); - bestDist = distSqr; - bestNode = curNode; - } - } - else - { - for (int k = 0; k < nneis; ++k) - { - // Skip if no node can be allocated. - dtNode* neighbourNode = m_tinyNodePool->getNode(neis[k]); - if (!neighbourNode) - continue; - // Skip if already visited. - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Skip the link if it is too far from search constraint. - // TODO: Maybe should use getPortalPoints(), but this one is way faster. - const float* vj = &verts[j*3]; - const float* vi = &verts[i*3]; - float tseg; - float distSqr = dtDistancePtSegSqr2D(searchPos, vj, vi, tseg); - if (distSqr > searchRadSqr) - continue; - - // Mark as the node as visited and push to queue. - if (nstack < MAX_STACK) - { - neighbourNode->pidx = m_tinyNodePool->getNodeIdx(curNode); - neighbourNode->flags |= DT_NODE_CLOSED; - stack[nstack++] = neighbourNode; - } - } - } - } - } - - int n = 0; - if (bestNode) - { - // Reverse the path. - dtNode* prev = 0; - dtNode* node = bestNode; - do - { - dtNode* next = m_tinyNodePool->getNodeAtIdx(node->pidx); - node->pidx = m_tinyNodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store result - node = prev; - do - { - visited[n++] = node->id; - if (n >= maxVisitedSize) - { - status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_tinyNodePool->getNodeAtIdx(node->pidx); - } - while (node); - } - - dtVcopy(resultPos, bestPos); - - *visitedCount = n; - - return status; -} - - -dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, - unsigned char& fromType, unsigned char& toType) const -{ - dtAssert(m_nav); - - const dtMeshTile* fromTile = 0; - const dtPoly* fromPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - fromType = fromPoly->getType(); - - const dtMeshTile* toTile = 0; - const dtPoly* toPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - toType = toPoly->getType(); - - return getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right); -} - -// Returns portal points between two polygons. -dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* left, float* right) const -{ - // Find the link that points to the 'to' polygon. - const dtLink* link = 0; - for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromTile->links[i].next) - { - if (fromTile->links[i].ref == to) - { - link = &fromTile->links[i]; - break; - } - } - if (!link) - return DT_FAILURE | DT_INVALID_PARAM; - - // Handle off-mesh connections. - if (fromPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - // Find link that points to first vertex. - for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromTile->links[i].next) - { - if (fromTile->links[i].ref == to) - { - const int v = fromTile->links[i].edge; - dtVcopy(left, &fromTile->verts[fromPoly->verts[v]*3]); - dtVcopy(right, &fromTile->verts[fromPoly->verts[v]*3]); - return DT_SUCCESS; - } - } - return DT_FAILURE | DT_INVALID_PARAM; - } - - if (toPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - for (unsigned int i = toPoly->firstLink; i != DT_NULL_LINK; i = toTile->links[i].next) - { - if (toTile->links[i].ref == from) - { - const int v = toTile->links[i].edge; - dtVcopy(left, &toTile->verts[toPoly->verts[v]*3]); - dtVcopy(right, &toTile->verts[toPoly->verts[v]*3]); - return DT_SUCCESS; - } - } - return DT_FAILURE | DT_INVALID_PARAM; - } - - // Find portal vertices. - const int v0 = fromPoly->verts[link->edge]; - const int v1 = fromPoly->verts[(link->edge+1) % (int)fromPoly->vertCount]; - dtVcopy(left, &fromTile->verts[v0*3]); - dtVcopy(right, &fromTile->verts[v1*3]); - - // If the link is at tile boundary, dtClamp the vertices to - // the link width. - if (link->side != 0xff) - { - // Unpack portal limits. - if (link->bmin != 0 || link->bmax != 255) - { - const float s = 1.0f/255.0f; - const float tmin = link->bmin*s; - const float tmax = link->bmax*s; - dtVlerp(left, &fromTile->verts[v0*3], &fromTile->verts[v1*3], tmin); - dtVlerp(right, &fromTile->verts[v0*3], &fromTile->verts[v1*3], tmax); - } - } - - return DT_SUCCESS; -} - -// Returns edge mid point between two polygons. -dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const -{ - float left[3], right[3]; - unsigned char fromType, toType; - if (dtStatusFailed(getPortalPoints(from, to, left,right, fromType, toType))) - return DT_FAILURE | DT_INVALID_PARAM; - mid[0] = (left[0]+right[0])*0.5f; - mid[1] = (left[1]+right[1])*0.5f; - mid[2] = (left[2]+right[2])*0.5f; - return DT_SUCCESS; -} - -dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* mid) const -{ - float left[3], right[3]; - if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right))) - return DT_FAILURE | DT_INVALID_PARAM; - mid[0] = (left[0]+right[0])*0.5f; - mid[1] = (left[1]+right[1])*0.5f; - mid[2] = (left[2]+right[2])*0.5f; - return DT_SUCCESS; -} - -/// @par -/// -/// This method is meant to be used for quick, short distance checks. -/// -/// If the path array is too small to hold the result, it will be filled as -/// far as possible from the start postion toward the end position. -/// -/// Using the Hit Parameter (t) -/// -/// If the hit parameter is a very high value (FLT_MAX), then the ray has hit -/// the end position. In this case the path represents a valid corridor to the -/// end position and the value of @p hitNormal is undefined. -/// -/// If the hit parameter is zero, then the start position is on the wall that -/// was hit and the value of @p hitNormal is undefined. -/// -/// If 0 < t < 1.0 then the following applies: -/// -/// @code -/// distanceToHitBorder = distanceToEndPosition * t -/// hitPoint = startPos + (endPos - startPos) * t -/// @endcode -/// -/// Use Case Restriction -/// -/// The raycast ignores the y-value of the end position. (2D check.) This -/// places significant limits on how it can be used. For example: -/// -/// Consider a scene where there is a main floor with a second floor balcony -/// that hangs over the main floor. So the first floor mesh extends below the -/// balcony mesh. The start position is somewhere on the first floor. The end -/// position is on the balcony. -/// -/// The raycast will search toward the end position along the first floor mesh. -/// If it reaches the end position's xz-coordinates it will indicate FLT_MAX -/// (no wall hit), meaning it reached the end position. This is one example of why -/// this method is meant for short distance checks. -/// -dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const -{ - dtAssert(m_nav); - - *t = 0; - if (pathCount) - *pathCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - dtPolyRef curRef = startRef; - float verts[DT_VERTS_PER_POLYGON*3]; - int n = 0; - - hitNormal[0] = 0; - hitNormal[1] = 0; - hitNormal[2] = 0; - - dtStatus status = DT_SUCCESS; - - while (curRef) - { - // Cast ray against current polygon. - - // The API input has been cheked already, skip checking internal data. - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - m_nav->getTileAndPolyByRefUnsafe(curRef, &tile, &poly); - - // Collect vertices. - int nv = 0; - for (int i = 0; i < (int)poly->vertCount; ++i) - { - dtVcopy(&verts[nv*3], &tile->verts[poly->verts[i]*3]); - nv++; - } - - float tmin, tmax; - int segMin, segMax; - if (!dtIntersectSegmentPoly2D(startPos, endPos, verts, nv, tmin, tmax, segMin, segMax)) - { - // Could not hit the polygon, keep the old t and report hit. - if (pathCount) - *pathCount = n; - return status; - } - // Keep track of furthest t so far. - if (tmax > *t) - *t = tmax; - - // Store visited polygons. - if (n < maxPath) - path[n++] = curRef; - else - status |= DT_BUFFER_TOO_SMALL; - - // Ray end is completely inside the polygon. - if (segMax == -1) - { - *t = FLT_MAX; - if (pathCount) - *pathCount = n; - return status; - } - - // Follow neighbours. - dtPolyRef nextRef = 0; - - for (unsigned int i = poly->firstLink; i != DT_NULL_LINK; i = tile->links[i].next) - { - const dtLink* link = &tile->links[i]; - - // Find link which contains this edge. - if ((int)link->edge != segMax) - continue; - - // Get pointer to the next polygon. - const dtMeshTile* nextTile = 0; - const dtPoly* nextPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &nextTile, &nextPoly); - - // Skip off-mesh connections. - if (nextPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Skip links based on filter. - if (!filter->passFilter(link->ref, nextTile, nextPoly)) - continue; - - // If the link is internal, just return the ref. - if (link->side == 0xff) - { - nextRef = link->ref; - break; - } - - // If the link is at tile boundary, - - // Check if the link spans the whole edge, and accept. - if (link->bmin == 0 && link->bmax == 255) - { - nextRef = link->ref; - break; - } - - // Check for partial edge links. - const int v0 = poly->verts[link->edge]; - const int v1 = poly->verts[(link->edge+1) % poly->vertCount]; - const float* left = &tile->verts[v0*3]; - const float* right = &tile->verts[v1*3]; - - // Check that the intersection lies inside the link portal. - if (link->side == 0 || link->side == 4) - { - // Calculate link size. - const float s = 1.0f/255.0f; - float lmin = left[2] + (right[2] - left[2])*(link->bmin*s); - float lmax = left[2] + (right[2] - left[2])*(link->bmax*s); - if (lmin > lmax) dtSwap(lmin, lmax); - - // Find Z intersection. - float z = startPos[2] + (endPos[2]-startPos[2])*tmax; - if (z >= lmin && z <= lmax) - { - nextRef = link->ref; - break; - } - } - else if (link->side == 2 || link->side == 6) - { - // Calculate link size. - const float s = 1.0f/255.0f; - float lmin = left[0] + (right[0] - left[0])*(link->bmin*s); - float lmax = left[0] + (right[0] - left[0])*(link->bmax*s); - if (lmin > lmax) dtSwap(lmin, lmax); - - // Find X intersection. - float x = startPos[0] + (endPos[0]-startPos[0])*tmax; - if (x >= lmin && x <= lmax) - { - nextRef = link->ref; - break; - } - } - } - - if (!nextRef) - { - // No neighbour, we hit a wall. - - // Calculate hit normal. - const int a = segMax; - const int b = segMax+1 < nv ? segMax+1 : 0; - const float* va = &verts[a*3]; - const float* vb = &verts[b*3]; - const float dx = vb[0] - va[0]; - const float dz = vb[2] - va[2]; - hitNormal[0] = dz; - hitNormal[1] = 0; - hitNormal[2] = -dx; - dtVnormalize(hitNormal); - - if (pathCount) - *pathCount = n; - return status; - } - - // No hit, advance to neighbour polygon. - curRef = nextRef; - } - - if (pathCount) - *pathCount = n; - - return status; -} - -/// @par -/// -/// At least one result array must be provided. -/// -/// The order of the result set is from least to highest cost to reach the polygon. -/// -/// A common use case for this method is to perform Dijkstra searches. -/// Candidate polygons are found by searching the graph beginning at the start polygon. -/// -/// If a polygon is not found via the graph search, even if it intersects the -/// search circle, it will not be included in the result set. For example: -/// -/// polyA is the start polygon. -/// polyB shares an edge with polyA. (Is adjacent.) -/// polyC shares an edge with polyB, but not with polyA -/// Even if the search circle overlaps polyC, it will not be included in the -/// result set unless polyB is also in the set. -/// -/// The value of the center point is used as the start position for cost -/// calculations. It is not projected onto the surface of the mesh, so its -/// y-value will effect the costs. -/// -/// Intersection tests occur in 2D. All polygons and the search circle are -/// projected onto the xz-plane. So the y-value of the center point does not -/// effect intersection tests. -/// -/// If the result arrays are to small to hold the entire result set, they will be -/// filled to capacity. -/// -dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - *resultCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtStatus status = DT_SUCCESS; - - int n = 0; - if (n < maxResult) - { - if (resultRef) - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - if (resultCost) - resultCost[n] = 0; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - const float radiusSqr = dtSqr(radius); - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the circle is not touching the next polygon, skip it. - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - if (distSqr > radiusSqr) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - dtVlerp(neighbourNode->pos, va, vb, 0.5f); - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - if (n < maxResult) - { - if (resultRef) - resultRef[n] = neighbourNode->id; - if (resultParent) - resultParent[n] = m_nodePool->getNodeAtIdx(neighbourNode->pidx)->id; - if (resultCost) - resultCost[n] = neighbourNode->total; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - neighbourNode->flags = DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - *resultCount = n; - - return status; -} - -/// @par -/// -/// The order of the result set is from least to highest cost. -/// -/// At least one result array must be provided. -/// -/// A common use case for this method is to perform Dijkstra searches. -/// Candidate polygons are found by searching the graph beginning at the start -/// polygon. -/// -/// The same intersection test restrictions that apply to findPolysAroundCircle() -/// method apply to this method. -/// -/// The 3D centroid of the search polygon is used as the start position for cost -/// calculations. -/// -/// Intersection tests occur in 2D. All polygons are projected onto the -/// xz-plane. So the y-values of the vertices do not effect intersection tests. -/// -/// If the result arrays are is too small to hold the entire result set, they will -/// be filled to capacity. -/// -dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - *resultCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - float centerPos[3] = {0,0,0}; - for (int i = 0; i < nverts; ++i) - dtVadd(centerPos,centerPos,&verts[i*3]); - dtVscale(centerPos,centerPos,1.0f/nverts); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtStatus status = DT_SUCCESS; - - int n = 0; - if (n < maxResult) - { - if (resultRef) - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - if (resultCost) - resultCost[n] = 0; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the poly is not touching the edge to the next polygon, skip the connection it. - float tmin, tmax; - int segMin, segMax; - if (!dtIntersectSegmentPoly2D(va, vb, verts, nverts, tmin, tmax, segMin, segMax)) - continue; - if (tmin > 1.0f || tmax < 0.0f) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - dtVlerp(neighbourNode->pos, va, vb, 0.5f); - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - if (n < maxResult) - { - if (resultRef) - resultRef[n] = neighbourNode->id; - if (resultParent) - resultParent[n] = m_nodePool->getNodeAtIdx(neighbourNode->pidx)->id; - if (resultCost) - resultCost[n] = neighbourNode->total; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - neighbourNode->flags = DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - *resultCount = n; - - return status; -} - -/// @par -/// -/// This method is optimized for a small search radius and small number of result -/// polygons. -/// -/// Candidate polygons are found by searching the navigation graph beginning at -/// the start polygon. -/// -/// The same intersection test restrictions that apply to the findPolysAroundCircle -/// mehtod applies to this method. -/// -/// The value of the center point is used as the start point for cost calculations. -/// It is not projected onto the surface of the mesh, so its y-value will effect -/// the costs. -/// -/// Intersection tests occur in 2D. All polygons and the search circle are -/// projected onto the xz-plane. So the y-value of the center point does not -/// effect intersection tests. -/// -/// If the result arrays are is too small to hold the entire result set, they will -/// be filled to capacity. -/// -dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, - int* resultCount, const int maxResult) const -{ - dtAssert(m_nav); - dtAssert(m_tinyNodePool); - - *resultCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - static const int MAX_STACK = 48; - dtNode* stack[MAX_STACK]; - int nstack = 0; - - m_tinyNodePool->clear(); - - dtNode* startNode = m_tinyNodePool->getNode(startRef); - startNode->pidx = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_CLOSED; - stack[nstack++] = startNode; - - const float radiusSqr = dtSqr(radius); - - float pa[DT_VERTS_PER_POLYGON*3]; - float pb[DT_VERTS_PER_POLYGON*3]; - - dtStatus status = DT_SUCCESS; - - int n = 0; - if (n < maxResult) - { - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - while (nstack) - { - // Pop front. - dtNode* curNode = stack[0]; - for (int i = 0; i < nstack-1; ++i) - stack[i] = stack[i+1]; - nstack--; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef curRef = curNode->id; - const dtMeshTile* curTile = 0; - const dtPoly* curPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(curRef, &curTile, &curPoly); - - for (unsigned int i = curPoly->firstLink; i != DT_NULL_LINK; i = curTile->links[i].next) - { - const dtLink* link = &curTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours. - if (!neighbourRef) - continue; - - // Skip if cannot alloca more nodes. - dtNode* neighbourNode = m_tinyNodePool->getNode(neighbourRef); - if (!neighbourNode) - continue; - // Skip visited. - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Skip off-mesh connections. - if (neighbourPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(curRef, curPoly, curTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the circle is not touching the next polygon, skip it. - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - if (distSqr > radiusSqr) - continue; - - // Mark node visited, this is done before the overlap test so that - // we will not visit the poly again if the test fails. - neighbourNode->flags |= DT_NODE_CLOSED; - neighbourNode->pidx = m_tinyNodePool->getNodeIdx(curNode); - - // Check that the polygon does not collide with existing polygons. - - // Collect vertices of the neighbour poly. - const int npa = neighbourPoly->vertCount; - for (int k = 0; k < npa; ++k) - dtVcopy(&pa[k*3], &neighbourTile->verts[neighbourPoly->verts[k]*3]); - - bool overlap = false; - for (int j = 0; j < n; ++j) - { - dtPolyRef pastRef = resultRef[j]; - - // Connected polys do not overlap. - bool connected = false; - for (unsigned int k = curPoly->firstLink; k != DT_NULL_LINK; k = curTile->links[k].next) - { - if (curTile->links[k].ref == pastRef) - { - connected = true; - break; - } - } - if (connected) - continue; - - // Potentially overlapping. - const dtMeshTile* pastTile = 0; - const dtPoly* pastPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(pastRef, &pastTile, &pastPoly); - - // Get vertices and test overlap - const int npb = pastPoly->vertCount; - for (int k = 0; k < npb; ++k) - dtVcopy(&pb[k*3], &pastTile->verts[pastPoly->verts[k]*3]); - - if (dtOverlapPolyPoly2D(pa,npa, pb,npb)) - { - overlap = true; - break; - } - } - if (overlap) - continue; - - // This poly is fine, store and advance to the poly. - if (n < maxResult) - { - resultRef[n] = neighbourRef; - if (resultParent) - resultParent[n] = curRef; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - if (nstack < MAX_STACK) - { - stack[nstack++] = neighbourNode; - } - } - } - - *resultCount = n; - - return status; -} - - -struct dtSegInterval -{ - dtPolyRef ref; - short tmin, tmax; -}; - -static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, - const short tmin, const short tmax, const dtPolyRef ref) -{ - if (nints+1 > maxInts) return; - // Find insertion point. - int idx = 0; - while (idx < nints) - { - if (tmax <= ints[idx].tmin) - break; - idx++; - } - // Move current results. - if (nints-idx) - memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx)); - // Store - ints[idx].ref = ref; - ints[idx].tmin = tmin; - ints[idx].tmax = tmax; - nints++; -} - -/// @par -/// -/// If the @p segmentRefs parameter is provided, then all polygon segments will be returned. -/// Otherwise only the wall segments are returned. -/// -/// A segment that is normally a portal will be included in the result set as a -/// wall if the @p filter results in the neighbor polygon becoomming impassable. -/// -/// The @p segmentVerts and @p segmentRefs buffers should normally be sized for the -/// maximum segments per polygon of the source navigation mesh. -/// -dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, - float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, - const int maxSegments) const -{ - dtAssert(m_nav); - - *segmentCount = 0; - - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - - int n = 0; - static const int MAX_INTERVAL = 16; - dtSegInterval ints[MAX_INTERVAL]; - int nints; - - const bool storePortals = segmentRefs != 0; - - dtStatus status = DT_SUCCESS; - - for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++) - { - // Skip non-solid edges. - nints = 0; - if (poly->neis[j] & DT_EXT_LINK) - { - // Tile border. - for (unsigned int k = poly->firstLink; k != DT_NULL_LINK; k = tile->links[k].next) - { - const dtLink* link = &tile->links[k]; - if (link->edge == j) - { - if (link->ref != 0) - { - const dtMeshTile* neiTile = 0; - const dtPoly* neiPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); - if (filter->passFilter(link->ref, neiTile, neiPoly)) - { - insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax, link->ref); - } - } - } - } - } - else - { - // Internal edge - dtPolyRef neiRef = 0; - if (poly->neis[j]) - { - const unsigned int idx = (unsigned int)(poly->neis[j]-1); - neiRef = m_nav->getPolyRefBase(tile) | idx; - if (!filter->passFilter(neiRef, tile, &tile->polys[idx])) - neiRef = 0; - } - - // If the edge leads to another polygon and portals are not stored, skip. - if (neiRef != 0 && !storePortals) - continue; - - if (n < maxSegments) - { - const float* vj = &tile->verts[poly->verts[j]*3]; - const float* vi = &tile->verts[poly->verts[i]*3]; - float* seg = &segmentVerts[n*6]; - dtVcopy(seg+0, vj); - dtVcopy(seg+3, vi); - if (segmentRefs) - segmentRefs[n] = neiRef; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - continue; - } - - // Add sentinels - insertInterval(ints, nints, MAX_INTERVAL, -1, 0, 0); - insertInterval(ints, nints, MAX_INTERVAL, 255, 256, 0); - - // Store segments. - const float* vj = &tile->verts[poly->verts[j]*3]; - const float* vi = &tile->verts[poly->verts[i]*3]; - for (int k = 1; k < nints; ++k) - { - // Portal segment. - if (storePortals && ints[k].ref) - { - const float tmin = ints[k].tmin/255.0f; - const float tmax = ints[k].tmax/255.0f; - if (n < maxSegments) - { - float* seg = &segmentVerts[n*6]; - dtVlerp(seg+0, vj,vi, tmin); - dtVlerp(seg+3, vj,vi, tmax); - if (segmentRefs) - segmentRefs[n] = ints[k].ref; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - } - - // Wall segment. - const int imin = ints[k-1].tmax; - const int imax = ints[k].tmin; - if (imin != imax) - { - const float tmin = imin/255.0f; - const float tmax = imax/255.0f; - if (n < maxSegments) - { - float* seg = &segmentVerts[n*6]; - dtVlerp(seg+0, vj,vi, tmin); - dtVlerp(seg+3, vj,vi, tmax); - if (segmentRefs) - segmentRefs[n] = 0; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - } - } - } - - *segmentCount = n; - - return status; -} - -/// @par -/// -/// @p hitPos is not adjusted using the height detail data. -/// -/// @p hitDist will equal the search radius if there is no wall within the -/// radius. In this case the values of @p hitPos and @p hitNormal are -/// undefined. -/// -/// The normal will become unpredicable if @p hitDist is a very small number. -/// -dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, - const dtQueryFilter* filter, - float* hitDist, float* hitPos, float* hitNormal) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - float radiusSqr = dtSqr(maxRadius); - - dtStatus status = DT_SUCCESS; - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - // Hit test walls. - for (int i = 0, j = (int)bestPoly->vertCount-1; i < (int)bestPoly->vertCount; j = i++) - { - // Skip non-solid edges. - if (bestPoly->neis[j] & DT_EXT_LINK) - { - // Tile border. - bool solid = true; - for (unsigned int k = bestPoly->firstLink; k != DT_NULL_LINK; k = bestTile->links[k].next) - { - const dtLink* link = &bestTile->links[k]; - if (link->edge == j) - { - if (link->ref != 0) - { - const dtMeshTile* neiTile = 0; - const dtPoly* neiPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); - if (filter->passFilter(link->ref, neiTile, neiPoly)) - solid = false; - } - break; - } - } - if (!solid) continue; - } - else if (bestPoly->neis[j]) - { - // Internal edge - const unsigned int idx = (unsigned int)(bestPoly->neis[j]-1); - const dtPolyRef ref = m_nav->getPolyRefBase(bestTile) | idx; - if (filter->passFilter(ref, bestTile, &bestTile->polys[idx])) - continue; - } - - // Calc distance to the edge. - const float* vj = &bestTile->verts[bestPoly->verts[j]*3]; - const float* vi = &bestTile->verts[bestPoly->verts[i]*3]; - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, vj, vi, tseg); - - // Edge is too far, skip. - if (distSqr > radiusSqr) - continue; - - // Hit wall, update radius. - radiusSqr = distSqr; - // Calculate hit pos. - hitPos[0] = vj[0] + (vi[0] - vj[0])*tseg; - hitPos[1] = vj[1] + (vi[1] - vj[1])*tseg; - hitPos[2] = vj[2] + (vi[2] - vj[2])*tseg; - } - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour. - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Skip off-mesh connections. - if (neighbourPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Calc distance to the edge. - const float* va = &bestTile->verts[bestPoly->verts[link->edge]*3]; - const float* vb = &bestTile->verts[bestPoly->verts[(link->edge+1) % bestPoly->vertCount]*3]; - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - - // If the circle is not touching the next polygon, skip it. - if (distSqr > radiusSqr) - continue; - - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - { - getEdgeMidPoint(bestRef, bestPoly, bestTile, - neighbourRef, neighbourPoly, neighbourTile, neighbourNode->pos); - } - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - neighbourNode->flags |= DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - // Calc hit normal. - dtVsub(hitNormal, centerPos, hitPos); - dtVnormalize(hitNormal); - - *hitDist = sqrtf(radiusSqr); - - return status; -} - -bool dtNavMeshQuery::isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const -{ - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - dtStatus status = m_nav->getTileAndPolyByRef(ref, &tile, &poly); - // If cannot get polygon, assume it does not exists and boundary is invalid. - if (dtStatusFailed(status)) - return false; - // If cannot pass filter, assume flags has changed and boundary is invalid. - if (!filter->passFilter(ref, tile, poly)) - return false; - return true; -} - -/// @par -/// -/// The closed list is the list of polygons that were fully evaluated during -/// the last navigation graph search. (A* or Dijkstra) -/// -bool dtNavMeshQuery::isInClosedList(dtPolyRef ref) const -{ - if (!m_nodePool) return false; - const dtNode* node = m_nodePool->findNode(ref); - return node && node->flags & DT_NODE_CLOSED; -} diff --git a/critterai/.svn/pristine/37/3716ecacec1a803c2317c2580fb007f421c13f04.svn-base b/critterai/.svn/pristine/37/3716ecacec1a803c2317c2580fb007f421c13f04.svn-base deleted file mode 100644 index 5a3aa724..00000000 --- a/critterai/.svn/pristine/37/3716ecacec1a803c2317c2580fb007f421c13f04.svn-base +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.geom; -using org.critterai.nmgen.rcn; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Provides various constants and utility methods related to generating navigation mesh data. - /// - public static class NMGen - { - /// - /// The maximum allowed area. - /// - public const byte MaxArea = 63; - - /// - /// Represents an unwalkable area. - /// - /// - /// - /// When a data element is given this value it is considered to no longer be assigned to a - /// usable area. (It usually becomes an obstruction.) - /// - /// - /// This is also the minimum value that can be used as an area. - /// - /// - public const byte NullArea = 0; - - /// - /// Represents the null region. - /// - /// - /// - /// When a data element is given this value it is considered to have been removed - /// from the the data set. - /// - /// - /// Examples: When applied to a poygon, it indicates the polygon should be culled - /// from the final mesh. When applied to an edge, it means the edge is a solid wall. - /// - /// - public const byte NullRegion = 0; - - /// - /// The minimum allowed value for cells size parameters. - /// - public const float MinCellSize = 0.01f; - - /// - /// The maximum allowed value for parameters that define maximum vertices per polygon. - /// - public const int MaxAllowedVertsPerPoly = 6; - - /// - /// The minimum value for parameters that define walkable height. - /// - /// - /// Dependencies between parameters may limit the minimum value to a higher value. - /// - public const int MinWalkableHeight = 3; - - /// - /// The maximum allowed value for parameters that define slope. - /// - public const float MaxAllowedSlope = 85.0f; - - /// - /// Derives the width and depth of a tile grid based on the provided parameters. - /// - /// - /// - /// This method does not validate the parameters. - /// - /// - /// The minimum bounds. - /// The maximum bounds. - /// The cell size on the xz-plane. - /// () - /// The tile size. () - /// The number of tiles along the x-axis. - /// The number of tiles along the z-axis. - public static void DeriveSizeOfTileGrid(Vector3 boundsMin, Vector3 boundsMax - , float xzCellSize, int tileSize - , out int width, out int depth) - { - if (tileSize < 1) - { - width = 1; - depth = 1; - return; - } - - int cellGridWidth = (int)((boundsMax.x - boundsMin.x) / xzCellSize + 0.5f); - int cellGridDepth = (int)((boundsMax.z - boundsMin.z) / xzCellSize + 0.5f); - - width = (cellGridWidth + tileSize - 1) / tileSize; - depth = (cellGridDepth + tileSize - 1) / tileSize; - } - - - /// - /// Derive the width and depth of a cell grid based on the provided parameters. - /// - /// - /// - /// This method does not validate the parameters. - /// - /// - /// The minimum bounds. - /// The maximum bounds. - /// - /// The cell size on the xz-plane. () - /// - /// The number of cells along the x-axis. - /// The number of cells along the z-axis. - public static void DeriveSizeOfCellGrid(Vector3 boundsMin, Vector3 boundsMax - , float xzCellSize - , out int width, out int depth) - { - width = (int)((boundsMax.x - boundsMin.x) / xzCellSize + 0.5f); - depth = (int)((boundsMax.z - boundsMin.z) / xzCellSize + 0.5f); - } - - /// - /// Creates an area buffer with all values set to . - /// - /// The length of the buffer. - /// An buffer with all values set to . - public static byte[] CreateDefaultAreaBuffer(int size) - { - return CreateAreaBuffer(size, MaxArea); - } - - /// - /// Creates an area buffer with all values set to the the specified area. - /// - /// The length of the buffer. - /// The area to assign to the buffer. (Will be auto-clamped.) - /// A buffer with all values set to the specified area. - public static byte[] CreateAreaBuffer(int size, byte area) - { - byte[] result = new byte[size]; - area = ClampArea(area); - - for (int i = 0; i < size; i++) - { - result[i] = area; - } - - return result; - } - - /// - /// Validates the content of an area buffer. (All areas are valid.) - /// - /// - /// - /// The validation checks for an undersized buffer. It doesn't care about an oversized - /// buffer. - /// - /// - /// The area buffer. [Length: <= areaCount] - /// The number of areas defined in the buffer. - /// True if the structure and content of the buffer is valid. - public static bool IsValidAreaBuffer(byte[] areas, int areaCount) - { - if (areas.Length < areaCount) - return false; - - for (int i = 0; i < areaCount; i++) - { - if (areas[i] > MaxArea) - return false; - } - return true; - } - - /// - /// Set the area of all triangles with a slope below the specified value to - /// . - /// - /// The context to use duing the operation. - /// The source mesh. - /// The maximum walkable slope. - /// - /// The areas associated with each triangle. [Length: >= mesh.triCount] (In/Out) - /// - /// True if the operation was successful. - public static bool MarkWalkableTriangles(BuildContext context, TriangleMesh mesh - , float walkableSlope - , byte[] areas) - { - if (mesh == null - || context == null - || areas == null || areas.Length < mesh.triCount) - { - return false; - } - - NMGenEx.nmgMarkWalkableTriangles(context.root - , walkableSlope - , mesh.verts - , mesh.vertCount - , mesh.tris - , mesh.triCount - , areas); - - return true; - } - - /// - /// Set the area of all triangles with a slope above the specified value to - /// . - /// - /// The context to use duing the operation. - /// The source mesh. - /// The maximum walkable slope. - /// - /// The areas associated with each triangle. [Length: >= mesh.triCount] (In/Out) - /// - /// True if the operation was successful. - public static bool ClearUnwalkableTriangles(BuildContext context, TriangleMesh mesh - , float walkableSlope - , byte[] areas) - { - if (mesh == null - || context == null - || areas == null || areas.Length < mesh.triCount) - { - return false; - } - - NMGenEx.nmgClearUnwalkableTriangles(context.root - , walkableSlope - , mesh.verts - , mesh.vertCount - , mesh.tris - , mesh.triCount - , areas); - - return true; - } - - /// - /// Builds an aggregate triangle mesh from a detail mesh. - /// - /// - /// - /// All duplicate vertices are merged. - /// - /// - /// The detail mesh to extract the triangle mesh from. - /// The result vertices. - /// - /// The result triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount] - /// - /// True if the operation completed successfully. - public static bool ExtractTriMesh(PolyMeshDetail source - , out Vector3[] verts - , out int[] tris) - { - // TODO: EVAL: v0.5: Inefficient. - - verts = null; - tris = null; - if (source == null || source.IsDisposed || source.TriCount == 0) - return false; - - // Assume no duplicate verts. - Vector3[] tverts = new Vector3[source.VertCount]; - tris = new int[source.TriCount * 3]; - int vertCount = 0; - int triCount = 0; - - if (PolyMeshDetailEx.rcpdFlattenMesh(source - , tverts - , ref vertCount - , source.VertCount - , tris - , ref triCount - , source.TriCount)) - { - verts = new Vector3[vertCount]; - for (int i = 0; i < vertCount; i++) - { - verts[i] = tverts[i]; - } - return true; - } - - tris = null; - return false; - } - - /// - /// Clamps the value to the valid area range. (0 <= value <= ) - /// - /// The value to clamp. - /// A valid area. - public static byte ClampArea(byte value) - { - return Math.Min(MaxArea, value); - } - - /// - /// Clamps the value to the valid area range. (0 <= value <= ) - /// - /// The value to clamp. - /// A valid area. - public static byte ClampArea(int value) - { - return (byte)Math.Min(NMGen.MaxArea, Math.Max(0, value)); - } - } -} diff --git a/critterai/.svn/pristine/37/37cd03228bbf4f57267a382a66c91805226e75c8.svn-base b/critterai/.svn/pristine/37/37cd03228bbf4f57267a382a66c91805226e75c8.svn-base deleted file mode 100644 index bf9dcaac..00000000 --- a/critterai/.svn/pristine/37/37cd03228bbf4f57267a382a66c91805226e75c8.svn-base +++ /dev/null @@ -1,102 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {8823F2CF-1139-41BF-BD47-A456B7FEE336} - Library - Properties - org.critterai - cai-nmbuild-u3d-editor - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - ..\bin\Release\cai-nmbuild-u3d-editor.XML - - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEditor.dll - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - input\fakename.cs - - - controls\fakename.cs - - - views\fakename.cs - - - Properties\AssemblyInfo.cs - - - - - {8093F287-EA45-46ab-AF58-710DA654392E} - cai-nav-u3d-editor - - - {D2154397-4098-4170-BBB0-58714D84E4C8} - cai-nav-u3d - - - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336} - cai-nmbuild - - - {9DFC1FE0-6469-4a04-AB13-9EAC59087802} - cai-nmgen - - - {1FF01BFD-2593-406A-959E-D4D84CEB662C} - cai-util-u3d-editor - - - {AF812AB8-633B-4e23-ABA7-6D02082FB2EE} - cai-util-u3d - - - {42218E47-156D-46ff-84E0-119D47B0E4EB} - cai-nav - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/38/38360706a3193abc16ffe8b5fcad9e4f1b4eb8b6.svn-base b/critterai/.svn/pristine/38/38360706a3193abc16ffe8b5fcad9e4f1b4eb8b6.svn-base deleted file mode 100644 index 6d38ee73..00000000 --- a/critterai/.svn/pristine/38/38360706a3193abc16ffe8b5fcad9e4f1b4eb8b6.svn-base +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav.rcn -{ - internal static class PathCorridorEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtpcAlloc(int maxPath); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtpcFree(IntPtr corridor); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtpcReset(IntPtr corridor - , NavmeshPoint position); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcFindCorners(IntPtr corridor - , [In, Out] Vector3[] cornerVerts - , [In, Out] WaypointFlag[] cornerFlags - , [In, Out] uint[] cornerPolys - , int maxCorners - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtpcOptimizePathVisibility(IntPtr corridor - , [In] ref Vector3 next - , float pathOptimizationRange - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcOptimizePathVisibilityExt(IntPtr corridor - , [In] ref Vector3 next - , float pathOptimizationRange - , [In, Out] Vector3[] cornerVerts - , [In, Out] WaypointFlag[] cornerFlags - , [In, Out] uint[] cornerPolys - , int maxCorners - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtpcOptimizePathTopology(IntPtr corridor - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcOptimizePathTopologyExt(IntPtr corridor - , [In, Out] Vector3[] cornerVerts - , [In, Out] WaypointFlag[] cornerFlags - , [In, Out] uint[] cornerPolys - , int maxCorners - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtpcMoveOverOffmeshConnection(IntPtr corridor - , uint offMeshConRef - , [In, Out] uint[] refs // size 2 - , ref Vector3 startPos - , ref Vector3 endPos - , ref NavmeshPoint resultPos - , IntPtr navquery); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcMovePosition(IntPtr corridor - , [In] ref Vector3 npos - , ref NavmeshPoint pos - , [In, Out] Vector3[] cornerVerts - , [In, Out] WaypointFlag[] cornerFlags - , [In, Out] uint[] cornerPolys - , int maxCorners - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcMoveTargetPosition(IntPtr corridor - , [In] ref Vector3 npos - , ref NavmeshPoint pos - , [In, Out] Vector3[] cornerVerts - , [In, Out] WaypointFlag[] cornerFlags - , [In, Out] uint[] cornerPolys - , int maxCorners - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcMove(IntPtr corridor - , [In] ref Vector3 npos - , [In] ref Vector3 ntarget - , ref NavmeshPoint pos - , ref NavmeshPoint target - , [In, Out] Vector3[] cornerVerts - , [In, Out] WaypointFlag[] cornerFlags - , [In, Out] uint[] cornerPolys - , int maxCorners - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcSetCorridor(IntPtr corridor - , [In] ref Vector3 target - , [In] uint[] path - , int pathCount - , ref NavmeshPoint resultTarget - , [In, Out] Vector3[] cornerVerts - , [In, Out] WaypointFlag[] cornerFlags - , [In, Out] uint[] cornerPolys - , int maxCorners - , IntPtr navquery - , IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcGetPath(IntPtr corridor - , [In, Out] uint[] path - , int maxPath); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpcGetPathCount(IntPtr corridor); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtpcGetData(IntPtr corridor - , [In, Out] PathCorridorData data); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtpcIsValid(IntPtr corridor - , int maxLookAhead - , IntPtr navquery - , IntPtr filter); - } -} diff --git a/critterai/.svn/pristine/38/38493a43f521d4dbee8c3df80e72e0428b3150ab.svn-base b/critterai/.svn/pristine/38/38493a43f521d4dbee8c3df80e72e0428b3150ab.svn-base deleted file mode 100644 index 2aca0d9a..00000000 --- a/critterai/.svn/pristine/38/38493a43f521d4dbee8c3df80e72e0428b3150ab.svn-base +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef RECASTASSERT_H -#define RECASTASSERT_H - -// Note: This header file's only purpose is to include define assert. -// Feel free to change the file and include your own implementation instead. - -#ifdef NDEBUG -// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ -# define rcAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false) -#else -# include -# define rcAssert assert -#endif - -#endif // RECASTASSERT_H diff --git a/critterai/.svn/pristine/38/385bc9fdcd9df93092828c4ff4271ef9641c72cd.svn-base b/critterai/.svn/pristine/38/385bc9fdcd9df93092828c4ff4271ef9641c72cd.svn-base deleted file mode 100644 index c3a9bca5..00000000 --- a/critterai/.svn/pristine/38/385bc9fdcd9df93092828c4ff4271ef9641c72cd.svn-base +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "DetourNavMeshBuilder.h" -#include "DetourCommon.h" -#include "DetourNavMeshEx.h" - -const long RCN_NAVMESH_VERSION = 1; - -struct rcnNavMeshCreateParams - : dtNavMeshCreateParams -{ - // Design note: This exists for marshalling - // purposes only. Associated with the TileBuildData class - // on the other side of the interop boundary. - bool isDisposed; - int maxPolyVerts; - int maxPolys; - int maxDetailVerts; - int maxDetailTris; - int maxConns; -}; - -struct rcnNavMeshSetHeader -{ - long version; - int tileCount; - dtNavMeshParams params; -}; - -struct rcnNavMeshTileHeader -{ - dtTileRef tileRef; - int dataSize; -}; - -extern "C" -{ - - EXPORT_API bool dtnmBuildTileData(rcnNavMeshCreateParams* params - , rcnTileData* resultData) - { - if (!params - || !resultData - || resultData->data) // Already has data in it. Not allowed. - { - return false; - } - resultData->isOwned = false; - return dtCreateNavMeshData((rcnNavMeshCreateParams*)params - , &resultData->data - , &resultData->dataSize); - } - - EXPORT_API bool dtnmBuildTileDataRaw(unsigned char* data - , int dataSize - , rcnTileData* resultData) - { - if (!data - || !resultData - || resultData->data) // Already has data in it. Not allowed. - { - return false; - } - - resultData->data = (unsigned char*)dtAlloc( - sizeof(unsigned char)*dataSize, DT_ALLOC_PERM); - - if (!resultData->data) - return false; - - memcpy(resultData->data, data, dataSize); - resultData->dataSize = dataSize; - resultData->isOwned = false; - - return true; - } - - EXPORT_API void dtnmFreeTileData(rcnTileData* tileData) - { - if (!tileData || !tileData->data || tileData->isOwned) - return; - - dtFree(tileData->data); - tileData->data = 0; - tileData->dataSize = 0; - } - - EXPORT_API dtStatus dtnmGetTileDataHeader(const unsigned char* data - , const int dataSize - , dtMeshHeader* resultHeader) - { - if (!data || !dataSize || !resultHeader) - return DT_FAILURE | DT_INVALID_PARAM; - - dtMeshHeader* header = (dtMeshHeader*)data; - - if (header->magic != DT_NAVMESH_MAGIC) - return DT_FAILURE | DT_WRONG_MAGIC; - if (header->version != DT_NAVMESH_VERSION) - return DT_FAILURE | DT_WRONG_VERSION; - - memcpy(resultHeader, header, sizeof(dtMeshHeader)); - - return DT_SUCCESS; - } - - - EXPORT_API dtStatus dtnmGetTileDataHeaderAlt(const unsigned char* data - , const int dataSize - , dtMeshHeader* resultHeader) - { - // The reason for this alternate method is Unity iOS capatibility. - // One signature supports an IntPtr, the other a byte[] array. - return dtnmGetTileDataHeader(data, dataSize, resultHeader); - } - - EXPORT_API void dtnmGetNavMeshRawData(const dtNavMesh* navMesh - , unsigned char** resultData - , int* dataSize) - { - if (!navMesh || !resultData || !dataSize) - { - *resultData = 0; - *dataSize = 0; - return; - } - - rcnNavMeshSetHeader header; - header.version = RCN_NAVMESH_VERSION; - header.tileCount = 0; - - for (int i = 0; i < navMesh->getMaxTiles(); ++i) - { - const dtMeshTile* tile = navMesh->getTile(i); - if (!tile || !tile->header || !tile->dataSize) continue; - header.tileCount++; - } - memcpy(&header.params, navMesh->getParams(), sizeof(dtNavMeshParams)); - - int totalDataSize = 0; - rcnNavMeshTileHeader* tileHeaders = - new rcnNavMeshTileHeader[header.tileCount]; - - for (int i = 0; i < navMesh->getMaxTiles(); ++i) - { - const dtMeshTile* tile = navMesh->getTile(i); - if (!tile || !tile->header || !tile->dataSize) continue; - - tileHeaders[i].tileRef = navMesh->getTileRef(tile); - tileHeaders[i].dataSize = tile->dataSize; - totalDataSize += tile->dataSize; - } - - totalDataSize += sizeof(rcnNavMeshSetHeader); - totalDataSize += sizeof(rcnNavMeshTileHeader) * header.tileCount; - - unsigned char* data = - (unsigned char*)dtAlloc(totalDataSize, DT_ALLOC_PERM); - - int pos = 0; - int size = sizeof(rcnNavMeshSetHeader); - memcpy(&data[pos], &header, size); - pos += size; - - for (int i = 0; i < header.tileCount; ++i) - { - size = sizeof(rcnNavMeshTileHeader); - memcpy(&data[pos], &tileHeaders[i], size); - pos += size; - - size = tileHeaders[i].dataSize; - const dtMeshTile* tile = - navMesh->getTileByRef(tileHeaders[i].tileRef); - memcpy(&data[pos], tile->data, size); - pos += size; - } - - delete tileHeaders; - tileHeaders = 0; - - *resultData = data; - *dataSize = totalDataSize; - } - - EXPORT_API void dtnmFreeBytes(unsigned char** data) - { - dtFree(*data); - *data = 0; - } - - EXPORT_API dtStatus dtnmBuildDTNavMeshFromRaw(const unsigned char* data - , int dataSize - , bool safeStorage - , dtNavMesh** ppNavMesh) - { - if (!data || dataSize < sizeof(rcnNavMeshSetHeader) || !ppNavMesh) - return DT_FAILURE + DT_INVALID_PARAM; - - int pos = 0; - int size = sizeof(rcnNavMeshSetHeader); - - rcnNavMeshSetHeader header; - memcpy(&header, data, size); - pos += size; - - if (header.version != RCN_NAVMESH_VERSION) - { - *ppNavMesh = 0; - return DT_FAILURE + DT_WRONG_VERSION; - } - - dtNavMesh* mesh = dtAllocNavMesh(); - if (!mesh) - { - *ppNavMesh = 0; - return DT_FAILURE + DT_OUT_OF_MEMORY; - } - - dtStatus status = mesh->init(&header.params); - if (dtStatusFailed(status)) - { - *ppNavMesh = 0; - return status; - } - - // Read tiles. - bool success = true; - for (int i = 0; i < header.tileCount; ++i) - { - rcnNavMeshTileHeader tileHeader; - size = sizeof(rcnNavMeshTileHeader); - memcpy(&tileHeader, &data[pos], size); - pos += size; - - size = tileHeader.dataSize; - if (!tileHeader.tileRef || !tileHeader.dataSize) - { - success = false; - status = DT_FAILURE + DT_INVALID_PARAM; - break; - } - - unsigned char* tileData = - (unsigned char*)dtAlloc(size, DT_ALLOC_PERM); - if (!tileData) - { - success = false; - status = DT_FAILURE + DT_OUT_OF_MEMORY; - break; - } - memcpy(tileData, &data[pos], size); - pos += size; - - status = mesh->addTile(tileData - , size - , (safeStorage ? DT_TILE_FREE_DATA : 0) - , tileHeader.tileRef - , 0); - - if (dtStatusFailed(status)) - { - success = false; - break; - } - } - - if (!success) - { - dtFreeNavMesh(mesh); - *ppNavMesh = 0; - return status; - } - - *ppNavMesh = mesh; - - return DT_SUCCESS; - } - - EXPORT_API dtStatus dtnmInitTiledNavMesh(dtNavMeshParams* params - , dtNavMesh** ppNavMesh) - { - if (!params) - return DT_FAILURE + DT_INVALID_PARAM; - - dtNavMesh* pNavMesh = dtAllocNavMesh(); - if (!pNavMesh) - return DT_FAILURE + DT_OUT_OF_MEMORY; - - dtStatus status = - pNavMesh->init(params); - if (dtStatusFailed(status)) - { - dtFreeNavMesh(pNavMesh); - return status; - } - - *ppNavMesh = pNavMesh; - - return DT_SUCCESS; - } - - EXPORT_API dtStatus dtnmBuildSingleTileMesh(dtNavMeshCreateParams* params - , dtNavMesh** ppNavMesh) - { - if (!params) - return DT_FAILURE + DT_INVALID_PARAM; - - unsigned char* navData = 0; - int navDataSize = 0; - - if (!dtCreateNavMeshData(params, &navData, &navDataSize)) - return DT_FAILURE + DT_INVALID_PARAM; - - dtNavMesh* pNavMesh = dtAllocNavMesh(); - if (!pNavMesh) - { - dtFree(navData); - return DT_FAILURE + DT_OUT_OF_MEMORY; - } - - dtStatus status = - pNavMesh->init(navData, navDataSize, DT_TILE_FREE_DATA); - if (dtStatusFailed(status)) - { - dtFreeNavMesh(pNavMesh); - dtFree(navData); - return status; - } - - *ppNavMesh = pNavMesh; - - return DT_SUCCESS; - - } - - EXPORT_API void dtnmFreeNavMesh(dtNavMesh** pNavMesh, bool freeTiles) - { - if (!pNavMesh && !(*pNavMesh)) - return; - - dtNavMesh* mesh = *pNavMesh; - const dtNavMesh* cmesh = *pNavMesh; // Cleaner code when calling getTile(). - - if (freeTiles) - { - unsigned char* tData = 0; - - for (int i = 0; i < mesh->getMaxTiles(); ++i) - { - const dtMeshTile* tile = cmesh->getTile(i); - - if (!tile || !tile->header || !tile->dataSize) - continue; - - dtTileRef tref = mesh->getTileRef(tile); - - dtStatus status = mesh->removeTile(tref, &tData, 0); - - if (dtStatusSucceed(status) && tData) - { - dtFree(tData); - tData = 0; - } - } - } - - dtFreeNavMesh(mesh); - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/38/3875220a489ca44e35025e5b7cb787f088f6fa11.svn-base b/critterai/.svn/pristine/38/3875220a489ca44e35025e5b7cb787f088f6fa11.svn-base deleted file mode 100644 index cf806680..00000000 Binary files a/critterai/.svn/pristine/38/3875220a489ca44e35025e5b7cb787f088f6fa11.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/38/38b741a85beb5bfc69ad030d3a8f6ff39b8b164c.svn-base b/critterai/.svn/pristine/38/38b741a85beb5bfc69ad030d3a8f6ff39b8b164c.svn-base deleted file mode 100644 index f46fe717..00000000 Binary files a/critterai/.svn/pristine/38/38b741a85beb5bfc69ad030d3a8f6ff39b8b164c.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/39/394ec0f588cef783ebc855d67178b50ca16b7885.svn-base b/critterai/.svn/pristine/39/394ec0f588cef783ebc855d67178b50ca16b7885.svn-base deleted file mode 100644 index 351f8327..00000000 --- a/critterai/.svn/pristine/39/394ec0f588cef783ebc855d67178b50ca16b7885.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-util")] -[assembly: AssemblyDescription("Shared utilities for CAI products.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAI")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2010-2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.5.0.0")] -[assembly: AssemblyFileVersion("0.5.0.0")] diff --git a/critterai/.svn/pristine/39/39584816653ffaa63e1e8f9ab7b9bc5df09acaae.svn-base b/critterai/.svn/pristine/39/39584816653ffaa63e1e8f9ab7b9bc5df09acaae.svn-base deleted file mode 100644 index 6c1db82f..00000000 --- a/critterai/.svn/pristine/39/39584816653ffaa63e1e8f9ab7b9bc5df09acaae.svn-base +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.u3d.editor; -using UnityEditor; - -/// -/// Base editor for objects. -/// -/// -public class NMGenComponentEditor - : Editor -{ - /// - /// Run when the editor is disabled. (Goes out of scope.) - /// - protected virtual void OnDisable() - { - if (target) - ((NMGenComponent)target).debugEnabledLocal = false; - } - - /// - /// Toggles the debug visualizations for all objects. - /// - [MenuItem(EditorUtil.ViewMenu + "Toggle NMGen Extras", false, EditorUtil.ViewGroup)] - public static void ToggleDebugView() - { - NMGenComponent.debugEnabled = !NMGenComponent.debugEnabled; - SceneView.RepaintAll(); - } -} diff --git a/critterai/.svn/pristine/39/3971c22315dbbbd40f724ab441b8cb86888a5e34.svn-base b/critterai/.svn/pristine/39/3971c22315dbbbd40f724ab441b8cb86888a5e34.svn-base deleted file mode 100644 index 31186206..00000000 --- a/critterai/.svn/pristine/39/3971c22315dbbbd40f724ab441b8cb86888a5e34.svn-base +++ /dev/null @@ -1,989 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; -import java.util.logging.Logger; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Builds a set of contours from the region information contained by an - * {@link OpenHeightfield}. It does this by locating and "walking" the edges - *

- *

- * @see Contour Generation - * @see Contour - * @see ContourSet - */ -public final class ContourSetBuilder -{ - - /* - * Design notes: - * - * Not adding configuration getters until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - * - * Recast Reference: rcBuildContours() in RecastContour.cpp - */ - - private static final Logger logger = - Logger.getLogger(ContourSetBuilder.class.getName()); - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * The post-processing algorithms to apply to the contours. - */ - private final ArrayList mAlgorithms = - new ArrayList(); - - /** - * Contructor - * @param algorithms The post-processing algorithms to apply to - * the contours. - */ - public ContourSetBuilder(ArrayList algorithms) - { - if (algorithms == null) - return; - this.mAlgorithms.addAll(algorithms); - } - - /** - * Generates a contour set from the provided {@link OpenHeightfield} - *

The provided field is expected to contain region information. - * Behavior is undefined if the provided field is malformed or incomplete. - *

- *

This operation overwrites the flag fields for all spans in the - * provided field. So the flags must be saved and restored if they are - * important.

- * @param sourceField A fully generated field. - * @return The contours generated from the field. - */ - public ContourSet build(OpenHeightfield sourceField) - { - if (sourceField == null || sourceField.regionCount() == 0) - return null; - - // Initialize the contour set. - final ContourSet result = new ContourSet(sourceField.boundsMin() - , sourceField.boundsMax() - , sourceField.cellSize() - , sourceField.cellHeight() - , sourceField.regionCount()); - - int discardedContours = 0; - - /* - * Set the flags on all spans in non-null regions to indicate which - * edges are connected to external regions. - * - * Reference: Neighbor search and nomenclature. - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - * - * If a span has no connections to external regions or is - * completely surrounded by other regions (a single span island), - * its flag will be zero. - * - * If a span is connected to one or more external regions then the - * flag will be a 4 bit value where connections are recorded as - * follows: - * bit1 = neighbor0 - * bit2 = neighbor1 - * bit3 = neighbor2 - * bit4 = neighbor3 - * With the meaning of the bits as follows: - * 0 = neighbor in same region. - * 1 = neighbor not in same region. (Neighbor may be the null - * region or a real region.) - */ - final OpenHeightFieldIterator iter = - sourceField.dataIterator(); - while(iter.hasNext()) - { - // Note: This algorithm first sets the flag bits such that - // 1 = "neighbor is in the same region". At the end it inverts - // the bits so flags are as expected. - final OpenHeightSpan span = iter.next(); - // Default to "not connected to any external region". - span.flags = 0; - if (span.regionID() == NULL_REGION) - // Don't care about spans in the null region. - continue; - // Loop through all directions. - for (int dir = 0; dir < 4; dir++) - { - // Default to show neighbor is in null region. - int nRegionID = NULL_REGION; - final OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null) - // There is a neighbor in the current direction. - // Get its region ID. - nRegionID = nSpan.regionID(); - if (span.regionID() == nRegionID) - // Neighbor is in same region as this span. Set the bit - // for this neighbor to 1. (Will be inverted later.) - span.flags |= (1 << dir); - } - // Invert the bits so a bit value of 1 indicates neighbor NOT in - // same region. - span.flags ^= 0xf; - if (span.flags == 0xf) - { - // This is an island span. (All neighbors are other regions.) - // Get rid of flags. - span.flags = 0; - discardedContours++; - logger.warning("Discarded contour: Island span. Can't form " + - "a contour. Region: " + span.regionID()); - } - } - - /* - * These are working lists whose content changes with each iteration - * of the up coming loop. They represent the detailed and simple - * contour vertices. - * Initial sizing is arbitrary. - */ - final ArrayList workingRawVerts = new ArrayList(256); - final ArrayList workingSimplifiedVerts = - new ArrayList(64); - - /* - * Loop through all spans looking for spans on the edge of a region. - * - * At this point, only spans with flags != 0 are edge spans that - * are part of a region contour. - * - * The process of building a contour will clear the flags on all spans - * that make up the contour. This ensures that the spans that make - * up a contour are only processed once. - */ - iter.reset(); - while(iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - if (span.regionID() == NULL_REGION || span.flags == 0) - // Span is either: Part of the null region, does not - // represent an edge span, or was already processed during - // an earlier iteration. - continue; - workingRawVerts.clear(); - workingSimplifiedVerts.clear(); - // The span is part of an unprocessed region's contour. - // Locate a direction of the span's edge which points toward - // another region. (We know there is at least one.) - int startDir = 0; - while ((span.flags & (1 << startDir)) == 0) - // This is not an edge direction. Try the next one. - startDir++; - // We now have a span that is part of a contour and a direction - // that points to a different region (null or real). - // Build the contour. - buildRawContours(span - , iter.widthIndex() - , iter.depthIndex() - , startDir - , workingRawVerts); - // Perform post processing on the contour in order to - // create the final, simplified contour. - generateSimplifiedContour(span.regionID() - , workingRawVerts - , workingSimplifiedVerts); - /* - * This next test is needed because some extreme cases contours - * just can't be successfully generated. - * We can't just copy the raw contour to the simplified contour - * because the reason the build failed may be because it - * can't be triangulated. (E.g. Has too many vertical segments.) - */ - if (workingSimplifiedVerts.size() < 12) - { - logger.warning("Discarded contour: Can't form enough valid" + - "edges from the vertices." + - " Region: " + span.regionID()); - discardedContours++; - } - else - { - result.add(new Contour(span.regionID() - , workingRawVerts - , workingSimplifiedVerts)); - } - - } - - if (discardedContours > 0) - { - logger.warning("Contours not generated for " + discardedContours - + " regions."); - } - - if (result.size() + discardedContours != - sourceField.regionCount() - 1) - { - /* - * The only valid state is one contour per region. - * - * The only time this should occur is if an invalid contour - * was formed or if a region resulted in multiple - * contours (bad region data). - * - * IMPORTANT: While a mismatch may not be a fatal error, - * it should be addressed since it can result in odd, - * hard to spot anomalies later in the pipeline. - * - * A known cause is if a region fully encompasses another - * region. In such a case, two contours will be formed. - * The normal outer contour and an inner contour. - * The CleanNullRegionBorders algorithm protects - * against internal encompassed null regions. - */ - - // Detect and report anomalies. - // Not reporting missing contours since those are sometimes - // expected and already reported. - - for (int regionID = 1 - ; regionID < sourceField.regionCount() - ; regionID++) - { - int regionMatches = 0; - for (int iContour = 0; iContour < result.size(); iContour++) - { - if (result.get(iContour).regionID == regionID) - regionMatches++; - } - if (regionMatches > 1) - { - logger.severe("More than one contour generated for a" + - "region: Region: " + regionID + ", Contours:" + - regionMatches); - } - } - - for (int iContour = 0; iContour < result.size(); iContour++) - { - Contour contour = result.get(iContour); - if (contour.regionID <= 0) - { - // Indicates a problem with this class. - logger.severe("A contour was generated for the null" - + "region."); - } - else if (contour.regionID >= sourceField.regionCount()) - { - // Indicates a problem with region generation. - logger.severe("A contour was generated for a region" - + " not in the source field's range: " - + contour.regionID); - } - } - - logger.severe("Contour generation failed: Detected contours does" - + " not match the number of regions. Regions: " - + (sourceField.regionCount() - 1) - + ", Detected contours: " - + (result.size() + discardedContours) - + " (Actual: " + result.size() - + ", Discarded: " + discardedContours + ")"); - return null; - } - - return result; - - } - - /** - * Walk around the edge of this span's region gathering vertices that - * represent the corners of each span on the sides that are external facing. - *

There will be two or three vertices for each edge span: - * Two for spans that don't represent a change in edge direction. Three - * for spans that represent a change in edge direction.

- *

The output array will contain vertices ordered as follows: - * (x, y, z, regionID) where regionID is the region (null or real) that - * this vertex is considered to be connected to.

- *

WARNING: Only run this operation on spans that are already known - * to be on a region edge. The direction must also be pointing to a - * valid edge. Otherwise behavior will be undefined.

- * @param startSpan A span that is known to be on the edge of a region. - * (Part of a region contour.) - * @param startWidthIndex The width index of the starting span. - * @param startDepthIndex The depth index of the starting span. - * @param startDirection The direction of the edge of the span that is - * known to point - * across the region edge. - * @param outContourVerts The list of vertices that represent the edge - * of the region. (Plus region information.) - */ - private void buildRawContours(OpenHeightSpan startSpan - , int startWidthIndex - , int startDepthIndex - , int startDirection - , ArrayList outContourVerts) - { - - /* - * Flaw in Algorithm: - * - * This method of contour generation can result in an inappropriate - * impassable seam between two adjacent regions in the following case: - * - * 1. One region connects to another region on two sides in an - * uninterrupted manner. (Visualize one region wrapping in an L - * shape around the corner of another.) - * 2. At the corner shared by the two regions, a change in height - * occurs. - * - * In this case, the two regions should share a corner vertex. - * (An obtuse corner vertex for one region and an acute corner - * vertex for the other region.) - * - * In reality, though this algorithm will select the same (x, z) - * coordinates for each region's corner vertex, the vertex heights - * may differ, eventually resulting in an impassable seam. - * - */ - - /* - * It is a bit hard to describe the stepping portion of this algorithm. - * One way to visualize it is to think of a robot sitting on the - * floor facing a known wall. It then does the following to skirt - * the wall: - * 1. If there is a wall in front of it, turn clockwise in 90 degrees - * increments until it finds the wall is gone. - * 2. Move forward one step. - * 3. Turn counter-clockwise by 90 degrees. - * 4. Repeat from step 1 until it finds itself at its original - * location facing its original direction. - * - * See also: http://www.critterai.org/nmgen_contourgen#robotwalk - */ - - // Initialize to current span pointing to the edge. - OpenHeightSpan span = startSpan; - int dir = startDirection; - int spanX = startWidthIndex; - int spanZ = startDepthIndex; - - int loopCount = 0; - /* - * The loop limit is arbitrary. It exists only to guarantee that - * bad input data doesn't result in an infinite loop. - * The only down side of this loop limit is that it limits the - * number of detectable edge vertices. (The longer the region edge - * and the higher the number of "turns" in a region's edge, the less - * edge vertices can be detected for that region.) - */ - while (++loopCount < 65535) - { - - // Note: The design of this loop is such that the span variable - // will always reference an edge span from the same region as - // the start span. - - if ((span.flags & (1 << dir)) != 0) - { - - // The current direction is pointing toward an edge. - // Get this edge's vertex. - int px = spanX; - final int py = getCornerHeight(span, dir); - int pz = spanZ; - /* - * Update the px and pz values based on current direction. - * The update is such that the corner being represented is - * clockwise from the edge the direction is currently pointing - * toward. - */ - switch(dir) - { - case 0: pz++; break; - case 1: px++; pz++; break; - case 2: px++; break; - } - // Default in case no neighbor. - int regionThisDirection = NULL_REGION; - final OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null) - // There is a neighbor in this direction. - // Get its region ID. - regionThisDirection = nSpan.regionID(); - // Add the vertex to the contour. - outContourVerts.add(px); - outContourVerts.add(py); - outContourVerts.add(pz); - outContourVerts.add(regionThisDirection); - - // Remove the flag for this edge. We never need to consider - // it again since we have a vertex for this edge. - span.flags &= ~(1 << dir); - dir = (dir+1) & 0x3; // Rotate in clockwise direction. - } - else - { - /* - * The current direction does not point to an edge. So it - * must point to a neighbor span in the same region as the - * current span. Move to the neighbor and swing the search - * direction back one increment (counterclockwise). - * By moving the direction back one increment we guarantee we - * don't miss any edges. - */ - span = span.getNeighbor(dir); - // Update the span index based on the direction traveled to - // get to this neighbor. - switch(dir) - { - case 0: spanX--; break; - case 1: spanZ++; break; - case 2: spanX++; break; - case 3: spanZ--; break; - } - dir = (dir+3) & 0x3; // Rotate counterclockwise. - } - - if (span == startSpan && dir == startDirection) - // We have returned to the starting point. Time to stop the - // walk. The contour is complete. - break; - - } - - } - - /** - * Takes a group of vertices that represent a region contour and changes - * it in the following manner: - *
    - *
  • For any edges that connect to non-null regions, remove all - * vertices except the start and end vertices for that edge. (This - * smoothes the edges between non-null regions into a straight line.)
  • - *
  • Runs all algorithm's in {@link #mAlgorithms} against the contour.
  • - *
- * @param regionID The region the contour was derived from. - * @param sourceVerts The source vertices that represent the complex - * contour in the form (x, y, z, regionID) - * @param outVerts The simplified contour vertices in the form: - * (x, y, z, regionID) - */ - private void generateSimplifiedContour(int regionID - , ArrayList sourceVerts - , ArrayList outVerts) - { - /* - * NOTE: In the output list, the forth field in each vertex contains - * the index of its corresponding source vertex. Only at the very end - * is the region information copied from the source to the output list. - */ - - boolean noConnections = true; - // Determine if this contour has any connections to non-null regions. - for (int pVert = 0; pVert < sourceVerts.size(); pVert += 4) - { - if (sourceVerts.get(pVert+3) != NULL_REGION) - { - // Found a non-null region connection. - noConnections = false; - break; - } - } - - // Seed the simplified contour with the mandatory edges. - // (At least one edge.) - if (noConnections) - { - /* - * This contour represents an island region surrounded only by the - * null region. Seed the simplified contour with the source's - * lower left (ll) and upper right (ur) vertices. - */ - int llx = sourceVerts.get(0); - int lly = sourceVerts.get(1); - int llz = sourceVerts.get(2); - int lli = 0; // Will be index of source vertex, not region. - int urx = sourceVerts.get(0); - int ury = sourceVerts.get(1); - int urz = sourceVerts.get(2); - int uri = 0; // Will be index of source vertex, not region. - // Loop through the source contour vertices and find the ur and - // ll vertices. - for (int pVert = 0; pVert < sourceVerts.size(); pVert += 4) - { - int x = sourceVerts.get(pVert); - int y = sourceVerts.get(pVert+1); - int z = sourceVerts.get(pVert+2); - if (x < llx || (x == llx && z < llz)) - { - // This the new lower left vertex. - llx = x; - lly = y; - llz = z; - lli = pVert / 4; - } - if (x >= urx || (x == urx && z > urz)) - { - // This is the new upper right vertex. - urx = x; - ury = y; - urz = z; - uri = pVert / 4; - } - } - // Seed the simplified contour with this edge. - outVerts.add(llx); - outVerts.add(lly); - outVerts.add(llz); - outVerts.add(lli); - - outVerts.add(urx); - outVerts.add(ury); - outVerts.add(urz); - outVerts.add(uri); - } - else - { - /* - * The contour shares edges with other non-null regions. - * Seed the simplified contour with a new vertex for every - * location where the region connection changes. These are - * vertices that are important because they represent portals - * to other regions. - */ - for (int iVert = 0, vCount = sourceVerts.size() / 4 - ; iVert < vCount - ; iVert++) - { - if (!sourceVerts.get(iVert*4+3) - .equals(sourceVerts.get(((iVert+1)%vCount)*4+3)) - ) - { - // The current vertex has a different region than the - // next vertex. So there is a change in vertex region. - outVerts.add(sourceVerts.get(iVert*4)); - outVerts.add(sourceVerts.get(iVert*4+1)); - outVerts.add(sourceVerts.get(iVert*4+2)); - outVerts.add(iVert); - } - } - } - - /* - * There are two situations where the out vert list may contain - * only two vertices. (An invalid polygon.) - * 1. The region is fully encompassed by the null region. - * 2. The region is encompassed by exactly two regions. - * This must be kept in mind since at least one vertex must be added - * back at some point. - * - * Though a region encompassed by two regions is technically a - * candidate for merging into one of the other regions, this is - * not done. It is the responsibility of region building to - * decide on such things. - */ - - // Run all post processing algorithms. These will build the final - // simplified contour from the seeded edges. - for (IContourAlgorithm algorithm : mAlgorithms) - { - algorithm.apply(sourceVerts, outVerts); - } - - if (outVerts.size() < 12) - { - /* - * Less than 3 vertices. - * - * This can occur in only one known case: The contour started - * with only two seed vertices and none of the algorithms added - * a vertex. - * - * This case is not completely unexpected. At this time, - * the contour algorithms only add vertices back if a null region - * edge is involved. So if a region is only surrounded by two - * non-null regions, it can end up in this situation. - * - * Find the vertex farthest from the current line segment - * and add it back to the contour. - * - * Design notes: - * - * This shouldn't happen very often. So I'm not optimizing it. - */ - int sourceVertCount = sourceVerts.size() / 4; - int iSelected = -1; - float maxDistance = 0; - int ax = outVerts.get(0); - int az = outVerts.get(2); - int bx = outVerts.get(4); - int bz = outVerts.get(6); - for (int iVert = 0; iVert < sourceVertCount; iVert++) - { - float dist = Geometry.getPointSegmentDistanceSq( - sourceVerts.get(iVert*4+0), - sourceVerts.get(iVert*4+2), - ax, - az, - bx, - bz); - if (dist > maxDistance) - { - maxDistance = dist; - iSelected = iVert; - } - } - // As selected vertex such that the contour stays - // wrapped clockwise. - if (iSelected < outVerts.get(3)) - { - // Insert selected vertex before other vertices. - outVerts.add(bx); - outVerts.add(outVerts.get(5)); - outVerts.add(bz); - outVerts.add(outVerts.get(7)); - outVerts.set(4, ax); - outVerts.set(5, outVerts.get(1)); - outVerts.set(6, az); - outVerts.set(7, outVerts.get(3)); - outVerts.set(0, sourceVerts.get(iSelected*4+0)); - outVerts.set(1, sourceVerts.get(iSelected*4+1)); - outVerts.set(2, sourceVerts.get(iSelected*4+2)); - outVerts.set(3, sourceVerts.get(iSelected)); - } - else if (iSelected < outVerts.get(7)) - { - // Insert selected vertex between other vertices. - outVerts.add(bx); - outVerts.add(outVerts.get(5)); - outVerts.add(bz); - outVerts.add(outVerts.get(7)); - outVerts.set(4, sourceVerts.get(iSelected*4+0)); - outVerts.set(5, sourceVerts.get(iSelected*4+1)); - outVerts.set(6, sourceVerts.get(iSelected*4+2)); - outVerts.set(7, sourceVerts.get(iSelected)); - } - else - { - // Insert selected vertex at end. - outVerts.add(sourceVerts.get(iSelected*4+0)); - outVerts.add(sourceVerts.get(iSelected*4+1)); - outVerts.add(sourceVerts.get(iSelected*4+2)); - outVerts.add(sourceVerts.get(iSelected)); - } - } - - // Replace the index pointers in the output list with region IDs. - final int sourceVertCount = sourceVerts.size() / 4; - final int simplifiedVertCount = outVerts.size() / 4; - for (int iVert = 0; iVert < simplifiedVertCount; ++iVert) - { - // The connected region id is taken from the next source point. - final int sourceVertIndex = - (outVerts.get(iVert * 4 + 3) + 1) % sourceVertCount; - outVerts.set(iVert * 4 + 3 - , sourceVerts.get(sourceVertIndex * 4 + 3)); - } - - /* - * Remove segments that will cause problems for the triangulation. - * - * There is a possibility that this will drop the vertices back below - * three. If this happens, nothing we can do about it. The contour - * will be lost. - */ - removeVerticalSegments(regionID, outVerts); - removeIntersectingSegments(regionID, outVerts); - } - - /** - * Removes segments that intersect with region portal segments. - * This can occur along the height axis in certain region configurations - * when detail is added back to a simplified contour. - *

This is required to prevent triangluation failures later in - * the pipeline.

- * @param regionID The region the contour was derived from. - * @param verts Contour vertices in the following form: (x, y, z, regionID) - */ - static void removeIntersectingSegments(int regionID - , ArrayList verts) - { - - /* Dev Notes: - * - * This is meant to be a temporary fix since it might remove - * important details. A more appropriate fix will require redesigning - * contour building into multiple stages so that detail can be - * added to portals such that both sides of the portal get the same - * detail. - * - * I'm a little worried about side effects from unanticipated - * contour configurations. - */ - - int startSize = verts.size(); - int vCount = startSize / 4; - for (int iVert = 0 - ; iVert < vCount - ; iVert++) - { - int iVertNext = (iVert+1)%vCount; - if (verts.get(iVertNext*4+3) != NULL_REGION) - { - // Segment iVert->iVertNext is a non-null region edge. - // Check for intersections. - iVert += removeIntersectingSegments(iVert - , iVertNext - , verts); // Offset will always be negative. - vCount = verts.size() / 4; - } - } - if (startSize != verts.size()) - { - logger.warning("Contour detail lost: Found and removed null" - + " region segments which were intersecting a portal." - + " Region: " + regionID + ", Segments removed: " - + (startSize - verts.size()) / 4); - } - } - - /** - * Merges segments such that no vertical segments exist. - * A vertical segment is a segment comprised of end points with - * duplicate (x, z) coordinates. - *

This is required to prevent triangluation failures later in - * the pipeline.

- * @param regionID The region the contour was derived from. - * @param verts Contour vertices in the following form: (x, y, z, regionID) - */ - static void removeVerticalSegments(int regionID, ArrayList verts) - { - /* - * Design Notes: - * - * Access level is set to internal to permit direct testing. - */ - - /* - * Remove vertical segments. - * - * Design notes: - * - * Protecting triangulation is more important than keeping region - * portals intact. So this algorithm will remove - * seed vertices if necessary. - * - * A potential enhancement is to have the algorithm try to detect - * the best vertex to remove from the pair. - * - * Another potential consideration: If otherwise there is no priority, - * Remove the vertex with the lowest y-value. This fits the general - * rule that the navigation mesh should be above the source geometry. - */ - - // Loop through all vertices starting with the last vertex. - for (int pVert = 0 ; pVert < verts.size();) - { - int pNextVert = (pVert+4)%verts.size(); - if (verts.get(pVert).equals(verts.get(pNextVert)) && - verts.get(pVert+2).equals(verts.get(pNextVert+2))) - { - // This segment represents a vertical line. - verts.remove(pNextVert); - verts.remove(pNextVert); // +1 - verts.remove(pNextVert); // +2 - verts.remove(pNextVert); // +3 - logger.warning("Contour detail lost: Removed a vertical" - + " segment from contour. Region: " + regionID); - } - else - pVert += 4; - } - - } - - /** - * Finds the correct height to use for a particular span vertex. - * (The vertex to the the right (clockwise) of the specified direction.) - * @param span A span on a region edge. - * @param direction A direction that points to a neighbor in a different - * region. (I.e. Crosses the border to a new region.) - * @return The height (y-value) to use for the vertex for this edge. - */ - static private int getCornerHeight(OpenHeightSpan span, int direction) - { - - /* - * This algorithm, while it uses similar processes as Recast, - * has been significantly adjusted. - * - * Examples: - * - Only 3 vertices are surveyed instead of the 4 - * the recast uses. - * - This algorithm searches more thoroughly for the diagonal neighbor. - * - * Reference: Neighbor search and nomenclature. - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - * - * See also: http://www.critterai.org/nmgen_contourgen#yselection - */ - - // Default height to the current floor. - int maxFloor = span.floor(); - - // The diagonal neighbor span to this corner. - OpenHeightSpan dSpan = null; - - // Rotate clockwise from original direction. - int directionOffset = (direction + 1) & 0x3; - - // Check axis neighbor in current direction. - OpenHeightSpan nSpan = span.getNeighbor(direction); - if (nSpan != null) - { - // Select for maximum floor using this neighbor. - maxFloor = Math.max(maxFloor, nSpan.floor()); - // Get diagonal neighbor. (By looking clockwise from this - // neighbor.) - dSpan = nSpan.getNeighbor(directionOffset); - } - // Check original span's axis-neighbor in clockwise direction. - nSpan = span.getNeighbor(directionOffset); - if (nSpan != null) - { - // Select for maximum floor using this neighbor. - maxFloor = Math.max(maxFloor, nSpan.floor()); - if (dSpan == null) - // Haven't found the diagonal neighbor yet. - // Try to get it by looking counter-clockwise - // from this neighbor. - dSpan = nSpan.getNeighbor(direction); - } - - if (dSpan != null) - // The diagonal neighbor was found. - // Select for maximum floor using this neighbor. - maxFloor = Math.max(maxFloor, dSpan.floor()); - - return maxFloor; - } - - /** - * Removes any null region segments that intersect with the - * specified edge. - *

Concerning the return value:

- *

The start and end vertices are expected to be in the - * correct contour order. So the only time the start index will be - * greater than the end index in value is if the end index is zero.

- *

So the return value can be used to offset the the end index as - * well as the start index unless the end index is zero.

- * @param startVertIndex The index of the edge's start index. - * @param endVertIndex The index of the edge's end index. - * @param verts Contour vertices in the following format: - * (x, y, z, regionID) - * @return If vertices were removed in such a way as to - * change the location of the start vertex, then this - * is the offset to apply to the startIndex. The value will always - * be <= 0. - */ - private static int removeIntersectingSegments(int startVertIndex - , int endVertIndex - , ArrayList verts) - { - - if (verts.size() < 16) - // Must have at least four vertices to have an intersection. - // This check is mandatory. An infinite loop will occur if - // there are less than four. - return 0; - - int offset = 0; - int startX = verts.get(startVertIndex*4+0); - int startZ = verts.get(startVertIndex*4+2); - int endX = verts.get(endVertIndex*4+0); - int endZ = verts.get(endVertIndex*4+2); - - int vCount = verts.size() / 4; - // Start at the line segment after the segment being - // checked and loop to the beginning of the segment being - // checked. - for (int iVert = (endVertIndex+2)%vCount - , iVertMinus = (endVertIndex+1)%vCount - ; iVert != startVertIndex - ;) - { - /* - * Only remove a vertex if it meets both of the following: - * - Both edges it belongs to connect to the null region. - * (null region segment - vertex - null region segment) - * - Belongs to a segment that intersects the segment being - * tested against. - */ - if (verts.get(iVert*4+3) == NULL_REGION - && verts.get(((iVert+1)%vCount)*4+3) == NULL_REGION - && Geometry.segmentsIntersect(startX - , startZ - , endX - , endZ - , verts.get(iVertMinus*4+0) - , verts.get(iVertMinus*4+2) - , verts.get(iVert*4+0) - , verts.get(iVert*4+2))) - { - // Remove the null region segment. - verts.remove(iVert*4); - verts.remove(iVert*4); // +1 - verts.remove(iVert*4); // +2 - verts.remove(iVert*4); // +3 - if (iVert < startVertIndex || iVert < endVertIndex) - { - // The removed vertex was stored before the line - // segment being tested. So the removal resulted - // in the segment indices shifting. - startVertIndex--; - endVertIndex--; - offset--; - } - // Segment has changed. Need to check the new segment. - // Adjust the indices as needed. - if (iVert < iVertMinus) - iVertMinus--; - vCount = verts.size() / 4; - iVert = iVert%vCount; - } - else - { - // Move to the next segment. - iVertMinus = iVert; - iVert = (iVert+1)%vCount; - } - } - return offset; - } -} diff --git a/critterai/.svn/pristine/39/399e7aa35af08c58722ce9646389bb4385713e38.svn-base b/critterai/.svn/pristine/39/399e7aa35af08c58722ce9646389bb4385713e38.svn-base deleted file mode 100644 index 0e81eae1..00000000 --- a/critterai/.svn/pristine/39/399e7aa35af08c58722ce9646389bb4385713e38.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nav-u3d")] -[assembly: AssemblyDescription("Pathfinding and obstacle avoidance extensions for Unity.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2011-2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/39/39a7168ec6181ce580518105f1a47b3d6d551039.svn-base b/critterai/.svn/pristine/39/39a7168ec6181ce580518105f1a47b3d6d551039.svn-base deleted file mode 100644 index aa50bdab..00000000 --- a/critterai/.svn/pristine/39/39a7168ec6181ce580518105f1a47b3d6d551039.svn-base +++ /dev/null @@ -1,60 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {C4B32B85-13F0-42B8-AC89-770BEFEAF022} - Library - Properties - org.critterai - cai-util - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG;NUNITY - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE;NUNITY - prompt - 4 - ..\bin\Release\cai-util.XML - - - - - 3.5 - - - - - - geom\FakeName.cs - - - interop\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/3a/3a11607335423e16c1d2d77a20c0e27e7581d549.svn-base b/critterai/.svn/pristine/3a/3a11607335423e16c1d2d77a20c0e27e7581d549.svn-base deleted file mode 100644 index 467adeb8..00000000 --- a/critterai/.svn/pristine/3a/3a11607335423e16c1d2d77a20c0e27e7581d549.svn-base +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CAI_DETOUREX_H -#define CAI_DETOUREX_H - -#include "DetourNavMesh.h" - -#if _MSC_VER // TRUE for Microsoft compiler. -#define EXPORT_API __declspec(dllexport) // Required for VC++ -#else -#define EXPORT_API // Otherwise don't define. -#endif - -static const int MAX_RCN_PATH_CORRIDOR_SIZE = 256; - -struct rcnPathCorridorData -{ - float position[3]; - float target[3]; - - dtPolyRef path[MAX_RCN_PATH_CORRIDOR_SIZE]; - int pathCount; -}; - -struct rcnNavmeshPoint -{ - dtPolyRef polyRef; - float point[3]; -}; - -#endif diff --git a/critterai/.svn/pristine/3a/3a514bcb8f9db92e1dce9e208fdec6a8bec67a16.svn-base b/critterai/.svn/pristine/3a/3a514bcb8f9db92e1dce9e208fdec6a8bec67a16.svn-base deleted file mode 100644 index b02be38e..00000000 --- a/critterai/.svn/pristine/3a/3a514bcb8f9db92e1dce9e208fdec6a8bec67a16.svn-base +++ /dev/null @@ -1,212 +0,0 @@ -package org.critterai.nmgen; - -/** - * Provides shared computational geometry operations. - *

This is a temporary class. Its functionality will eventually - * be merged into classes in the utility library.

- */ -public final class Geometry -{ - - /* - * Design Notes: - * - * Until computational geometry functions are moved to the utilities - * library, they will slowly be migrated here as needed for easier - * unit testing. - * - */ - - // TODO: GENERALIZATION: Move these algorithms to the utility library. - - private Geometry() { } - - /** - * Returns the distance squared from the point to the line segment. - *

Behavior is undefined if the the closest distance is outside the - * line segment.

- * @param px The x-value of point (px, py). - * @param py The y-value of point (px, py) - * @param ax The x-value of the line segment's vertex A. - * @param ay The y-value of the line segment's vertex A. - * @param bx The x-value of the line segment's vertex B. - * @param by The y-value of the line segment's vertex B. - * @return The distance squared from the point (px, py) to line segment AB. - */ - public static float getPointSegmentDistanceSq(int px, int py - , int ax, int ay - , int bx, int by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line segment AB - * that is closest to P and then calculate the distance between P - * and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = - deltaABx * deltaABx + deltaABy * deltaABy; - - if (segmentABLengthSq == 0) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = - (deltaAPx * deltaABx + deltaAPy * deltaABy) / segmentABLengthSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and - // closer to A. So return distanceSq from P to A. - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) + (py - by)*(py - by); - - // Closest point on lineAB is inside segment AB. So find the exact - // point on AB and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on - // the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - public static float getPointSegmentDistanceSq(float px - , float py - , float pz - , float ax - , float ay - , float az - , float bx - , float by - , float bz) - { - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaABz = bz - az; - float deltaAPx = px - ax; - float deltaAPy = py - ay; - float deltaAPz = pz - az; - - final float segmentABDistSq = deltaABx * deltaABx - + deltaABy * deltaABy - + deltaABz * deltaABz; - if (segmentABDistSq == 0) - // AB is not a line segment. So just return - // distanceSq from P to A. - return deltaAPx * deltaAPx - + deltaAPy * deltaAPy - + deltaAPz * deltaAPz; - - float u = (deltaABx * deltaAPx - + deltaABy * deltaAPy - + deltaABz * deltaAPz) / segmentABDistSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and - // closer to A. So return distanceSq from P to A. - return deltaAPx * deltaAPx - + deltaAPy * deltaAPy - + deltaAPz * deltaAPz; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) - + (py - by)*(py - by) - + (pz - bz)*(pz - bz); - - - // Closest point on lineAB is inside segment AB. So find the exact - // point on AB and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on - // the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - final float deltaZ = (az + u * deltaABz) - pz; - - return deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; - - } - - /** - * Returns TRUE if line segment AB intersects with line segment CD in any - * manner. Either collinear or at a single point. - * @param ax The x-value for point (ax, ay) in line segment AB. - * @param ay The y-value for point (ax, ay) in line segment AB. - * @param bx The x-value for point (bx, by) in line segment AB. - * @param by The y-value for point (bx, by) in line segment AB. - * @param cx The x-value for point (cx, cy) in line segment CD. - * @param cy The y-value for point (cx, cy) in line segment CD. - * @param dx The x-value for point (dx, dy) in line segment CD. - * @param dy The y-value for point (dx, dy) in line segment CD. - * @return TRUE if line segment AB intersects with line segment CD in any - * manner. - */ - public static boolean segmentsIntersect(int ax - , int ay - , int bx - , int by - , int cx - , int cy - , int dx - , int dy) - { - - /* - * This is modified 2D line-line intersection/segment-segment - * intersection test. - */ - - int deltaABx = bx - ax; - int deltaABy = by - ay; - int deltaCAx = ax - cx; - int deltaCAy = ay - cy; - int deltaCDx = dx - cx; - int deltaCDy = dy - cy; - - int numerator = (deltaCAy * deltaCDx) - (deltaCAx * deltaCDy); - int denominator = (deltaABx * deltaCDy) - (deltaABy * deltaCDx); - - // Perform early exit tests. - if (denominator == 0 && numerator != 0) - { - // If numerator is zero, then the lines are colinear. - // Since it isn't, then the lines must be parallel. - return false; - } - - // Lines intersect. But do the segments intersect? - - // Forcing float division on both of these via casting of the - // denominator. - float factorAB = numerator / (float)denominator; - float factorCD = ((deltaCAy * deltaABx) - (deltaCAx * deltaABy)) - / (float)denominator; - - // Determine the type of intersection - if ((factorAB >= 0.0f) - && (factorAB <= 1.0f) - && (factorCD >= 0.0f) - && (factorCD <= 1.0f)) - { - return true; // The two segments intersect. - } - - // The lines intersect, but segments to not. - - return false; - } -} diff --git a/critterai/.svn/pristine/3b/3b9c79f4eb0eddc4aee9d0cd940b89f65db35a40.svn-base b/critterai/.svn/pristine/3b/3b9c79f4eb0eddc4aee9d0cd940b89f65db35a40.svn-base deleted file mode 100644 index 41fa6d88..00000000 --- a/critterai/.svn/pristine/3b/3b9c79f4eb0eddc4aee9d0cd940b89f65db35a40.svn-base +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -/** - * Indicates the vertex wrap direction of a polygon. - *

Static operations are thread safe.

- */ -public enum WrapDirection -{ - /** - * Polygon vertex wrap direction is clockwise. - */ - CLOCKWISE, - - /** - * Polygon vertex wrap direction is counter-clockwise. - */ - COUNTERCLOCKWISE, - - /** - * The wrap direction hasn't been determined or could not be determined, depending - * on the use case. - */ - UNKNOWN; - - /** - * Returns the opposite of the provided direction. - * NULL and {@link #UNKNOWN} will always return {@link #UNKNOWN}. - * @param direction The direction to invert. - * @return The opposite of the provided direction. - */ - public static WrapDirection getInverted(WrapDirection direction) - { - if (direction == CLOCKWISE) - return COUNTERCLOCKWISE; - if (direction == COUNTERCLOCKWISE) - return CLOCKWISE; - return UNKNOWN; - } -} diff --git a/critterai/.svn/pristine/3c/3ca4eba1443cf9d54e18ae9c17b5a2d7a4f58a33.svn-base b/critterai/.svn/pristine/3c/3ca4eba1443cf9d54e18ae9c17b5a2d7a4f58a33.svn-base deleted file mode 100644 index 486a8afd..00000000 --- a/critterai/.svn/pristine/3c/3ca4eba1443cf9d54e18ae9c17b5a2d7a4f58a33.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nav-u3d-editor")] -[assembly: AssemblyDescription("Pathfinding and obstacle avoidance extensions for the Unity Editor.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2011-2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/3e/3e15ecce08d9584b693137f8ee45ebc60205ce68.svn-base b/critterai/.svn/pristine/3e/3e15ecce08d9584b693137f8ee45ebc60205ce68.svn-base deleted file mode 100644 index 792dd627..00000000 --- a/critterai/.svn/pristine/3e/3e15ecce08d9584b693137f8ee45ebc60205ce68.svn-base +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nmgen -{ - /// - /// Represents a span within a object. - /// - /// - /// - /// Useful instances of this type can only by obtained from a - /// object. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct HeightfieldSpan - { - private uint mPacked; // [Area, Max, Min] - - /// - /// The miniumum height of span. - /// - public ushort Min { get { return (ushort)(mPacked & 0x1fff ); } } - - /// - /// The maximum height of the span. - /// - public ushort Max - { - get { return (ushort)((mPacked >> 13) & 0x1fff); } - } - - /// - /// The area assigned to the span. - /// - public byte Area { get { return (byte)(mPacked >> 26); } } - } -} diff --git a/critterai/.svn/pristine/3f/3f35ca4e29da3eca80a886ac0edb1ab7681f1379.svn-base b/critterai/.svn/pristine/3f/3f35ca4e29da3eca80a886ac0edb1ab7681f1379.svn-base deleted file mode 100644 index caf57289..00000000 --- a/critterai/.svn/pristine/3f/3f35ca4e29da3eca80a886ac0edb1ab7681f1379.svn-base +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "DetourCrowd.h" -#include "DetourCommon.h" -#include "DetourEx.h" - -static const int MAX_LOCAL_BOUNDARY_SEGS = 8; - -struct rcnLocalBoundary -{ - float center[3]; - float segs[6 * MAX_LOCAL_BOUNDARY_SEGS]; - int segmentCount; -}; - -struct rcnCrowdCornerData -{ - float cornerVerts[DT_CROWDAGENT_MAX_CORNERS*3]; - unsigned char cornerFlags[DT_CROWDAGENT_MAX_CORNERS]; - dtPolyRef cornerPolys[DT_CROWDAGENT_MAX_CORNERS]; - int ncorners; -}; - -struct rcnCrowdAgentCoreData -{ - unsigned char state; - dtPolyRef polyRef; - dtPolyRef targetRef; - dtPolyRef cornerRef; - - // Important: Keep this section in sync with the dtCrowdAgent layout. - - int nneis; - - float desiredSpeed; - - float npos[3]; - float disp[3]; - float dvel[3]; - float nvel[3]; - float vel[3]; - - // End of sync section. - - float target[3]; // Corridor target. - float corner[3]; // Next corner. -}; - -extern "C" -{ - EXPORT_API dtCrowd* dtcDetourCrowdAlloc(const int maxAgents - , const float maxAgentRadius - , dtNavMesh* nav) - { - dtCrowd* result = new dtCrowd(); - if (result) - result->init(maxAgents, maxAgentRadius, nav); - return result; - } - - EXPORT_API void dtcDetourCrowdFree(dtCrowd* crowd) - { - if (crowd) - crowd->~dtCrowd(); - } - - EXPORT_API void dtcSetObstacleAvoidanceParams(dtCrowd* crowd - , const int idx - , dtObstacleAvoidanceParams* params) - { - crowd->setObstacleAvoidanceParams(idx, params); - } - - EXPORT_API const void dtcGetObstacleAvoidanceParams( - dtCrowd* crowd - , const int idx - , dtObstacleAvoidanceParams* params) - { - memcpy(params - , crowd->getObstacleAvoidanceParams(idx) - , sizeof(dtObstacleAvoidanceParams)); - } - - EXPORT_API const dtCrowdAgent* dtcGetAgent(dtCrowd* crowd - , const int idx) - { - return crowd->getAgent(idx); - } - - EXPORT_API const int dtcGetAgentCount(dtCrowd* crowd) - { - return crowd->getAgentCount(); - } - - EXPORT_API void dtcUpdateAgentParameters(dtCrowd* crowd - , const int idx, const dtCrowdAgentParams* params) - { - crowd->updateAgentParameters(idx, params); - } - - EXPORT_API void dtcRemoveAgent(dtCrowd* crowd - , const int idx) - { - crowd->removeAgent(idx); - } - - EXPORT_API bool dtcRequestMoveTarget(dtCrowd* crowd - , const int idx - , rcnNavmeshPoint pos) - { - return crowd->requestMoveTarget(idx, pos.polyRef, &pos.point[0]); - } - - EXPORT_API bool dtcAdjustMoveTarget(dtCrowd* crowd - , const int idx - , rcnNavmeshPoint pos) - { - return crowd->adjustMoveTarget(idx, pos.polyRef, &pos.point[0]); - } - - EXPORT_API const dtQueryFilter* dtcGetFilter(dtCrowd* crowd) - { - return crowd->getFilter(); - } - - EXPORT_API void dtcGetQueryExtents(dtCrowd* crowd, float* extents) - { - const float* e = crowd->getQueryExtents(); - dtVcopy(extents, e); - } - - EXPORT_API int dtcGetVelocitySampleCount(dtCrowd* crowd) - { - return crowd->getVelocitySampleCount(); - } - - EXPORT_API const dtProximityGrid* dtcGetGrid(dtCrowd* crowd) - { - return crowd->getGrid(); - } - - EXPORT_API const float dtpgGetCellSize(dtProximityGrid* grid) - { - return grid->getCellSize(); - } - - EXPORT_API void dtpgGetBounds(dtProximityGrid* grid, int* bounds) - { - if (bounds) - { - memcpy(bounds, grid->getBounds(), sizeof(int) * 6); - } - } - - EXPORT_API int dtpgGetItemCountAt(dtProximityGrid* grid - , const int x - , const int y) - { - return grid->getItemCountAt(x, y); - } - - EXPORT_API const dtNavMeshQuery* dtcGetNavMeshQuery(dtCrowd* crowd) - { - return crowd->getNavMeshQuery(); - } - - EXPORT_API void dtcaGetAgentParams(const dtCrowdAgent* agent - , dtCrowdAgentParams* params) - { - if (!agent || !params) - return; - memcpy(params, &agent->params, sizeof(dtCrowdAgentParams)); - } - - EXPORT_API void dtcaGetAgentCorners(const dtCrowdAgent* agent - , rcnCrowdCornerData* resultData) - { - if (!agent || !resultData) - return; - memcpy(resultData, &agent->cornerVerts[0], sizeof(rcnCrowdCornerData)); - } - - EXPORT_API void dtcaGetAgentCoreData(const dtCrowdAgent* agent - , rcnCrowdAgentCoreData* resultData) - { - // The active check is important to the design. - if (!agent || !agent->active || !resultData) - return; - - resultData->state = agent->state; - resultData->polyRef = agent->corridor.getFirstPoly(); - resultData->targetRef = agent->corridor.getLastPoly(); - resultData->cornerRef = agent->cornerPolys[0]; - - int size = sizeof(rcnCrowdAgentCoreData) - - sizeof(unsigned char) - 3 * sizeof(dtPolyRef) - - sizeof(float) * 6; - - memcpy(&resultData->nneis, &agent->nneis, size); - - dtVcopy(&resultData->target[0], agent->corridor.getTarget()); - dtVcopy(&resultData->corner[0], &agent->cornerVerts[0]); - } - - EXPORT_API int dtcaGetAgentNeighbors(const dtCrowdAgent* agent - , dtCrowdNeighbour* neighbors - , const int neighborsSize) - { - if (!agent - || !neighbors - || neighborsSize < agent->nneis) - { - return -1; - } - - int count = agent->nneis; - - memcpy(neighbors, agent->neis, sizeof(dtCrowdNeighbour) * count); - - return count; - } - - EXPORT_API void dtcaGetPathCorridorData(const dtCrowdAgent* agent - , rcnPathCorridorData* corridor) - { - if (!agent || !corridor) - return; - - int count = agent->corridor.getPathCount(); - - corridor->pathCount = count; - dtVcopy(corridor->position, agent->corridor.getPos()); - dtVcopy(corridor->target, agent->corridor.getTarget()); - memcpy(&corridor->path[0] - , agent->corridor.getPath() - , sizeof(dtPolyRef) * count); - } - - EXPORT_API void dtcaGetLocalBoundary(const dtCrowdAgent* agent - , rcnLocalBoundary* boundary) - { - if (!agent || !boundary) - return; - - int count = agent->boundary.getSegmentCount(); - - boundary->segmentCount = count; - dtVcopy(&boundary->center[0], agent->boundary.getCenter()); - - for (int i = 0; i < count; i++) - { - memcpy(&boundary->segs[i*6] - , agent->boundary.getSegment(i) - , sizeof(float) * 6); - } - } - - EXPORT_API void dtcUpdate(dtCrowd* crowd - , const float dt - , rcnCrowdAgentCoreData* coreData) - { - crowd->update(dt, 0); - - for (int i = 0; i < crowd->getAgentCount(); i++) - { - // Note: The get function performs all necessary parameter - // validations. - dtcaGetAgentCoreData(crowd->getAgent(i), &coreData[i]); - } - } - - EXPORT_API int dtcAddAgent(dtCrowd* crowd - , const float* pos - , const dtCrowdAgentParams* params - , const dtCrowdAgent** agent - , rcnCrowdAgentCoreData* initialData) - { - int index = crowd->addAgent(pos, params); - if (agent) - { - if (index == -1) - *agent = 0; - else - { - *agent = crowd->getAgent(index); - dtcaGetAgentCoreData(*agent, initialData); - } - } - return index; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/40/4038a6a2c45a369d9cb5bbf6b0453445cfed57b5.svn-base b/critterai/.svn/pristine/40/4038a6a2c45a369d9cb5bbf6b0453445cfed57b5.svn-base deleted file mode 100644 index 39de38dd..00000000 --- a/critterai/.svn/pristine/40/4038a6a2c45a369d9cb5bbf6b0453445cfed57b5.svn-base +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen.rcn -{ - internal static class CompactHeightfieldEx - { - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfBuildField(IntPtr context - , int walkableHeight - , int walkableStep - , IntPtr sourceField - , [In, Out] CompactHeightfield compactField); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmcfFreeFieldData( - [In, Out] CompactHeightfield chf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfGetCellData([In] CompactHeightfield chf - , [In, Out] CompactCell[] cells - , int cellsSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfGetSpanData([In] CompactHeightfield chf - , [In, Out] CompactSpan[] spans - , int spansSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfErodeWalkableArea(IntPtr context - , int radius - , [In, Out] CompactHeightfield chf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfMedianFilterWalkableArea(IntPtr context - , [In, Out] CompactHeightfield chf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfMarkBoxArea(IntPtr context - , [In] ref Vector3 boundsMin - , [In] ref Vector3 boundsMax - , byte areaId - , [In, Out] CompactHeightfield chf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfMarkConvexPolyArea(IntPtr context - , [In] Vector3[] verts - , int vertCount - , float heightMin - , float heightMax - , byte areaId - , [In, Out] CompactHeightfield chf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfMarkCylinderArea(IntPtr context - , [In] ref Vector3 position - , float radius - , float height - , byte area - , [In, Out] CompactHeightfield chf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfBuildDistanceField(IntPtr context - , [In, Out] CompactHeightfield chf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfBuildRegions(IntPtr context - , [In, Out] CompactHeightfield chf - , int borderSize - , int minRegionArea - , int mergeRegionArea); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmcfBuildRegionsMonotone(IntPtr context - , [In, Out] CompactHeightfield chf - , int borderSize - , int minRegionArea - , int mergeRegionArea); - } -} diff --git a/critterai/.svn/pristine/40/404b8c5f33e8346dd0b9b1446a6c9bafea1ba29d.svn-base b/critterai/.svn/pristine/40/404b8c5f33e8346dd0b9b1446a6c9bafea1ba29d.svn-base deleted file mode 100644 index b2e7ead1..00000000 --- a/critterai/.svn/pristine/40/404b8c5f33e8346dd0b9b1446a6c9bafea1ba29d.svn-base +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.nmgen; -using org.critterai.u3d; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Provides debug utilities related to navigation mesh generation. (Editor Only) - /// - public static class NMGenDebug - { - /// - /// Draws a debug view of a object. - /// - /// - /// - /// Meant to be called during the MonoBehavior.OnRenderObject() method. - /// - /// - /// The polygon mesh to draw. - public static void Draw(PolyMeshData polyData) - { - DebugDraw.SimpleMaterial.SetPass(0); - - Color walkableColor = new Color(0, 0.75f, 1.0f, 0.25f); - Color nullRegionColor = new Color(0, 0, 0, 0.25f); - - int[] pTargetVert = new int[3]; - - GL.Begin(GL.TRIANGLES); - for (int iPoly = 0; iPoly < polyData.polyCount; iPoly++) - { - int pPoly = iPoly * polyData.maxVertsPerPoly * 2; - - if (polyData.areas[iPoly] == NMGen.MaxArea) - GL.Color(walkableColor); - else if (polyData.areas[iPoly] == NMGen.NullRegion) - GL.Color(nullRegionColor); - else - GL.Color(ColorUtil.IntToColor(polyData.areas[iPoly], 1.0f)); - - pTargetVert[0] = polyData.polys[pPoly + 0] * 3; - for (int iPolyVert = 2 - ; iPolyVert < polyData.maxVertsPerPoly - ; iPolyVert++) - { - - if (polyData.polys[pPoly + iPolyVert] - == PolyMesh.NullIndex) - break; - - pTargetVert[1] = - polyData.polys[pPoly + iPolyVert] * 3; - pTargetVert[2] = - polyData.polys[pPoly + iPolyVert - 1] * 3; - - for (int i = 0; i < 3; i++) - { - int p = pTargetVert[i]; - int x = polyData.verts[p + 0]; - // Offset y a little to ensure it clears the - // source geometry. - int y = polyData.verts[p + 1] + 1; - int z = polyData.verts[p + 2]; - GL.Vertex3(polyData.boundsMin[0] + x * polyData.xzCellSize - , polyData.boundsMin[1] + y * polyData.yCellSize - , polyData.boundsMin[2] + z * polyData.xzCellSize); - } - } - } - GL.End(); - - Color internalEdgeColor = new Color(0, 0.2f, 0.25f, 0.25f); - Color boundaryEdgeColor = new Color(0.65f, 0.2f, 0, 0.9f); - - GL.Begin(GL.LINES); - for (int iPoly = 0; iPoly < polyData.polyCount; iPoly++) - { - int pPoly = iPoly * polyData.maxVertsPerPoly * 2; - - for (int iPolyVert = 0; iPolyVert < polyData.maxVertsPerPoly; iPolyVert++) - { - int iv = polyData.polys[pPoly + iPolyVert]; - - if (iv == PolyMesh.NullIndex) - break; - - if (polyData.polys[pPoly + polyData.maxVertsPerPoly + iPolyVert] - == PolyMesh.NullIndex) - { - GL.Color(boundaryEdgeColor); - } - else - GL.Color(internalEdgeColor); - - // Note: Using only first two indexes. - pTargetVert[0] = iv * 3; - - if (iPolyVert + 1 >= polyData.maxVertsPerPoly) - { - // Reached hard end of polygon. Loop back. - iv = polyData.polys[pPoly + 0]; - } - else - { - iv = polyData.polys[pPoly + iPolyVert + 1]; - - if (iv == PolyMesh.NullIndex) - // Reached soft end of polygon. Loop back. - iv = polyData.polys[pPoly + 0]; - } - - pTargetVert[1] = iv * 3; - - for (int i = 0; i < 2; i++) - { - int p = pTargetVert[i]; - int x = polyData.verts[p + 0]; - // Offset y a little to ensure it clears the - // source geometry. - int y = polyData.verts[p + 1] + 1; - int z = polyData.verts[p + 2]; - - GL.Vertex3(polyData.boundsMin[0] + x * polyData.xzCellSize - , polyData.boundsMin[1] + y * polyData.yCellSize - , polyData.boundsMin[2] + z * polyData.xzCellSize); - } - } - } - GL.End(); - } - - /// - /// Draws a debug view of a object. - /// - /// - /// - /// Meant to be called during the MonoBehavior.OnRenderObject() method. - /// - /// - /// The detail mesh to draw. - public static void Draw(PolyMeshDetailData detailData) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.TRIANGLES); - for (int iMesh = 0; iMesh < detailData.meshCount; iMesh++) - { - GL.Color(ColorUtil.IntToColor(iMesh, 0.75f)); - - int pMesh = iMesh * 4; - int pVertBase = (int)detailData.meshes[pMesh + 0]; - int pTriBase = (int)detailData.meshes[pMesh + 2] * 4; - int tCount = (int)detailData.meshes[pMesh + 3]; - - for (int iTri = 0; iTri < tCount; iTri++) - { - for (int iVert = 0; iVert < 3; iVert++) - { - int pVert = pVertBase - + (detailData.tris[pTriBase + (iTri * 4 + iVert)]); - - GL.Vertex(detailData.verts[pVert]); - } - } - } - GL.End(); - - // Draw the triangle lines. - - GL.Begin(GL.LINES); - Color portalColor = new Color(0, 0, 0, 0.25f); - for (int iMesh = 0; iMesh < detailData.meshCount; iMesh++) - { - Color meshColor = ColorUtil.IntToColor(iMesh, 1.0f); - - int pMesh = iMesh * 4; - int pVertBase = (int)detailData.meshes[pMesh + 0]; - int pTriBase = (int)detailData.meshes[pMesh + 2] * 4; - int tCount = (int)detailData.meshes[pMesh + 3]; - - for (int iTri = 0; iTri < tCount; iTri++) - { - byte flags = detailData.tris[pTriBase + (iTri * 4 + 3)]; - for (int iVert = 0, iPrevVert = 2 - ; iVert < 3 - ; iPrevVert = iVert++) - { - if (((flags >> (iPrevVert * 2)) & 0x3) == 0) - GL.Color(meshColor); - else - GL.Color(portalColor); - - int pVert = pVertBase - + (detailData.tris[pTriBase + (iTri * 4 + iVert)]); - int pPrevVert = pVertBase - + (detailData.tris[pTriBase + (iTri * 4 + iPrevVert)]); - - GL.Vertex(detailData.verts[pVert]); - GL.Vertex(detailData.verts[pPrevVert]); - } - } - } - GL.End(); - } - } -} diff --git a/critterai/.svn/pristine/40/40d3b53bccc9116a9e9c3e4bac04314c07b5f769.svn-base b/critterai/.svn/pristine/40/40d3b53bccc9116a9e9c3e4bac04314c07b5f769.svn-base deleted file mode 100644 index ccdeae7b..00000000 --- a/critterai/.svn/pristine/40/40d3b53bccc9116a9e9c3e4bac04314c07b5f769.svn-base +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// A navigation mesh off-mesh connection. - /// - [StructLayout(LayoutKind.Sequential)] - public struct NavmeshConnection - { - /// - /// The flag that indicates the connection is bi-directional. - /// - public const uint BiDirectionalFlag = 0x01; - - /// - /// The endpoints of the connection. [(start, end)]. - /// - /// - /// - /// For a properly built navigation mesh, the start vertex will always be within the - /// bounds of a navigation mesh polygon. - /// - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] - public Vector3[] endpoints; - - /// - /// The radius of the endpoints. [Limit: >=0] - /// - public float radius; - - /// - /// The polygon reference of the connection. - /// - /// - /// - /// All connections are stored as 2-vertex polygons within the navigation mesh. - /// - /// - public ushort polyRef; - - /// - /// Link flags. - /// - /// - /// - /// These are not the user flags. Those are assigned to the connection's polygon. These - /// are link flags used for internal purposes. - /// - /// - public byte flags; - - /// - /// Side. - /// - public byte side; - - /// - /// The id of the off-mesh connection. (User assigned when the navmesh is built.) - /// - /// - /// - /// This value has no meaning to the core navigation system. It's purpose is entirely - /// user defined. - /// - /// - public uint userId; - - /// - /// True if the traversal of the connection can start from either endpoint. False if the - /// connection can only be travered from the start to the end point. - /// - public bool IsBiDirectional - { - get { return (flags & BiDirectionalFlag) != 0; } - } - } -} diff --git a/critterai/.svn/pristine/41/410610af7d9d6f0656c88da1e09924a618e0ad65.svn-base b/critterai/.svn/pristine/41/410610af7d9d6f0656c88da1e09924a618e0ad65.svn-base deleted file mode 100644 index fe3920b6..00000000 --- a/critterai/.svn/pristine/41/410610af7d9d6f0656c88da1e09924a618e0ad65.svn-base +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURPATHQUEUE_H -#define DETOURPATHQUEUE_H - -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" - -static const unsigned int DT_PATHQ_INVALID = 0; - -typedef unsigned int dtPathQueueRef; - -class dtPathQueue -{ - struct PathQuery - { - dtPathQueueRef ref; - /// Path find start and end location. - float startPos[3], endPos[3]; - dtPolyRef startRef, endRef; - /// Result. - dtPolyRef* path; - int npath; - /// State. - dtStatus status; - int keepAlive; - const dtQueryFilter* filter; ///< TODO: This is potentially dangerous! - }; - - static const int MAX_QUEUE = 8; - PathQuery m_queue[MAX_QUEUE]; - dtPathQueueRef m_nextHandle; - int m_maxPathSize; - int m_queueHead; - dtNavMeshQuery* m_navquery; - - void purge(); - -public: - dtPathQueue(); - ~dtPathQueue(); - - bool init(const int maxPathSize, const int maxSearchNodeCount, dtNavMesh* nav); - - void update(const int maxIters); - - dtPathQueueRef request(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter); - - dtStatus getRequestStatus(dtPathQueueRef ref) const; - - dtStatus getPathResult(dtPathQueueRef ref, dtPolyRef* path, int* pathSize, const int maxPath); - - inline const dtNavMeshQuery* getNavQuery() const { return m_navquery; } - -}; - -#endif // DETOURPATHQUEUE_H diff --git a/critterai/.svn/pristine/41/411308416558fc5336f63b8c304a0660a093a40b.svn-base b/critterai/.svn/pristine/41/411308416558fc5336f63b8c304a0660a093a40b.svn-base deleted file mode 100644 index 942e0512..00000000 --- a/critterai/.svn/pristine/41/411308416558fc5336f63b8c304a0660a093a40b.svn-base +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/critterai/.svn/pristine/41/413b73fde930216f49ae2bef43642db4113e5001.svn-base b/critterai/.svn/pristine/41/413b73fde930216f49ae2bef43642db4113e5001.svn-base deleted file mode 100644 index 62794c33..00000000 --- a/critterai/.svn/pristine/41/413b73fde930216f49ae2bef43642db4113e5001.svn-base +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using System; -using org.critterai.nav.u3d.editor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class InputCompileControl - : BuildControl - { - private const string Category = "Input Compile"; - private const float MarginSize = ControlUtil.MarginSize; - - private MiniInputCompile mCompiler; - - public override void Exit() - { - if (Context != null) - { - if (mCompiler != null && !mCompiler.IsFinished) - Debug.LogError("Input compile aborted. (Forced exit.)"); - } - - mCompiler = null; - - base.Exit(); - } - - public override void Update() - { - if (Context == null || mCompiler == null) - // Either an error, or nothing to do. - return; - - NavmeshBuild build = Context.Build; - - if (!build) - return; - - if (Context.Build.BuildState == NavmeshBuildState.Invalid - && mCompiler != null) - { - Logger.PostError("Build has become invalid. Discarded input compile.", Context.Build); - mCompiler = null; - return; - } - - if (!mCompiler.IsFinished) - { - mCompiler.Update(); - return; - } - - if (!mCompiler.HasData) - { - Logger.PostError("Input data compile failed.", null); - mCompiler = null; - } - else if (build.HasInputData) - { - // Note: Don't apply the changes if it will cause - // a state transition. It creates GUI control issues. - ApplyData(); - } - } - - public bool HasInputData { get { return (mCompiler != null && mCompiler.HasData); } } - - protected override void OnGUIMain() - { - NavmeshBuild build = Context.Build; - - if (!build) - return; - - Rect statusArea = Context.MainArea; - - if (build.BuildState == NavmeshBuildState.Invalid) - return; - - InputBuildInfo info; - InputGeometry geometry = null; - ConnectionSet connections = null; - int triCount = 0; - int processorCount = 0; - - ViewOption viewFlags = 0; - bool hasData = false; - - string topLabel; - - if (mCompiler != null) - { - if (mCompiler.IsFinished) - { - if (mCompiler.HasData) - topLabel = "Input successfully compiled. (Needs to be accepted.)"; - else - topLabel = "No input data produced."; - } - else - topLabel = "Compiling"; - - info = mCompiler.Info; - geometry = mCompiler.Geometry; - connections = mCompiler.Connections; - triCount = mCompiler.TriCount; - processorCount = (mCompiler.Processors == null ? 0 : mCompiler.Processors.Length); - - if (geometry != null) - hasData = true; - } - else if (build.HasInputData) - { - topLabel = "Current Input"; - - viewFlags = (ViewOption.Input | ViewOption.Grid); - - info = build.InputInfo; - geometry = build.InputGeom; - connections = build.Connections; - triCount = geometry.TriCount; - processorCount = build.NMGenProcessors.Count; - - hasData = true; - } - else - { - topLabel = "Input needs to be compiled."; - info = new InputBuildInfo(); - } - - DebugContext.SetViews(viewFlags); - - if (!hasData && triCount > 0) - { - GUI.Box(Context.MainArea - , string.Format("{0} {1:N0} triangles", topLabel, triCount) - , EditorUtil.HelpStyle); - - OnGUICompiler(statusArea); - - return; - } - - GUILayout.BeginArea(statusArea, GUI.skin.box); - - string currScene = System.IO.Path.GetFileName(EditorApplication.currentScene); - - int idx = currScene.LastIndexOf("."); - if (idx >= 0) - currScene = currScene.Substring(0, idx); - - if (currScene.Length == 0) - currScene = "None"; - - GUILayout.BeginHorizontal(); - - GUILayout.Label("Input scene:"); - - GUILayout.Label(" Current: " + currScene); - - GUILayout.Label(" Last: " - + NavEditorUtil.SceneDisplayName(build.BuildTarget.BuildInfo)); - - GUILayout.EndHorizontal(); - - if (NavEditorUtil.SceneMismatch(build.BuildTarget.BuildInfo)) - { - GUILayout.Box("Current scene does not match last input scene." - , EditorUtil.WarningStyle); - } - - GUILayout.Space(MarginSize); - - GUILayout.Label(topLabel); - - if (hasData) - { - GUILayout.Space(ControlUtil.MarginSize * 3); - - GUILayout.BeginHorizontal(); - - GUILayout.BeginVertical(); - - GUILayout.Label("Geometry"); - - GUILayout.Space(ControlUtil.MarginSize); - - GUILayout.Label(string.Format("Triangles: {0:N0}", triCount)); - - GUILayout.Space(ControlUtil.MarginSize); - - GUILayout.Label("Min Bounds: " + Vector3Util.ToString(geometry.BoundsMin)); - - GUILayout.Label("Max Bounds: " + Vector3Util.ToString(geometry.BoundsMax)); - - GUILayout.Space(ControlUtil.MarginSize); - - Vector3 diff = geometry.BoundsMax - geometry.BoundsMin; - GUILayout.Label(string.Format("WxHxD: {0:f3} x {1:f3} x {2:f3}" - , diff.x, diff.y, diff.z)); - - GUILayout.Space(ControlUtil.MarginSize * 2); - - // Note: The build press interprets zero root objects as a global search. - - GUILayout.Space(ControlUtil.MarginSize); - GUILayout.Label("Components"); - GUILayout.Space(ControlUtil.MarginSize); - - GUILayout.Label("Pre-filter: " + info.compCountPre); - GUILayout.Label("Post-filter: " + info.compCountPost); - - GUILayout.EndVertical(); - - GUILayout.BeginVertical(); - - GUILayout.Label("Modifiers"); - - GUILayout.Space(ControlUtil.MarginSize); - - GUILayout.Label("Component loaders: " + info.loaderCount); - GUILayout.Label("Component filters: " + info.filterCount); - GUILayout.Label("Area assignment: " + info.areaModifierCount); - GUILayout.Label("Component compilers: " + info.compilerCount); - GUILayout.Label("Input post-processors: " + info.postCount); - GUILayout.Label("NMGen processors: " + processorCount); - GUILayout.Label("Off-Mesh connections: " + connections.Count); - - GUILayout.EndVertical(); - - GUILayout.EndHorizontal(); - } - - GUILayout.EndArea(); - - OnGUICompiler(statusArea); - } - - private void OnGUICompiler(Rect statusArea) - { - if (!(mCompiler == null || mCompiler.IsFinished)) - { - // Assuming that the draw area is at least 25 in height. - Rect area = new Rect(statusArea.x, statusArea.yMax - 25 - , statusArea.width, 25); - - mCompiler.OnGUI(area); - } - } - - private void ApplyData() - { - NavmeshBuild build = Context.Build; // Caller checks for null. - - if (!build.SetInputData(Logger, mCompiler.Geometry - , mCompiler.Info, mCompiler.Processors, mCompiler.Connections - , true)) - { - Logger.PostError("Could not apply input data.", build); - return; // Let the compiler persist so user can review it. - } - - mCompiler = null; - } - - protected override void OnGUIButtons() - { - NavmeshBuild build = Context.Build; - - if (!build) - return; - - if (build.BuildState == NavmeshBuildState.Invalid) - { - GUI.Box(Context.ButtonArea, ""); - return; - } - - bool hasLocalData = (mCompiler != null && mCompiler.HasData); - bool dataExists = (build.HasInputData || hasLocalData); - bool isCompiling = !(mCompiler == null || mCompiler.IsFinished); - - bool guiEnabled = GUI.enabled; - - GUI.enabled = !isCompiling; - - ControlUtil.BeginButtonArea(Context.ButtonArea); - - float origFVal = build.Config.WalkableSlope; - - GUILayout.Label(NMGenConfig.SlopeLabel); - - build.Config.WalkableSlope = EditorGUILayout.FloatField(build.Config.WalkableSlope); - - if (origFVal != build.Config.WalkableSlope) - build.IsDirty = true; - - GUILayout.Space(MarginSize); - - string compileButtonText; - - GUIStyle style = (GUI.enabled && !dataExists) - ? ControlUtil.HighlightedButton : GUI.skin.button; - - if (dataExists) - compileButtonText = "Recompile"; - else - compileButtonText = "Compile"; - - if (GUILayout.Button(compileButtonText, style)) - { - GC.Collect(); - Logger.ResetLog(); - mCompiler = new MiniInputCompile(Context); - - if (mCompiler.IsFinished) - mCompiler = null; - } - - if (hasLocalData) - { - GUILayout.Space(MarginSize); - - style = (GUI.enabled ? ControlUtil.HighlightedButton : GUI.skin.button); - - if (GUILayout.Button("Accept", style)) - ApplyData(); - } - - GUI.enabled = guiEnabled; - - if (isCompiling) - { - GUILayout.Space(MarginSize); - - if (GUILayout.Button("Cancel Compile")) - { - mCompiler.Abort(); - mCompiler = null; - } - } - else - { - bool resetOK = (hasLocalData || build.HasInputData || build.HasBuildData); - - if (ControlUtil.OnGUIStandardButtons(Context, DebugContext, resetOK)) - // Reset button clicked. - mCompiler = null; - } - - ControlUtil.EndButtonArea(); - } - } -} diff --git a/critterai/.svn/pristine/41/41702a78c2c2e41bf57bdee55dfd22a090aedef8.svn-base b/critterai/.svn/pristine/41/41702a78c2c2e41bf57bdee55dfd22a090aedef8.svn-base deleted file mode 100644 index f06ea3a0..00000000 --- a/critterai/.svn/pristine/41/41702a78c2c2e41bf57bdee55dfd22a090aedef8.svn-base +++ /dev/null @@ -1,69 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {9DFC1FE0-6469-4a04-AB13-9EAC59087802} - Library - Properties - org.critterai - cai-nmgen - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG;NUNITY - prompt - 4 - AnyCPU - - - pdbonly - true - ..\bin\Release\ - TRACE;NUNITY - prompt - 4 - AnyCPU - ..\bin\Release\cai-nmgen.XML - - - - - 3.5 - - - - - - rcn\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - {B783B817-8746-4D54-A6CC-664C0A73186F} - cai-nmgen-rcn - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/41/41b333975cc99e5c09eef2dca8be6cd82176efd2.svn-base b/critterai/.svn/pristine/41/41b333975cc99e5c09eef2dca8be6cd82176efd2.svn-base deleted file mode 100644 index 9edd9eb8..00000000 --- a/critterai/.svn/pristine/41/41b333975cc99e5c09eef2dca8be6cd82176efd2.svn-base +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.geom; -using org.critterai.u3d; - -namespace org.critterai.nav.u3d -{ - /// - /// Provides methods useful for debugging navigation. - /// - /// - /// - /// All draw methods use GL, so they should generally be called from within the - /// OnRenderObject() method. - /// - /// - public static class NavDebug - { - #region Static Config - - /// - /// The alpha to use for surface fill. - /// - public static float surfaceAlpha = 0.25f; - - /// - /// The color to use when drawing corner visualizations. - /// - public static Color cornerColor = - new Color(Color.blue.r, Color.blue.g, Color.blue.b, 0.66f); - - /// - /// The scale to use for corner markers. - /// - public static float cornerScale = 0.2f; - - /// - /// The color to use when drawing position visualizations. - /// - public static Color positionColor = - new Color(Color.blue.r, Color.blue.g, Color.blue.b, 0.5f); - - /// - /// The scale to use for position markers. - /// - public static float positionScale = 0.8f; - - /// - /// The base color to use when drawing goal visualizations. - /// - public static Color goalColor = - new Color(Color.green.r, Color.green.g, Color.green.b, 0.5f); - - /// - /// The scale to use for goal markers. - /// - public static float goalScale = 0.8f; - - /// - /// The color to use for drawing visualizations that overlay polygons. - /// - public static Color polygonOverlayColor = - new Color(Color.yellow.r, Color.yellow.g, Color.yellow.b, 0.33f); - - #endregion - - #region Navmesh - - /// - /// Draws a debug visualization of the navigation mesh. - /// - /// The mesh to draw. - /// - /// If true, will be colored by polygon area. If false, will be colored by tile index. - /// - public static void Draw(Navmesh mesh, bool colorByArea) - { - int count = mesh.GetMaxTiles(); - for (int i = 0; i < count; i++) - { - Draw(mesh.GetTile(i), null, null, 0, colorByArea ? -1 : i); - } - } - - /// - /// Draws a debug visualization of the specified navigation mesh tile. - /// - /// - /// - /// This method is safe to call on empty tile locations. - /// - /// - /// The mesh. - /// The tile grid x-location. - /// The tile grid z-location. - /// The tile layer. - /// - /// If true, will be colored by polygon area. If false, will be colored by tile index. - /// - public static void Draw(Navmesh mesh, int tx, int tz, int layer, bool colorByArea) - { - NavmeshTile tile = mesh.GetTile(tx, tz, layer); - - if (tile == null) - // No tile at grid location. - return; - - Draw(tile, null, null, 0 - , colorByArea ? -1 : tx.GetHashCode() ^ tz.GetHashCode() ^ layer.GetHashCode()); - } - - /// - /// Draws a debug visualization of the navigation mesh with the closed nodes highlighted. - /// - /// The mesh to draw. - /// The query which provides the list of closed nodes. - public static void Draw(Navmesh mesh, NavmeshQuery query) - { - int count = mesh.GetMaxTiles(); - for (int i = 0; i < count; i++) - { - Draw(mesh.GetTile(i), query, null, 0, i); - } - } - - /// - /// Draws a debug visualization of the navigation mesh with the specified polygons - /// highlighted. - /// - /// The mesh to draw. - /// - /// The references of the polygons that should be highlighted. - /// - /// - /// The number of polygons in the array. - /// - public static void Draw(Navmesh mesh, uint[] markPolys, int polyCount) - { - int count = mesh.GetMaxTiles(); - for (int i = 0; i < count; i++) - { - Draw(mesh.GetTile(i) - , null - , markPolys - , polyCount - , i); - } - } - - /// - /// Draws a debug visualization of a corridor. - /// - /// The navigation mesh associated with the corridor. - /// The corridor to draw. - public static void Draw(Navmesh mesh, PathCorridorData corridor) - { - if (corridor.pathCount == 0) - return; - - DebugDraw.SimpleMaterial.SetPass(0); - - Vector3[] tileVerts = null; - - for (int iPoly = 0; iPoly < corridor.pathCount; iPoly++) - { - NavmeshTile tile; - NavmeshPoly poly; - mesh.GetTileAndPoly(corridor.path[iPoly], out tile, out poly); - - if (poly.Type == NavmeshPolyType.OffMeshConnection) - continue; - - NavmeshTileHeader header = tile.GetHeader(); - if (tileVerts == null - || tileVerts.Length < 3 * header.vertCount) - { - // Resize. - tileVerts = new Vector3[header.vertCount]; - } - - tile.GetVerts(tileVerts); - - GL.Begin(GL.TRIANGLES); - GL.Color(polygonOverlayColor); - - int pA = poly.indices[0]; - for (int i = 2; i < poly.vertCount; i++) - { - int pB = poly.indices[i - 1]; - int pC = poly.indices[i]; - - GL.Vertex(tileVerts[pA]); - GL.Vertex(tileVerts[pB]); - GL.Vertex(tileVerts[pC]); - } - - GL.End(); - - // Not drawing boundaries since it would obscure other agent - // debug data. - } - - Vector3 v = corridor.position; - DebugDraw.XMarker(v, positionScale, positionColor); - DebugDraw.Circle(v, positionScale, positionColor); - DebugDraw.Circle(v, positionScale * 0.5f, positionColor); - DebugDraw.Circle(v, positionScale * 0.25f, positionColor); - - v = corridor.target; - DebugDraw.XMarker(v, goalScale, goalColor); - DebugDraw.Circle(v, goalScale, goalColor); - DebugDraw.Circle(v, goalScale * 0.5f, goalColor); - DebugDraw.Circle(v, goalScale * 0.25f, goalColor); - } - - private static Color GetStandardColor(uint polyRef, int polyArea, int colorId - , NavmeshQuery query, uint[] markPolys, int markPolyCount) - { - Color result; - - if ((query != null && query.IsInClosedList(polyRef)) - || IsInList(polyRef, markPolys, markPolyCount) != -1) - { - result = polygonOverlayColor; - } - else - { - if (colorId == -1) - { - if (polyArea == 0) - result = new Color(0, 0.75f, 1, surfaceAlpha); - else - result = ColorUtil.IntToColor(polyArea, surfaceAlpha); - } - else - result = ColorUtil.IntToColor(colorId, surfaceAlpha); - } - - return result; - } - - /// - /// Draws a debug visualization of an individual navmesh tile. - /// - /// - /// - /// The tile will be checked to see if it is in use before it is drawn. So there is no - /// need for caller to do so. - /// - /// - private static void Draw(NavmeshTile tile - , NavmeshQuery query, uint[] markPolys, int markPolyCount - , int colorId) - { - NavmeshTileHeader header = tile.GetHeader(); - - // Keep this check. Less trouble for clients. - if (header.polyCount < 1) - return; - - DebugDraw.SimpleMaterial.SetPass(0); - - uint polyBase = tile.GetBasePolyRef(); - - NavmeshPoly[] polys = new NavmeshPoly[header.polyCount]; - tile.GetPolys(polys); - - Vector3[] verts = new Vector3[header.vertCount]; - tile.GetVerts(verts); - - NavmeshDetailMesh[] meshes = - new NavmeshDetailMesh[header.detailMeshCount]; - tile.GetDetailMeshes(meshes); - - byte[] detailTris = new byte[header.detailTriCount * 4]; - tile.GetDetailTris(detailTris); - - Vector3[] detailVerts = new Vector3[header.detailVertCount]; - tile.GetDetailVerts(detailVerts); - - GL.Begin(GL.TRIANGLES); - for (int i = 0; i < header.polyCount; i++) - { - NavmeshPoly poly = polys[i]; - - if (poly.Type == NavmeshPolyType.OffMeshConnection) - continue; - - NavmeshDetailMesh mesh = meshes[i]; - - Color color = GetStandardColor(polyBase | (uint)i - , poly.Area, colorId - , query, markPolys, markPolyCount); - - GL.Color(color); - - for (int j = 0; j < mesh.triCount; j++) - { - int pTri = (int)(mesh.triBase + j) * 4; - - for (int k = 0; k < 3; k++) - { - // Note: iVert and pVert refer to different - // arrays. - int iVert = detailTris[pTri + k]; - if (iVert < poly.vertCount) - { - // Get the vertex from the main vertices. - int pVert = poly.indices[iVert]; - GL.Vertex(verts[pVert]); - } - else - { - // Get the vertex from the detail vertices. - int pVert = (int) - (mesh.vertBase + iVert - poly.vertCount); - GL.Vertex(detailVerts[pVert]); - } - } - } - } - GL.End(); - - NavmeshLink[] links = new NavmeshLink[header.maxLinkCount]; - tile.GetLinks(links); - - GL.Begin(GL.LINES); - - DrawPolyBoundaries(header - , polys - , verts - , meshes - , detailTris - , detailVerts - , links - , new Color(0, 0.2f, 0.25f, 0.13f) - , true); - - DrawPolyBoundaries(header - , polys - , verts - , meshes - , detailTris - , detailVerts - , links - , new Color(0.65f, 0.2f, 0, 0.9f) - , false); - - if (header.connCount == 0) - { - GL.End(); - return; - } - - NavmeshConnection[] conns = new NavmeshConnection[header.connCount]; - tile.GetConnections(conns); - - for (int i = 0; i < header.polyCount; i++) - { - NavmeshPoly poly = polys[i]; - - if (poly.Type != NavmeshPolyType.OffMeshConnection) - continue; - - Color color = GetStandardColor(polyBase | (uint)i - , poly.Area, colorId - , query, markPolys, markPolyCount); - - // Note: Alpha of less than one doesn't look good because connections tend to - // overlay a lot of geometry, resulting is off color transitions. - color.a = 1; - - GL.Color(color); - - NavmeshConnection conn = conns[i - header.connBase]; - - Vector3 va = verts[poly.indices[0]]; - Vector3 vb = verts[poly.indices[1]]; - - // Check to see if start and end end-points have links. - bool startSet = false; - bool endSet = false; - for (uint k = poly.firstLink; k != Navmesh.NullLink; k = links[k].next) - { - if (links[k].edge == 0) - startSet = true; - if (links[k].edge == 1) - endSet = true; - } - - // For linked endpoints: Draw a line between on-mesh location and endpoint, - // and draw circle at the endpoint. - // For un-linked endpoints: Draw a small red x-marker. - - if (startSet) - { - GL.Vertex(va); - GL.Vertex(conn.endpoints[0]); - DebugDraw.AppendCircle(conn.endpoints[0], conn.radius); - } - else - { - GL.Color(Color.red); - DebugDraw.AppendXMarker(conn.endpoints[0], 0.1f); - GL.Color(color); - } - - if (endSet) - { - GL.Vertex(vb); - GL.Vertex(conn.endpoints[1]); - DebugDraw.AppendCircle(conn.endpoints[1], conn.radius); - } - else - { - GL.Color(Color.red); - DebugDraw.AppendXMarker(conn.endpoints[1], 0.1f); - GL.Color(color); - } - - DebugDraw.AppendArc(conn.endpoints[0], conn.endpoints[1] - , 0.25f - , conn.IsBiDirectional ? 0.6f : 0 - , 0.6f); - } - - GL.End(); - } - - /// - /// Returns the index of the polygon reference within the list, or - /// -1 if it was not found. - /// - private static int IsInList(uint polyRef - , uint[] polyList - , int polyCount) - { - if (polyList == null) - return -1; - - for (int i = 0; i < polyCount; i++) - { - if (polyList[i] == polyRef) - return i; - } - - return -1; - } - - /// - /// Draws the polygon boundary lines based on the height detail. - /// - private static void DrawPolyBoundaries(NavmeshTileHeader header - , NavmeshPoly[] polys - , Vector3[] verts - , NavmeshDetailMesh[] meshes - , byte[] detailTris - , Vector3[] detailVerts - , NavmeshLink[] links - , Color color - , bool inner) - { - const float thr = 0.01f * 0.01f; - - for (int i = 0; i < header.polyCount; i++) - { - NavmeshPoly poly = polys[i]; - - if (poly.Type == NavmeshPolyType.OffMeshConnection) - continue; - - NavmeshDetailMesh mesh = meshes[i]; - Vector3[] tv = new Vector3[3]; - - for (int j = 0, nj = (int)poly.vertCount; j < nj; j++) - { - Color c = color; // Color may change. - if (inner) - { - if (poly.neighborPolyRefs[j] == 0) - continue; - if ((poly.neighborPolyRefs[j] - & Navmesh.ExternalLink) != 0) - { - bool con = false; - for (uint k = poly.firstLink - ; k != Navmesh.NullLink - ; k = links[k].next) - { - if (links[k].edge == j) - { - con = true; - break; - } - } - if (con) - c = new Color(1, 1, 1, 0.2f); - else - c = new Color(0, 0, 0, 0.2f); - } - else - c = new Color(0, 0.2f, 0.25f, 0.13f); - } - else - { - if (poly.neighborPolyRefs[j] != 0) - continue; - } - - GL.Color(c); - - int pVertA = poly.indices[j]; - int pVertB = poly.indices[(j + 1) % nj]; - - for (int k = 0; k < mesh.triCount; k++) - { - int pTri = (int)((mesh.triBase + k) * 4); - for (int m = 0; m < 3; m++) - { - int iVert = detailTris[pTri + m]; - if (iVert < poly.vertCount) - { - int pv = poly.indices[iVert]; - tv[m] = verts[pv]; - } - else - { - int pv = (int)(mesh.vertBase - + (iVert - poly.vertCount)); - tv[m] = detailVerts[pv]; - } - } - for (int m = 0, n = 2; m < 3; n = m++) - { - if (((detailTris[pTri + 3] >> (n * 2)) & 0x3) == 0) - // Skip inner detail edges. - continue; - - float distN = Line2.GetPointLineDistanceSq( - new Vector2(tv[n].x, tv[n].z) - , new Vector2(verts[pVertA].x, verts[pVertA].z) - , new Vector2(verts[pVertB].x, verts[pVertB].z)); - float distM = Line2.GetPointLineDistanceSq( - new Vector2(tv[m].x, tv[m].z) - , new Vector2(verts[pVertA].x, verts[pVertA].z) - , new Vector2(verts[pVertB].x, verts[pVertB].z)); - - if (distN < thr && distM < thr) - { - GL.Vertex(tv[n]); - GL.Vertex(tv[m]); - } - } - } - } - } - } - - /// - /// Returns the 3D centroids of the provided navigation mesh polygons. - /// - /// - /// - /// If a polygon does not exist within the mesh, its associated centroid will not - /// be altered. So some centroid data will be invalid if - /// is not equal to the result count. - /// - /// - /// The navigation mesh containing the polygons. - /// The references of the polygons. - /// The number of polygons. - /// - /// The centroids for the polygons. [Length: >= polyCount] (Out) - /// - /// The actual number of polygons found within the mesh. - public static int GetCentroids(Navmesh mesh - , uint[] polyRefs - , int polyCount - , Vector3[] centroids) - { - int resultCount = 0; - int count = mesh.GetMaxTiles(); - for (int i = 0; i < count; i++) - { - resultCount += GetCentroids(mesh.GetTile(i) - , polyRefs - , polyCount - , centroids); - if (resultCount == polyRefs.Length) - break; - } - return resultCount; - } - - /// - /// Gets the centroids for the polygons that are part of the tile. - /// - private static int GetCentroids(NavmeshTile tile - , uint[] polyRefs - , int polyCount - , Vector3[] centroids) - { - NavmeshTileHeader header = tile.GetHeader(); - - if (header.polyCount < 1) - return 0; - - uint polyBase = tile.GetBasePolyRef(); - - NavmeshPoly[] polys = new NavmeshPoly[header.polyCount]; - tile.GetPolys(polys); - - Vector3[] verts = new Vector3[header.vertCount]; - tile.GetVerts(verts); - - int resultCount = 0; - - for (int i = 0; i < header.polyCount; i++) - { - uint polyRef = polyBase | (uint)i; - - int iResult = IsInList(polyRef, polyRefs, polyCount); - - if (iResult == -1) - continue; - - resultCount++; - - NavmeshPoly poly = polys[i]; - - centroids[iResult] = GetCentroid(verts, poly.indices, poly.vertCount); - } - - return resultCount; - } - - /// - /// Gets the centroid for a polygon. - /// - private static Vector3 GetCentroid(Vector3[] verts - , ushort[] indices - , int vertCount) - { - // Reference: - // http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - Vector3 result = new Vector3(); - - for (int i = 0; i < vertCount; i++) - { - int p = (ushort)indices[i]; - result += verts[p]; - } - - result.x /= vertCount; - result.y /= vertCount; - result.z /= vertCount; - - return result; - } - - #endregion - - #region Miscellaneous - - /// - /// Draws a debug visualization of corner data. - /// - /// The corners to draw. - public static void Draw(CornerData corners) - { - if (corners.cornerCount == 0) - return; - - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - - GL.Color(cornerColor); - - for (int i = 0; i < corners.cornerCount; i++) - { - DebugDraw.AppendXMarker(corners.verts[i], cornerScale); - } - - GL.End(); - } - - #endregion - } -} diff --git a/critterai/.svn/pristine/43/436576446733a999ddaf89286e3c4abc92f50672.svn-base b/critterai/.svn/pristine/43/436576446733a999ddaf89286e3c4abc92f50672.svn-base deleted file mode 100644 index e0645ee8..00000000 --- a/critterai/.svn/pristine/43/436576446733a999ddaf89286e3c4abc92f50672.svn-base +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.geom; -using System.Collections.Generic; -using org.critterai.nmgen; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Represents triangle mesh and area data used as input to the NMGen build process. - /// - /// - /// - /// Objects of this type are created using the class. - /// - /// - /// Objects of this type are guarenteed to be thread-safe, immutable, and contain at least - /// one triangle. There is no empty state. - /// - /// - /// The data storage is optimized for the NMGen build process, so this is not a general - /// use class. - /// - /// - /// - /// - public sealed class InputGeometry - { - private readonly Vector3 mBoundsMin; - private readonly Vector3 mBoundsMax; - - private readonly ChunkyTriMesh mMesh; - - internal InputGeometry(ChunkyTriMesh mesh, Vector3 boundsMin, Vector3 boundsMax) - { - mBoundsMin = boundsMin; - mBoundsMax = boundsMax; - mMesh = mesh; - } - - /// - /// The minimum bounds of the AABB. - /// - public Vector3 BoundsMin { get { return mBoundsMin; } } - - /// - /// The maximum bounds of the AABB. - /// - public Vector3 BoundsMax { get { return mBoundsMax; } } - - /// - /// The number of triangles. [Limit: > 0] - /// - public int TriCount { get { return mMesh.TriCount; } } - - internal ChunkyTriMesh Mesh { get { return mMesh; } } - - /// - /// Extracts all input geometry for inspection. - /// - /// - /// - /// This method exists to permit debugging. - /// - /// - /// The triangle areas. - /// The triangle mesh. - public TriangleMesh ExtractMesh(out byte[] areas) - { - return mMesh.ExtractMesh(out areas); - } - - /// - /// Extracts all input geometry for a particular bounds. - /// - /// - /// - /// This method exists to permit debugging. - /// - /// - /// The returned result is only guarenteed to be the result 'seen' by the NMGen build - /// process. - /// - /// - /// The minimum x-axis bounds. - /// The minimum z-axis bounds. - /// The maximum x-axis bounds. - /// The maximum z-axis bounds. - /// The triangle areas. - /// The triangle mesh. - public TriangleMesh ExtractMesh(float xmin, float zmin, float xmax, float zmax - , out byte[] areas) - { - byte[] lareas; - - TriangleMesh lmesh = mMesh.ExtractMesh(out lareas); - - List nodes = new List(); - - int triCount = mMesh.GetChunks(xmin, zmin, xmax, zmax, nodes); - - if (triCount == 0) - { - areas = new byte[0]; - return new TriangleMesh(); - } - - TriangleMesh result = new TriangleMesh(); - result.verts = lmesh.verts; - result.vertCount = lmesh.vertCount; - - result.tris = new int[triCount * 3]; - result.triCount = triCount; - areas = new byte[triCount]; - - int i = 0; - foreach (ChunkyTriMeshNode node in nodes) - { - for (int j = 0; j < node.count; j++, i++) - { - result.tris[i * 3 + 0] = lmesh.tris[(node.i + j) * 3 + 0]; - result.tris[i * 3 + 1] = lmesh.tris[(node.i + j) * 3 + 1]; - result.tris[i * 3 + 2] = lmesh.tris[(node.i + j) * 3 + 2]; - areas[i] = lareas[node.i + j]; - } - } - - return result; - } - } -} diff --git a/critterai/.svn/pristine/43/438222233142a130426380b67866cafb64ead002.svn-base b/critterai/.svn/pristine/43/438222233142a130426380b67866cafb64ead002.svn-base deleted file mode 100644 index a3e311fa..00000000 --- a/critterai/.svn/pristine/43/438222233142a130426380b67866cafb64ead002.svn-base +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild -{ - /// - /// Flags for common build options. - /// - /// - /// - /// Most builds have all flags set except . - /// - /// - /// - /// - [System.Flags] - public enum NMGenBuildFlag - { - /* - * Design notes: - * - * Keep the base type of this enum an integer in order to remain - * compatible with Unity serialization. - * - */ - - /// - /// Include - /// in the build. - /// - LedgeSpansNotWalkable = 0x010, - - /// - /// Include - /// in the build. - /// - LowHeightSpansNotWalkable = 0x020, - - /// - /// Include - /// in the build. - /// - LowObstaclesWalkable = 0x040, - - /// - /// Apply the 0x01 flag to all polygons in the - /// object. - /// - ApplyPolyFlags = 0x080, - - /// - /// Generate tile bounding volumns. - /// - BVTreeEnabled = 0x100 - } -} diff --git a/critterai/.svn/pristine/43/439f079ffa025ff3e8fd833b22a36e428a2798b0.svn-base b/critterai/.svn/pristine/43/439f079ffa025ff3e8fd833b22a36e428a2798b0.svn-base deleted file mode 100644 index d6f8d689..00000000 --- a/critterai/.svn/pristine/43/439f079ffa025ff3e8fd833b22a36e428a2798b0.svn-base +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.nmgen.rcn -{ - internal static class HeightfieldLayserSetEx - { - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int nmlsBuildLayers(IntPtr context - , [In] CompactHeightfield chf - , int borderSize - , int walkableHeight - , ref IntPtr layerSet); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmlsFreeLayers(IntPtr lset); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmlsGetLayer(IntPtr lset - , int index - , [In, Out] HeightfieldLayer layer); - } -} diff --git a/critterai/.svn/pristine/43/43bed4d0f3840ca050e58d9a0039860695168636.svn-base b/critterai/.svn/pristine/43/43bed4d0f3840ca050e58d9a0039860695168636.svn-base deleted file mode 100644 index 363db96b..00000000 --- a/critterai/.svn/pristine/43/43bed4d0f3840ca050e58d9a0039860695168636.svn-base +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" -#include "RecastAlloc.h" - -extern "C" -{ - EXPORT_API void nmgFreeSerializationData(unsigned char** data) - { - rcFree(*data); - *data = 0; - } - - // The only purpose for this function is to allow testing - // the context interop. - EXPORT_API void nmgTestContext(rcContext* ctx, const int count) - { - for (int i = 0; i < count; i++) - { - ctx->log(RC_LOG_PROGRESS, "MSG: %d", i); - } - } - - EXPORT_API void nmgMarkWalkableTriangles(rcContext* ctx - , const float walkableSlopeAngle - , const float* verts - , int nv - , const int* tris - , int nt - , unsigned char* areas) - { - rcMarkWalkableTriangles(ctx - , walkableSlopeAngle - , verts - , nv - , tris - , nt - , areas); - } - - EXPORT_API void nmgClearUnwalkableTriangles(rcContext* ctx - , const float walkableSlopeAngle - , const float* verts - , int nv - , const int* tris - , int nt - , unsigned char* areas) - { - rcClearUnwalkableTriangles(ctx - , walkableSlopeAngle - , verts - , nv - , tris - , nt - , areas); - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/44/448b105efd4009fe5ce6d429a7000563e1f38122.svn-base b/critterai/.svn/pristine/44/448b105efd4009fe5ce6d429a7000563e1f38122.svn-base deleted file mode 100644 index 22982846..00000000 --- a/critterai/.svn/pristine/44/448b105efd4009fe5ce6d429a7000563e1f38122.svn-base +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - A multi-tile navigation mesh consists of a group of square tiles layed out in a grid on the xz-plane. Each tile in the mesh consists of its - own polygon mesh, detail mesh, and off-mesh connection data. The tiles are linked together when added to the navigation mesh to form - the full navigation mesh. - - - This topic covers the extra steps necessary to create a multi-tile navigation mesh. - - - -
- - The Multi-Tile Build Process - - - - - The process for building multi-tile navigation meshes is very similar to building a single-tile mesh. The main difference is that you need to - repeat the IncrementalBuilder and tile build steps for each tile, then combine the result into the final navigation mesh. You also have a new - input data class: TileSetDefinition. This class combines the InputGeometry and some configuration settings to define - the tile set. - - - - // Example: A simple multi-tile navigation mesh build. - - // Where 'geom' is an InputGeometry object and 'pset' is a ProcessorSet object. - - NMGenParams config = new NMGenParams(); - - // Load the various standard config settings based on your needs. - // E.g. cell size and agent settings. - - // ... - - // Then set the tile settings. - // The border size must be greater than zero, otherwise the tiles won't connect - // properly when added to the navigation mesh. You should almost always use - // the standard border size. - - config.TileSize = 512; - config.BorderSize = NMGenParams.DeriveBorderSize(config); // Standard border size. - - // Create the tile set definition. - TileSetDefinition tdef = - TileSetDefinition.Create(geom.BoundsMin, geom.BoundsMax, config, geom); - - NMGenAssetFlag resultFlags = NMGenAssetFlag.PolyMesh | NMGenAssetFlag.DetailMesh; - - List<TileBuildAssets> tiles = new List<TileBuildAssets>(); - int maxPolys = 0; // Need to keep track of maximum polys in a tile. - - // Interate over all tiles and build. - for (int tx = 0; tx < tdef.Width; tx++) - { - for (int tz = 0; tz < tdef.Depth; tz++) - { - IncrementalBuilder builder = - IncrementalBuilder.Create(tx, tz, resultFlags, tdef, pset); - - // Perform the build and check the result. - builder.BuildAll(); - - switch (builder.State) - { - case NMGenState.Aborted: - - // Handle the error. - // Check builder messages for details. - - case NMGenState.NoResult: - - // No result was produced. This is not uncommon for multi-tile builds. - // E.g. There may be no geometry at the location. - - continue; - } - - // Completed with a result. Build the tile data. - - NMGenAssets assets = builder.Result; - - // You can build the tile manually, but the tile build task will take - // care of standard error handling. - - TileBuildTask task = TileBuildTask.Create(tx, tz - , assets.PolyMesh.GetData(false), assets.DetailMesh.GetData(false) - , ConnectionSet.CreateEmpty() // Or use your connection set. - , false, 0); - - task.Run(); - - if (task.TaskState == BuildTaskState.Aborted) - { - // Perform error handling. - // Check task messages for details. - } - - TileBuildAssets tassets = task.Result; - - // Store for later. - tiles.Add(tassets); - - maxPolys = System.Math.Max(maxPolys, tassets.PolyCount); - } - - // Create an empty navigation mesh large enough to hold all tiles - // that produced a result. - - NavmeshParams nconfig = new NavmeshParams(tdef.BoundsMin - , tdef.Width, tdef.Depth - , tiles.Count, maxPolys); - - Navmesh navmesh; - - if ((Navmesh.Create(nconfig, out navmesh) & NavStatus.Sucess) == 0) - { - // Perform error handling. - } - - // Add the tiles to the navigation mesh. - foreach (TileBuildAssets tile in tiles) - { - // Note: Allowing the navigation mesh to assign the tile reference. - uint trash; - navmesh.AddTile(tile.Tile, Navmesh.NullTile, out trash); - } - - // The navigation mesh is ready to use. - // You will usually serialize it for later use. - } - - - - -
- -
- - Notes - - - - - The tile size should usually be between 500 and 1000. A tile size that is too small can result in extra, - unnecessary polygons and less than optimal pathfinding. A value that is too large can be result in memory and - performance issues during the build process. - In general, pick the largest size that also results in a good tile layout along the x and z axes. (You want to avoid creation - of thin tiles along the upper bounds of the navigation mesh.) - - - - You can use a single ConnectionSet for the entire build. The build process will add the appropriate - connections to each tile. - - - - Off-mesh connections can only be formed between a tile and its immediate neighbors. For example, an off-mesh connection - can't start in tile (5, 8) and end in (5, 10) since it would skip over tile (5, 9). So keep the length of off-mesh - connections less than (TileSize * XZCellSize). - - - - -
- - - - T:org.critterai.nmbuild.IncrementalBuilder - T:org.critterai.nmgen.NMGenParams - T:org.critterai.nmgen.NMGenTileParams - T:org.critterai.nmbuild.TileSetDefinition - T:org.critterai.nmbuild.TileBuildTask - T:org.critterai.nmbuild.TileBuildAssets - - - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/44/44aa5e97c2d2b2ca3ae2ede91af8dbc7024b638e.svn-base b/critterai/.svn/pristine/44/44aa5e97c2d2b2ca3ae2ede91af8dbc7024b638e.svn-base deleted file mode 100644 index e33b3223..00000000 --- a/critterai/.svn/pristine/44/44aa5e97c2d2b2ca3ae2ede91af8dbc7024b638e.svn-base +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" -#include "RecastAlloc.h" - -// Used for versioning related to serialization. -static const long NMG_POLYMESHDETAIL_VERSION = 1; - -struct nmgPolyMeshDetailHeader -{ - int nmeshes; - int nverts; - int ntris; - int maxmeshes; - int maxverts; - int maxtris; - long version; -}; - -struct nmgPolyMeshDetail - : rcPolyMeshDetail -{ - int maxmeshes; - int maxverts; - int maxtris; - unsigned char resourcetype; -}; - -// Iterates an array of vertices and copies the unique vertices to -// another array. -// vertCount - The number of vertices in sourceVerts. -// sourceVerts - The source vertices in the form (x, y, z). Length equals -// vertCount * 3. -// resultVerts - An initialized array to load unique vertices into. -// Values will be in the form (x, y, z). It must be the same length as -// sourceVerts. -// indicesMap - An initialized array of length vertCount which will hold -// the map of indices from sourceVerts to resultVerts. E.g. If the value -// at index 5 is 2, then sourceVerts[5*3] is located at resultVerts[2*3]. -// Returns: The number of unique vertices found. -// Notes: -// If there are no duplicate vertices, the content of the source and -// result arrays will be identical and vertCount will equal -// resultVertCount. -int removeDuplicateVerts(int vertCount - , const float* sourceVerts - , float* resultVerts - , int* indicesMap) -{ - int resultCount = 0; - - for (int i = 0; i < vertCount; i++) - { - int index = resultCount; - int pi = i*3; - // Check to see if this vertex has already been seen. - for (int j = 0; j < resultCount; j++) - { - int pj = j*3; - if (nmgSloppyEquals(sourceVerts[pi+0], resultVerts[pj+0]) - && nmgSloppyEquals(sourceVerts[pi+1], resultVerts[pj+1]) - && nmgSloppyEquals(sourceVerts[pi+2], resultVerts[pj+2])) - { - // This vertex already exists. - index = j; - break; - } - } - indicesMap[i] = index; - if (index == resultCount) - { - // This is a new vertex. - resultVerts[resultCount*3+0] = sourceVerts[pi+0]; - resultVerts[resultCount*3+1] = sourceVerts[pi+1]; - resultVerts[resultCount*3+2] = sourceVerts[pi+2]; - resultCount++; - } - } - - return resultCount; - -}; - -extern "C" -{ - // Won't free managed local resources. - EXPORT_API bool rcpdFreeMeshData(nmgPolyMeshDetail* mesh) - { - // Dev Note: Expect that the structure was allocated externally. - // So only free the fields expected to have been allocated internally. - - if (mesh && mesh->resourcetype == NMG_ALLOC_TYPE_LOCAL) - { - rcFree(mesh->meshes); - rcFree(mesh->verts); - rcFree(mesh->tris); - return true; - } - - return false; - } - - EXPORT_API bool rcpdGetSerializedData(const nmgPolyMeshDetail* mesh - , bool includeBuffer - , unsigned char** resultData - , int* dataSize) - { - if (!mesh - || !resultData - || !dataSize - || mesh->maxmeshes == 0) - { - return false; - } - - nmgPolyMeshDetailHeader header; - header.version = NMG_POLYMESHDETAIL_VERSION; - memcpy(&header - , &mesh->nmeshes - , sizeof(nmgPolyMeshDetailHeader) - sizeof(long)); - - int meshCount = (includeBuffer ? mesh->maxmeshes : mesh->nmeshes); - int vertCount = (includeBuffer ? mesh->maxverts : mesh->nverts); - int triCount = (includeBuffer ? mesh->maxtris : mesh->ntris); - - header.maxmeshes = meshCount; - header.maxverts = vertCount; - header.maxtris = triCount; - - int headerSize = sizeof(nmgPolyMeshDetailHeader); - int vertSize = sizeof(float) * (vertCount * 3); - int meshSize = sizeof(unsigned int) * (meshCount * 4); - int trisSize = sizeof(unsigned char) * (triCount * 4); - - int totalDataSize = headerSize + vertSize + meshSize + trisSize; - - unsigned char* data = - (unsigned char*)rcAlloc(totalDataSize, RC_ALLOC_PERM); - - if (!data) - return false; - - int pos = 0; - memcpy(&data[pos], &header, headerSize); - pos += headerSize; - - memcpy(&data[pos], mesh->meshes, meshSize); - pos += meshSize; - - memcpy(&data[pos], mesh->tris, trisSize); - pos += trisSize; - - memcpy(&data[pos], mesh->verts, vertSize); - pos += vertSize; - - *resultData = data; - *dataSize = totalDataSize; - - return true; - } - - EXPORT_API bool rcpdBuildFromMeshData(const unsigned char* meshData - , const int dataSize - , nmgPolyMeshDetail* resultMesh) - { - int headerSize = sizeof(nmgPolyMeshDetailHeader); - - if (!meshData - || !resultMesh - || resultMesh->maxmeshes // Buffers should not be allocated. - || dataSize < headerSize) - return false; - - nmgPolyMeshDetailHeader header; - - memcpy(&header, meshData, headerSize); - - if (header.version != NMG_POLYMESHDETAIL_VERSION) - return false; - - int vertSize = sizeof(float) * (header.maxverts * 3); - int meshSize = sizeof(unsigned int) * (header.maxmeshes * 4); - int trisSize = sizeof(unsigned char) * (header.maxtris * 4); - - int totalDataSize = headerSize + vertSize + meshSize + trisSize; - - if (dataSize < totalDataSize) - return false; - - // This needs to be set early or the error handling won't work. - resultMesh->resourcetype = NMG_ALLOC_TYPE_LOCAL; - - resultMesh->meshes = (unsigned int*)rcAlloc(meshSize, RC_ALLOC_PERM); - if (!resultMesh->meshes) - { - rcpdFreeMeshData(resultMesh); - return false; - } - - resultMesh->tris = (unsigned char*)rcAlloc(trisSize, RC_ALLOC_PERM); - if (!resultMesh->tris) - { - rcpdFreeMeshData(resultMesh); - return false; - } - - resultMesh->verts = (float*)rcAlloc(vertSize, RC_ALLOC_PERM); - if (!resultMesh->verts) - { - rcpdFreeMeshData(resultMesh); - return false; - } - - // Populate the mesh. - - memcpy(&resultMesh->nmeshes, &header, headerSize - sizeof(long)); - - int pos = headerSize; - memcpy(resultMesh->meshes, &meshData[pos], meshSize); - pos += meshSize; - - memcpy(resultMesh->tris, &meshData[pos], trisSize); - pos += trisSize; - - memcpy(resultMesh->verts, &meshData[pos], vertSize); - - return true; - } - - EXPORT_API bool rcpdFlattenMesh(rcPolyMeshDetail* detailMesh - , float* verts - , int* vertCount - , int vertsSize - , int* tris - , int* triCount - , int trisSize) - { - /* - * Remember: The detailMesh->tris array has a stride of 4 - * (3 indices + flags) - * - * The detail meshes are completely independent, which results - * in duplicate verts. The flattening process will remove - * the duplicates. - */ - - if (!detailMesh - || !verts - || !vertCount - || !tris - || !triCount - || trisSize < detailMesh->ntris) - { - return false; - } - - float* uniqueVerts = new float[(detailMesh->nverts)*3]; - int* vertMap = new int[detailMesh->nverts]; - - int resultVertCount = removeDuplicateVerts(detailMesh->nverts - , detailMesh->verts - , uniqueVerts - , vertMap); - - if (vertsSize < resultVertCount) - return false; - - memcpy(verts, &uniqueVerts[0], sizeof(float) * resultVertCount * 3); - - delete [] uniqueVerts; - - // Flatten and re-map the indices. - int pCurrentTri = 0; - for (int iMesh = 0; iMesh < detailMesh->nmeshes; iMesh++) - { - int vBase = detailMesh->meshes[iMesh*4+0]; - int tBase = detailMesh->meshes[iMesh*4+2]; - int tCount = detailMesh->meshes[iMesh*4+3]; - for (int iTri = 0; iTri < tCount; iTri++) - { - const unsigned char* tri = &detailMesh->tris[(tBase+iTri)*4]; - for (int i = 0; i < 3; i++) - { - tris[pCurrentTri] = vertMap[vBase+tri[i]]; - pCurrentTri++; - } - } - } - - delete [] vertMap; - - *vertCount = resultVertCount; - *triCount = detailMesh->ntris; - - return true; - } - - EXPORT_API bool rcpdBuildPolyMeshDetail(nmgBuildContext* ctx - , const rcPolyMesh* mesh - , const rcCompactHeightfield* chf - , const float sampleDist - , const float sampleMaxError - , nmgPolyMeshDetail* dmesh) - { - if (!ctx || !mesh || !chf || !dmesh) - return false; - - if (rcBuildPolyMeshDetail(ctx - , *mesh - , *chf - , sampleDist - , sampleMaxError - , *dmesh)) - { - dmesh->maxverts = dmesh->nverts; - dmesh->maxtris = dmesh->ntris; - dmesh->maxmeshes = dmesh->nmeshes; - dmesh->resourcetype = NMG_ALLOC_TYPE_LOCAL; - return true; - } - - return false; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/47/471dba99e3c1106b709abdf99fa2f21bc58af550.svn-base b/critterai/.svn/pristine/47/471dba99e3c1106b709abdf99fa2f21bc58af550.svn-base deleted file mode 100644 index 5b7ec409..00000000 --- a/critterai/.svn/pristine/47/471dba99e3c1106b709abdf99fa2f21bc58af550.svn-base +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.nmgen; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(AreaFlagDef))] -public sealed class AreaFlagDefEditor - : Editor -{ - private string[] mFlagNames; - private CAINavEditorSettingsEditor.AreaGUIControl mAreaControl; - - private byte mAddSelection = NMGen.MaxArea; - - void OnEnable() - { - mAreaControl = CAINavEditorSettingsEditor.CreateAreaControl(""); - mFlagNames = CAINavEditorSettingsEditor.GetFlagNames(); - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - AreaFlagDef targ = (AreaFlagDef)target; - - // Has someone done something naughty? - - if (targ.areas == null || targ.areas == null || targ.areas.Count != targ.flags.Count) - { - Debug.LogError("Data null reference or size mismatch. Resetting component.", targ); - targ.areas = new List(); - targ.flags = new List(); - } - - List areas = targ.areas; - List flags = targ.flags; - - EditorGUILayout.Separator(); - - targ.SetPriority(EditorGUILayout.IntField("Priority", targ.Priority)); - - EditorGUILayout.Separator(); - - GUILayout.Label("Area / Flags"); - - EditorGUILayout.Separator(); - - if (areas.Count > 0) - { - EditorGUILayout.BeginVertical(); - - int delChoice = -1; - - for (int i = 0; i < areas.Count; i++) - { - EditorGUILayout.BeginHorizontal(); - - // Note: Duplicates are a waste, but technically ok. - - areas[i] = mAreaControl.OnGUI(areas[i]); - flags[i] = EditorGUILayout.MaskField(flags[i], mFlagNames); - - if (GUILayout.Button("X", GUILayout.Width(30))) - delChoice = i; - - EditorGUILayout.EndHorizontal(); - } - - if (delChoice >= 0) - { - flags.RemoveAt(delChoice); - areas.RemoveAt(delChoice); - } - - EditorGUILayout.EndVertical(); - } - - EditorGUILayout.BeginVertical(); - EditorGUILayout.Separator(); - - EditorGUILayout.BeginHorizontal(); - - mAddSelection = mAreaControl.OnGUI(mAddSelection); - - if (GUILayout.Button("Add")) - { - areas.Add(mAddSelection); - flags.Add(org.critterai.nmbuild.NMBuild.DefaultFlag); - GUI.changed = true; - } - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.EndVertical(); - - EditorGUILayout.Separator(); - - GUILayout.Box("Input Build Processor\n\nAdds an NMGen processor that adds flags to" - + " polygons based on area assignment. E.g. Add the 'swim' flag to all 'water'" - + " polygons." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Compiler : Area Flag Def" - , false, NMBEditorUtil.CompilerGroup)] - static void CreateAsset() - { - AreaFlagDef item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/47/4738f3a7f6ebb355f1d8115b065f6e2b1232079f.svn-base b/critterai/.svn/pristine/47/4738f3a7f6ebb355f1d8115b065f6e2b1232079f.svn-base deleted file mode 100644 index e2f9b4f7..00000000 --- a/critterai/.svn/pristine/47/4738f3a7f6ebb355f1d8115b065f6e2b1232079f.svn-base +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using org.critterai.nav; -using org.critterai.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(CAINavEditorSettings))] -public sealed class CAINavEditorSettingsEditor - : Editor -{ - /// - /// A control GUI suitable for selecting an area based on its well known name. - /// - public class AreaGUIControl - { - private List mNamesAll = new List(Navmesh.MaxArea + 1); - private string[] mNamesShort; - private string mLabel; - - internal AreaGUIControl(string label, string[] areaNames) - { - mLabel = label; - - for (int i = 0; i < areaNames.Length; i++) - { - if (areaNames[i] != CAINavEditorSettings.Undefined) - mNamesAll.Add(areaNames[i]); - } - - mNamesAll.Add(CAINavEditorSettings.Undefined); - - mNamesShort = mNamesAll.ToArray(); - - mNamesAll.Clear(); - - mNamesAll.AddRange(areaNames); - } - - /// - /// Displays the area selector. - /// - /// The current area. - /// The selected area. - public byte OnGUI(byte currentArea) - { - return OnGUI(mLabel, currentArea); - } - - /// - /// Displays the area selector with a custom label. - /// - /// The custom label. - /// The current area. - /// The selected area. - public byte OnGUI(string labelOverride, byte currentArea) - { - string name = mNamesAll[currentArea]; - - int undef = mNamesShort.Length - 1; - - int i = undef; - for (;i >= 0; i--) - { - if (name == mNamesShort[i]) - break; - } - - if (i == undef) - mNamesShort[undef] = currentArea + " " + mNamesShort[undef]; - - int ni = EditorGUILayout.Popup(labelOverride, i, mNamesShort); - - mNamesShort[undef] = CAINavEditorSettings.Undefined; - - if (i == ni || ni == undef) - return currentArea; - - return (byte)mNamesAll.IndexOf(mNamesShort[ni]); - } - } - - private const string AddAreaName = "AddArea"; - - private static bool mShowAreas = true; - private static bool mShowFlags = true; - private static bool mShowAvoidance = true; - - private static byte mNewArea = Navmesh.NullArea; - private static bool mFocusNew = false; - - /// - /// Creates a control useful for assigning area values. - /// - /// The default label for the control. - /// - public static AreaGUIControl CreateAreaControl(string label) - { - CAINavEditorSettings settings = EditorUtil.GetGlobalAsset(); - return new AreaGUIControl(label, (string[])settings.areaNames.Clone()); - } - - /// - /// Gets a clone of the global well know flag names. - /// - /// A clone of the flag names. - public static string[] GetFlagNames() - { - CAINavEditorSettings settings = EditorUtil.GetGlobalAsset(); - return (string[])settings.flagNames.Clone(); - } - - /// - /// Gets a clone of the global well known avoidance type names. - /// - /// A clone of the well known avoidance type names. - public static string[] GetAvoidanceNames() - { - CAINavEditorSettings settings = EditorUtil.GetGlobalAsset(); - return (string[])settings.avoidanceNames.Clone(); - } - - void OnEnable() - { - mNewArea = NextUndefinedArea(); - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - EditorGUIUtility.LookLikeControls(80); - - EditorGUILayout.Separator(); - - mShowAreas = EditorGUILayout.Foldout(mShowAreas, "Area Names"); - - if (mShowAreas) - OnGUIAreas(); - - EditorGUILayout.Separator(); - - mShowFlags = EditorGUILayout.Foldout(mShowFlags, "Flag Names"); - - if (mShowFlags) - OnGUIFlags(); - - EditorGUILayout.Separator(); - - mShowAvoidance = EditorGUILayout.Foldout(mShowAvoidance, "Crowd Avoidance Names"); - - if (mShowAvoidance) - OnGUIAvoidance(); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - private byte NextUndefinedArea() - { - CAINavEditorSettings targ = (CAINavEditorSettings)target; - - string[] areaNames = targ.areaNames; - - for (int i = 1; i < areaNames.Length; i++) - { - if (areaNames[i] == CAINavEditorSettings.Undefined) - return (byte)i; - } - - return 0; - } - - private void OnGUIAreas() - { - CAINavEditorSettings targ = (CAINavEditorSettings)target; - - string[] areaNames = targ.areaNames; - - EditorGUILayout.Separator(); - - for (int i = 0; i < areaNames.Length; i++) - { - if (areaNames[i] == CAINavEditorSettings.Undefined) - continue; - - EditorGUILayout.BeginHorizontal(); - - GUI.enabled = (i != Navmesh.NullArea); - - string areaName = EditorGUILayout.TextField(i.ToString(), areaNames[i]); - - // Note: Extra checks reduce the need to run the last check, which is more expensive. - if (areaName.Length > 0 - && areaName != areaNames[i] - && areaName != CAINavEditorSettings.NotWalkable // Quick check. - && areaName != CAINavEditorSettings.Undefined // This check is important. - && targ.GetArea(areaName) == CAINavEditorSettings.UnknownArea) - { - areaNames[i] = areaName; - } - - GUI.enabled = !(i == Navmesh.NullArea || i == Navmesh.MaxArea); - - if (GUILayout.Button("X", GUILayout.Width(30))) - { - areaNames[i] = CAINavEditorSettings.Undefined; - - mNewArea = NextUndefinedArea(); - mFocusNew = true; // Prevents off GUI behavior. - - GUI.changed = true; - } - - GUI.enabled = true; - - EditorGUILayout.EndHorizontal(); - } - - EditorGUILayout.Separator(); - - EditorGUILayout.BeginHorizontal(); - - GUI.SetNextControlName(AddAreaName); - mNewArea = NavUtil.ClampArea(EditorGUILayout.IntField(mNewArea, GUILayout.Width(80))); - if (mFocusNew) - { - GUI.FocusControl(AddAreaName); - mFocusNew = false; - } - - GUI.enabled = (areaNames[mNewArea] == CAINavEditorSettings.Undefined); - - if (GUILayout.Button("Add", GUILayout.Width(80))) - { - areaNames[mNewArea] = "Area " + mNewArea; - mNewArea = NextUndefinedArea(); - mFocusNew = true; - GUI.changed = true; - } - - GUI.enabled = true; - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.Separator(); - - EditorGUILayout.LabelField("Maximum allowed area: " + Navmesh.MaxArea - , EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - } - - private void OnGUIFlags() - { - CAINavEditorSettings targ = (CAINavEditorSettings)target; - - string[] names = targ.flagNames; - - EditorGUILayout.Separator(); - - for (int i = 0; i < names.Length; i++) - { - string val = EditorGUILayout.TextField(string.Format("0x{0:X}", 1 << i), names[i]); - names[i] = (val.Length == 0 ? names[i] : val); - } - } - - private void OnGUIAvoidance() - { - CAINavEditorSettings targ = (CAINavEditorSettings)target; - - string[] names = targ.avoidanceNames; - - EditorGUILayout.Separator(); - - for (int i = 0; i < names.Length; i++) - { - string val = EditorGUILayout.TextField(i.ToString(), names[i]); - names[i] = (val.Length == 0 ? names[i] : val); - } - } - - [MenuItem(EditorUtil.MainMenu + "Nav Editor Settings", false, EditorUtil.GlobalGroup)] - static void EditSettings() - { - CAINavEditorSettings item = EditorUtil.GetGlobalAsset(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/47/473bc7105ec8a013486a4d02b5109af2283f36a8.svn-base b/critterai/.svn/pristine/47/473bc7105ec8a013486a4d02b5109af2283f36a8.svn-base deleted file mode 100644 index c605186c..00000000 --- a/critterai/.svn/pristine/47/473bc7105ec8a013486a4d02b5109af2283f36a8.svn-base +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.interop; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen.rcn -{ - [StructLayout(LayoutKind.Sequential)] - internal struct PolyMeshEx - { - /* - * Design notes: - * - * Must be structure so it can be passed across interop boundary - * in an array. - * - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpmBuildSerializedData([In] byte[] meshData - , int dataSize - , ref PolyMeshEx polyMesh - , ref int maxVerts - , ref float walkableHeight - , ref float walkableRadius - , ref float walkableStep); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpmFreeMeshData(ref PolyMeshEx polyMesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpmGetSerializedData(ref PolyMeshEx polyMesh - , int maxVerts - , float walkableHeight - , float waklableRadius - , float walkableStep - , bool includeBuffer - , ref IntPtr data - , ref int dataSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpmBuildFromContourSet(IntPtr context - , [In] ContourSetEx cset - , int maxVertsPerPoly - , ref PolyMeshEx polyMesh - , ref int maxVerts); - - /// - /// ushort buffer - /// - public IntPtr verts; - - /// - /// ushort buffer - /// - public IntPtr polys; - - /// - /// ushort buffer - /// - public IntPtr regions; - - /// - /// ushort buffer - /// - public IntPtr flags; - - /// - /// byte buffer - /// - public IntPtr areas; - - public int vertCount; - public int polyCount; - - public int maxPolys; - - public int maxVertsPerPoly; - - public Vector3 boundsMin; - public Vector3 boundsMax; - public float xzCellSize; - public float yCellSize; - public int borderSize; - - public void Reset() - { - verts = IntPtr.Zero; - polys = IntPtr.Zero; - regions = IntPtr.Zero; - areas = IntPtr.Zero; - vertCount = 0; - polyCount = 0; - maxPolys = 0; - maxVertsPerPoly = 0; - boundsMin = Vector3Util.Zero; - boundsMax = Vector3Util.Zero; - xzCellSize = 0; - yCellSize = 0; - borderSize = 0; - } - } -} diff --git a/critterai/.svn/pristine/48/484c4e9af0aa6dd7b2724a890e496c317e6312b1.svn-base b/critterai/.svn/pristine/48/484c4e9af0aa6dd7b2724a890e496c317e6312b1.svn-base deleted file mode 100644 index 74cba4d4..00000000 Binary files a/critterai/.svn/pristine/48/484c4e9af0aa6dd7b2724a890e496c317e6312b1.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/48/48627cad89a7c70e445b1cc3a837ed56725c4af2.svn-base b/critterai/.svn/pristine/48/48627cad89a7c70e445b1cc3a837ed56725c4af2.svn-base deleted file mode 100644 index 0710032e..00000000 --- a/critterai/.svn/pristine/48/48627cad89a7c70e445b1cc3a837ed56725c4af2.svn-base +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.nav; -using org.critterai.nav.u3d; - -/// -/// Navigation mesh data that is baked at design time. -/// -[System.Serializable] -public sealed class CAIBakedNavmesh - : ScriptableObject, INavmeshData -{ - [SerializeField] - private byte[] mDataPack = null; - - [SerializeField] - private NavmeshBuildInfo mBuildInfo; - - [SerializeField] - private int mVersion; - - /// - /// Information related to the build of the mesh data. - /// - /// - /// - /// This information is used by the build system to perform partial re-builds and provide - /// helpful information to the user. - /// - /// - /// Partial re-build features will not be available if this property is null. - /// - /// - public NavmeshBuildInfo BuildInfo { get { return mBuildInfo.Clone(); } } - - /// - /// True if the navigation mesh is available. - /// - /// True if the navigation mesh is available. - public bool HasNavmesh - { - get { return (mDataPack != null && mDataPack.Length > 0); } - } - - /// - /// The version of the data. - /// - /// - /// - /// This is used to track changes to the mesh data. It is incremented every time new data is - /// loaded. - /// - /// - public int Version { get { return mVersion; } } - - /// - /// Creates a new object from the mesh data - /// - /// A new object. Or null if the mesh is not available. - public Navmesh GetNavmesh() - { - if (!HasNavmesh) - return null; - - Navmesh result; - if (NavUtil.Failed(Navmesh.Create(mDataPack, out result))) - return null; - - return result; - } - - /// - /// Generates a human readable report of the mesh data. - /// - /// A human readable report of the mesh data. - public string GetMeshReport() - { - if (!HasNavmesh) - return "No mesh."; - - Navmesh nm = GetNavmesh(); - - NavmeshParams nmconfig = nm.GetConfig(); - - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - - sb.AppendLine("Navigation mesh report for " + name); - - if (mBuildInfo != null) - sb.AppendLine("Built from scene: " + mBuildInfo.inputScene); - - sb.AppendLine(string.Format("Tiles: {0}, Tile Size: {1:F3}x{2:F3}, Max Polys Per Tile: {3}" - , nmconfig.maxTiles, nmconfig.tileWidth, nmconfig.tileDepth, nmconfig.maxPolysPerTile)); - - int polyCount = 0; - int vertCount = 0; - int connCount = 0; - - for (int i = 0; i < nmconfig.maxTiles; i++) - { - NavmeshTileHeader header = nm.GetTile(i).GetHeader(); - - if (header.polyCount == 0) - continue; - - sb.AppendLine(string.Format( - "Tile ({0},{1}): Polygons: {2}, Vertices: {3}, Off-mesh Connections: {4}" - , header.tileX, header.tileZ - , header.polyCount, header.vertCount - , header.connCount)); - - polyCount += header.polyCount; - vertCount += header.vertCount; - connCount += header.connCount; - } - - sb.AppendLine(string.Format( - "Totals: Polygons: {0}, Vertices: {1}, Off-mesh Connections: {2}" - , polyCount, vertCount, connCount)); - - return sb.ToString(); - } - - /// - /// Loads a single-tile navigation mesh from the provided data. - /// - /// The tile build data. - /// The build information. (Optional) - /// The flags for the operation. - public NavStatus Load(NavmeshTileBuildData buildData, NavmeshBuildInfo buildConfig) - { - if (buildData == null || buildData.IsDisposed) - return NavStatus.Failure | NavStatus.InvalidParam; - - Navmesh navmesh; - NavStatus status = Navmesh.Create(buildData, out navmesh); - - if ((status & NavStatus.Sucess) == 0) - return status; - - mDataPack = navmesh.GetSerializedMesh(); - - if (mDataPack == null) - return NavStatus.Failure; - - mBuildInfo = buildConfig; - - mVersion++; - - return NavStatus.Sucess; - } - - /// - /// Loads a navigation mesh. - /// - /// The mesh configuration. - /// The tiles to add to the mesh. - /// The build information. (Optional) - /// The flags for the operation. - public NavStatus Load(NavmeshParams config - , NavmeshTileData[] tiles - , NavmeshBuildInfo buildConfig) - { - if (config == null || tiles == null || tiles.Length > config.maxTiles) - return NavStatus.Failure | NavStatus.InvalidParam; - - Navmesh navmesh; - NavStatus status = Navmesh.Create(config, out navmesh); - - if ((status & NavStatus.Sucess) == 0) - return status; - - foreach (NavmeshTileData tile in tiles) - { - if (tile == null) - continue; - - uint trash; - status = navmesh.AddTile(tile, Navmesh.NullTile, out trash); - - if ((status & NavStatus.Sucess) == 0) - return status | NavStatus.InvalidParam; - } - - mDataPack = navmesh.GetSerializedMesh(); - - if (mDataPack == null) - return NavStatus.Failure; - - mBuildInfo = buildConfig; - - mVersion++; - - return NavStatus.Sucess; - } - - /// - /// Load a navigation mesh from data created from the - /// method. - /// - /// The serialized mesh. - /// The build information. (Optional) - /// The flags for the operation. - public NavStatus Load(byte[] serializedMesh, NavmeshBuildInfo buildConfig) - { - if (serializedMesh == null) - return NavStatus.Failure | NavStatus.InvalidParam; - - // This roundabout method is used for validation. - - Navmesh navmesh; - NavStatus status = Navmesh.Create(serializedMesh, out navmesh); - - if ((status & NavStatus.Sucess) == 0) - return status; - - mDataPack = navmesh.GetSerializedMesh(); - - if (mDataPack == null) - return NavStatus.Failure; - - mBuildInfo = buildConfig; - - mVersion++; - - return NavStatus.Sucess; - } -} diff --git a/critterai/.svn/pristine/49/49d25a9f1da5cfa66c1d166f5cd1522a379ce8e7.svn-base b/critterai/.svn/pristine/49/49d25a9f1da5cfa66c1d166f5cd1522a379ce8e7.svn-base deleted file mode 100644 index 371d4a77..00000000 Binary files a/critterai/.svn/pristine/49/49d25a9f1da5cfa66c1d166f5cd1522a379ce8e7.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/4a/4a50e570cef836db9e7a0988e25836e39a8559a8.svn-base b/critterai/.svn/pristine/4a/4a50e570cef836db9e7a0988e25836e39a8559a8.svn-base deleted file mode 100644 index f8e64790..00000000 --- a/critterai/.svn/pristine/4a/4a50e570cef836db9e7a0988e25836e39a8559a8.svn-base +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" - -void nmgTransferMessages(const nmgBuildContext* context - , unsigned char* messageBuffer - , int messageBufferSize) -{ - if (context && context->getMessageCount() > 0) - { - int size = (messageBufferSize < context->getMessagePoolLength() - ? messageBufferSize : context->getMessagePoolLength()); - memcpy(messageBuffer, context->getMessagePool(), size); - } -} - -nmgBuildContext::nmgBuildContext() - : rcContext(false), mMessageCount(0), mTextPoolSize(0) -{ - m_logEnabled = true; -} - -nmgBuildContext::~nmgBuildContext() -{ -} - -void nmgBuildContext::doResetLog() -{ - mMessageCount = 0; - mTextPoolSize = 0; -} - -void nmgBuildContext::doLog(const rcLogCategory category - , const char* message - , const int messageLength) -{ - // Design Note: The category is ignored. - - // Process early exits. - if (!getLogEnabled() - || messageLength == 0 - || mMessageCount >= MAX_MESSAGES) - return; - int remainingSpace = MESSAGE_POOL_SIZE - mTextPoolSize; - if (remainingSpace < 1) - return; - - // Store message - const int realLength = rcMin(messageLength+1, remainingSpace-1); - char* pEntry = &mTextPool[mTextPoolSize]; - memcpy(pEntry, message, realLength); - pEntry[realLength-1] = '\0'; - mTextPoolSize += realLength; - mMessages[mMessageCount++] = pEntry; -} - -int nmgBuildContext::getMessageCount() const -{ - return mMessageCount; -} - -const char* nmgBuildContext::getMessage(const int i) const -{ - return mMessages[i]; -} - -int nmgBuildContext::getMessagePoolLength() const { return mTextPoolSize; } -const char* nmgBuildContext::getMessagePool() const { return mTextPool; } - -extern "C" -{ - EXPORT_API nmgBuildContext* nmbcAllocateContext(bool logEnabled) - { - nmgBuildContext* context = new nmgBuildContext(); - context->enableLog(logEnabled); - return context; - } - - EXPORT_API void nmbcFreeContext(nmgBuildContext* context) - { - if (context) - delete context; - } - - EXPORT_API void nmbcEnableLog(nmgBuildContext* context, bool state) - { - if (context) - context->enableLog(state); - } - - EXPORT_API bool nmbcGetLogEnabled(nmgBuildContext* context) - { - if (context) - return context->getLogEnabled(); - return false; - } - - EXPORT_API void nmbcResetLog(nmgBuildContext* context) - { - if (context) - context->resetLog(); - } - - EXPORT_API int nmbcGetMessageCount(const nmgBuildContext* context) - { - if (!context) - return 0; - - return context->getMessageCount(); - } - - EXPORT_API int nmbcGetMessagePool(nmgBuildContext* context - , unsigned char* messageBuffer - , const int bufferSize) - { - if (!context) - return 0; - nmgTransferMessages(context, messageBuffer, bufferSize); - return context->getMessageCount(); - } - - EXPORT_API void nmbcLog(nmgBuildContext* context - , const char* message) - { - if (context && message) - context->log(RC_LOG_PROGRESS, message); - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/4a/4a5ba844c89694f426cd53bbe01578ce9e31fce5.svn-base b/critterai/.svn/pristine/4a/4a5ba844c89694f426cd53bbe01578ce9e31fce5.svn-base deleted file mode 100644 index 0c55e65d..00000000 --- a/critterai/.svn/pristine/4a/4a5ba844c89694f426cd53bbe01578ce9e31fce5.svn-base +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using System.Collections.Generic; -using org.critterai.geom; -using org.critterai.interop; -using org.critterai.nmgen.rcn; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// A heightfield representing obstructed space. - /// - /// - /// - /// When used in the context of a heighfield, the term voxel refers to an area - /// in width, in depth, - /// and in height. - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class Heightfield - : IManagedObject - { - /* - * Design notes: - * - * I ran into complications with implementing this class with a data - * layout matching the native structure. The cause appears to be the - * pointer to a pointer field in the native structure. So I switched - * to the root pattern with some duplication of data on this size - * of the boundary for performance reasons. - * - * The AddSpan method is not supported yet because of a bug in Recast. - * http://code.google.com/p/recastnavigation/issues/detail?id=167 - * - */ - - private int mWidth = 0; - private int mDepth = 0; - - private Vector3 mBoundsMin; - private Vector3 mBoundsMax; - - private float mXZCellSize = 0; - private float mYCellSize = 0; - - internal IntPtr root; - - /// - /// The width of the heightfield. (Along the x-axis in cell units.) - /// - public int Width { get { return mWidth; } } - - /// - /// The depth of the heighfield. (Along the z-axis in cell units.) - /// - public int Depth { get { return mDepth; } } - - /// - /// The minimum bounds of the heightfield in world space. - /// - /// The minimum bounds of the heighfield. - public Vector3 BoundsMin { get { return mBoundsMin; } } - - /// - /// The maximum bounds of the heightfield in world space. - /// - /// The maximum bounds of the heightfield. - public Vector3 BoundsMax { get { return mBoundsMax; } } - - /// - /// The width/depth size of each cell. (On the xz-plane.) - /// - /// - /// - /// The smallest span can be - /// (XZCellSize width * XZCellSize depth * YCellSize height). - /// - /// - /// A width or depth value within the field can be converted to world units as follows: - /// - /// - /// boundsMin[0] + (width * XZCellSize) - /// boundsMin[2] + (depth * XZCellSize) - /// - /// - public float XZCellSize { get { return mXZCellSize; } } - - /// - /// The height increments for span data. (On the y-axis.) - /// - /// - /// - /// The smallest span can be - /// (XZCellSize width * XZCellSize depth * YCellSize height). - /// - /// - /// A height within the field is converted to world units as follows: - /// - /// - /// boundsMin[1] + (height * YCellSize) - /// - /// - public float YCellSize { get { return mYCellSize; } } - - /// - /// The type of unmanaged resources within the object. - /// - public AllocType ResourceType { get { return AllocType.External; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return root == IntPtr.Zero; } } - - private Heightfield(IntPtr root - , int width, int depth - , Vector3 boundsMin, Vector3 boundsMax - , float xzCellSize, float yCellSize) - { - this.root = root; - mWidth = width; - mDepth = depth; - mBoundsMin = boundsMin; - mBoundsMax = boundsMax; - mYCellSize = yCellSize; - mXZCellSize = xzCellSize; - } - - /// - /// Destructor - /// - ~Heightfield() - { - RequestDisposal(); - } - - /// - /// Creates a new heightfield object. - /// - /// The width of the field. [Limit: >= 1] [Units: Cells] - /// The depth of the field. [Limit: >= 1] [Units: Cells] - /// The minimum bounds of the field's AABB. [Units: World] - /// The maximum bounds of the field's AABB. [Units: World] - /// - /// The xz-plane cell size. [Limit:>= ] [Units: World] - /// - /// - /// The y-axis span increments. [Limit:>= ] [Units: World] - /// - /// The heightfield, or null on error. - public static Heightfield Create(int width, int depth - , Vector3 boundsMin, Vector3 boundsMax - , float xzCellSize, float yCellSize) - { - if (width < 1 || depth < 1 - || !TriangleMesh.IsBoundsValid(boundsMin, boundsMax) - || xzCellSize < NMGen.MinCellSize - || yCellSize < NMGen.MinCellSize) - { - return null; - } - - IntPtr root = HeightfieldEx.nmhfAllocField(width, depth - , ref boundsMin, ref boundsMax, xzCellSize, yCellSize); - - if (root == IntPtr.Zero) - return null; - - return new Heightfield(root - , width, depth - , boundsMin, boundsMax - , xzCellSize, yCellSize); - } - - /// - /// Frees all resources and marks object as disposed. - /// - public void RequestDisposal() - { - if (!IsDisposed) - { - HeightfieldEx.nmhfFreeField(root); - root = IntPtr.Zero; - mWidth = 0; - mDepth = 0; - mXZCellSize = 0; - mYCellSize = 0; - mBoundsMin = Vector3Util.Zero; - mBoundsMax = Vector3Util.Zero; - } - } - - /// - /// The number of spans in the field. - /// - /// - /// - /// This is a non-trivial method call. Cache the result when possible. - /// - /// - /// The number of spans in the field. - public int GetSpanCount() - { - if (IsDisposed) - return 0; - return HeightfieldEx.nmhfGetHeightFieldSpanCount(root); - } - - /// - /// Gets an buffer that is sized to fit the maximum number of spans within a column of - /// the field. - /// - /// A buffer that is sized to fit the maximum spans within a column. - public HeightfieldSpan[] GetSpanBuffer() - { - if (IsDisposed) - return null; - - int size = HeightfieldEx.nmhfGetMaxSpansInColumn(root); - return new HeightfieldSpan[size]; - } - - /// - /// Gets the spans within the specified column. - /// - /// - /// - /// The spans will be ordered from lowest height to highest. - /// - /// - /// The method can be used to get a properly sized buffer. - /// - /// - /// - /// The width index. [Limits: 0 <= value < ] - /// - /// - /// The depth index. [Limits: 0 <= value < ] - /// - /// - /// The buffer to load the result into. [Size: Maximum spans in a column] - /// - /// The number of spans returned. - public int GetSpans(int widthIndex - , int depthIndex - , HeightfieldSpan[] buffer) - { - if (IsDisposed) - return -1; - - return HeightfieldEx.nmhfGetSpans(root - , widthIndex - , depthIndex - , buffer - , buffer.Length); - } - - /// - /// Marks non-walkable spans as walkable if their maximum is within walkableStep of a - /// walkable neighbor. - /// - /// - /// - /// Example of test: Math.Abs(currentSpan.Max - neighborSpan.Max) < walkableStep - /// - /// Allows the formation of walkable regions that will flow over low lying objects such - /// as curbs, and up structures such as stairways. - /// - /// - /// The context to use for the operation - /// - /// The maximum allowed difference between span maximum's for the step to be considered - /// waklable. [Limit: > 0] - /// - /// True if the operation was successful. - public bool MarkLowObstaclesWalkable(BuildContext context, int walkableStep) - { - if (IsDisposed) - return false; - - return HeightfieldEx.nmhfFilterLowHangingWalkableObstacles(context.root - , walkableStep - , root); - } - - /// - /// Marks spans that are ledges as not-walkable. - /// - /// - /// - /// A ledge is a span with a neighbor whose maximum is farther away than walkableStep. - /// Example: Math.Abs(currentSpan.Max - neighborSpan.Max) > walkableStep - /// - /// - /// This method removes the impact of the overestimation of conservative voxelization so - /// the resulting mesh will not have regions hanging in the air over ledges. - /// - /// - /// The context to use for the operation - /// - /// The maximum floor to ceiling height that is considered still walkable. - /// [Limit: > ] - /// - /// - /// The maximum allowed difference between span maximum's for the step to be considered - /// walkable. [Limit: > 0] - /// - /// True if the operation was successful. - public bool MarkLedgeSpansNotWalkable(BuildContext context - , int walkableHeight, int walkableStep) - { - if (IsDisposed) - return false; - - return HeightfieldEx.nmhfFilterLedgeSpans(context.root - , walkableHeight - , walkableStep - , root); - } - - /// - /// Marks walkable spans as not walkable if the clearence above the span is less than the - /// specified height. - /// - /// - /// - /// For this method, the clearance above the span is the distance from the span's maximum - /// to the next higher span's minimum. (Same column.) - /// - /// - /// The context to use for the operation - /// - /// The maximum allowed floor to ceiling height that is considered still walkable. - /// [Limit: > ] - /// - /// True if the operation was successful. - public bool MarkLowHeightSpansNotWalkable(BuildContext context, int walkableHeight) - { - if (IsDisposed) - return false; - - return HeightfieldEx.nmhfFilterWalkableLowHeightSpans(context.root - , walkableHeight - , root); - } - - /// - /// Voxelizes a triangle into the heightfield. - /// - /// The context to use for the operation - /// The triangle vertices. [(vertA, vertB, vertC)] - /// - /// The id of the area the triangle belongs to. [Limit: <= ] - /// - /// - /// The distance where the walkable flag is favored over the non-walkable flag. - /// [Limit: >= 0] [Normal: 1] - /// - /// True if the operation was successful. - public bool AddTriangle(BuildContext context - , Vector3[] verts, byte area, int flagMergeThreshold) - { - if (IsDisposed) - return false; - - return HeightfieldEx.nmhfRasterizeTriangle(context.root - , verts - , area - , root - , flagMergeThreshold); - } - - /// - /// Voxelizes the triangles in the provided mesh into the heightfield. - /// - /// The context to use for the operation - /// The triangle mesh. - /// - /// The ids of the areas the triangles belong to. - /// [Limit: <= ] [Size: >= mesh.triCount] - /// - /// - /// The distance where the walkable flag is favored over the non-walkable flag. - /// [Limit: >= 0] [Normal: 1] - /// - /// True if the operation was successful. - public bool AddTriangles(BuildContext context, TriangleMesh mesh, byte[] areas - , int flagMergeThreshold) - { - if (IsDisposed) - return false; - - return HeightfieldEx.nmhfRasterizeTriMesh(context.root - , mesh.verts - , mesh.vertCount - , mesh.tris - , areas - , mesh.triCount - , root - , flagMergeThreshold); - } - - /// - /// Voxelizes the triangles from the provided into the - /// heightfield. - /// - /// - /// - /// The chunks that are voxelized is controled by the bounds parameters. - /// - /// - /// The build context. - /// The mesh. - /// The minimum bounds for the mesh query. - /// The maximum bounds for the mesh query. - /// - /// The distance where the walkable flag is favored over the non-walkable flag. - /// [Limit: >= 0] [Normal: 1] - /// - /// True if the operation was successful. - public bool AddTriangles(BuildContext context, ChunkyTriMesh mesh - , Vector3 boundsMin, Vector3 boundsMax - , int flagMergeThreshold) - { - if (IsDisposed || mesh == null || mesh.IsDisposed) - return false; - - List nodeList = new List(); - - int triCount = mesh.GetChunks(boundsMin.x, boundsMin.z - , boundsMax.x, boundsMax.z - , nodeList); - - if (triCount == 0) - return true; - - return HeightfieldEx.nmhfRasterizeNodes(context.root - , mesh.verts - , mesh.tris - , mesh.areas - , nodeList.ToArray() - , nodeList.Count - , root - , flagMergeThreshold); - } - - /// - /// Voxelizes the provided triangles into the heightfield. - /// - /// - /// - /// Unlike many other methods in the library, the arrays must be sized exactly to the - /// content. If you need to pass buffers, use the method that takes a - /// object. - /// - /// - /// The context to use for the operation - /// The vertices. [Length: >= vertCount] (No buffering allowed.) - /// - /// The triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount] - /// - /// - /// The ids of the areas the triangles belong to. - /// [Limit: <= ] [Size: >= triCount] - /// - /// - /// The distance where the walkable flag is favored over the non-walkable flag. - /// [Limit: >= 0] [Normal: 1] - /// - /// True if the operation was successful. - public bool AddTriangles(BuildContext context - , Vector3[] verts, ushort[] tris, byte[] areas - , int flagMergeThreshold) - { - if (IsDisposed) - return false; - - return HeightfieldEx.nmhfRasterizeTriMeshShort(context.root - , verts - , verts.Length / 3 - , tris - , areas - , tris.Length / 3 - , root - , flagMergeThreshold); - } - - /// - /// Voxelizes the provided triangles into the heightfield. - /// - /// The context to use for the operation - /// The triangles. [(vertA, vertB, vertC) * triCount] - /// - /// The ids of the areas the triangles belong to. - /// [Limit: <= ] [Size: >= triCount] - /// - /// The number of triangles in the vertex array. - /// - /// The distance where the walkable flag is favored over the non-walkable flag. - /// [Limit: >= 0] [Normal: 1] - /// - /// True if the operation was successful. - public bool AddTriangles(BuildContext context - , Vector3[] verts, byte[] areas, int triCount - , int flagMergeThreshold) - { - if (IsDisposed) - return false; - - return HeightfieldEx.nmhfRasterizeTriangles(context.root - , verts, areas, triCount - , root - , flagMergeThreshold); - } - } -} diff --git a/critterai/.svn/pristine/4a/4a7653edf6966073083a1454d31f64e121bc529e.svn-base b/critterai/.svn/pristine/4a/4a7653edf6966073083a1454d31f64e121bc529e.svn-base deleted file mode 100644 index ed0035c5..00000000 --- a/critterai/.svn/pristine/4a/4a7653edf6966073083a1454d31f64e121bc529e.svn-base +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// The context for an input build. (Editor Only) - /// - public class InputBuildContext - : UnityBuildContext - { - private readonly ISceneQuery mSceneQuery; - - private readonly InputBuildOption mOptions; - - /// - /// The components included in the input build. - /// - public readonly List components = new List(); - - /// - /// The area associated with each component in . - /// - public readonly List areas = new List(); - - /// - /// The processors to run during the NMGen build. - /// - public readonly List processors = new List(); - - /// - /// The connection compiler used to add connections. - /// - public readonly ConnectionSetCompiler connCompiler = new ConnectionSetCompiler(50); - - /// - /// The geometry compiler used to add geometry. - /// - public readonly InputGeometryCompiler geomCompiler = new InputGeometryCompiler(131072, 262144); - - /// - /// Input build information. - /// - public InputBuildInfo info = new InputBuildInfo(); - - /// - /// Input build options. - /// - public InputBuildOption Options { get { return mOptions; } } - - /// - /// Construction. - /// - /// - /// - /// The scene query will be initialized during construction. - /// - /// - /// If no scene query is provided, the query scope will be all game objects in the scene. - /// - /// - /// The scene query. (Optional) - /// Build options. - public InputBuildContext(ISceneQuery sceneQuery, InputBuildOption options) - { - mOptions = options; - mSceneQuery = sceneQuery; - if (sceneQuery != null) - mSceneQuery.Initialize(); - } - - /// - /// Gets components of the specified type using the scene query. - /// - /// - /// - /// All queries are against the currently open scene. - /// - /// - /// The component type. - /// The components, or a zero length array if none are found. - public T[] GetFromScene() where T : Component - { - if (mSceneQuery == null) - return (T[])Object.FindObjectsOfType(typeof(T)); - else - return mSceneQuery.GetComponents(); - } - - /// - /// Loads all components of the specified type into the list, - /// using the scene query. - /// - /// - /// - /// All queries are against the currently open scene. - /// - /// - /// The component type. - /// The number of components loaded. - public int LoadFromScene() where T : Component - { - int result; - - T[] items = GetFromScene(); - result = items.Length; - - components.AddRange(items); - - return result; - } - - /// - /// Loads the components into the list. - /// - /// The components to load. - public void Load(Component[] items) - { - components.AddRange(items); - } - - /// - /// Loads a component into the list. - /// - /// The component to load. - public void Load(Component item) - { - components.Add(item); - } - } -} diff --git a/critterai/.svn/pristine/4a/4a7c98624cd7fd55d6acd67c54ad989711713785.svn-base b/critterai/.svn/pristine/4a/4a7c98624cd7fd55d6acd67c54ad989711713785.svn-base deleted file mode 100644 index 6c34fe23..00000000 --- a/critterai/.svn/pristine/4a/4a7c98624cd7fd55d6acd67c54ad989711713785.svn-base +++ /dev/null @@ -1,374 +0,0 @@ - - - - Debug - AnyCPU - 2.0 - {fca7a86a-dedd-4cdc-a1e5-05acca3edf76} - 1.9.0.0 - - Documentation - Documentation - Documentation - - .\alldoc\ - cai - en-US - alldoc.log - 3.5 - Website - Aggregate documentation for all CritterAI projects. - - - -&lt%3bp&gt%3bSome libraries require &lt%3ba href=&quot%3bhttp://unity3d.com/&quot%3b target=&quot%3b_blank&quot%3b&gt%3bUnity&lt%3b/a&gt%3b.&lt%3b/p&gt%3b - - - -&lt%3bp&gt%3b -&lt%3ba href=&quot%3bhttp://www.critterai.org/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bProject Home -&lt%3b/a&gt%3b&lt%3bbr /&gt%3b -&lt%3ba href=&quot%3bhttp://code.google.com/p/critterai/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bProject Source&lt%3b/a&gt%3b&lt%3bbr /&gt%3b - -&lt%3ba href=&quot%3bhttp://www.critterai.org/cailic&quot%3b target=&quot%3b_parent&quot%3b&gt%3bLicense&lt%3b/a&gt%3b -&lt%3b/p&gt%3b - - - - - - - - - - - - - Copyright %28c%29 2010-2012 Stephen A. Pratt - &lt%3ba href=&quot%3bhttp://www.critterai.org/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bProject Home&lt%3b/a&gt%3b | &lt%3ba href=&quot%3bhttp://code.google.com/p/critterai/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bSource Code&lt%3b/a&gt%3b | &lt%3ba href=&quot%3bhttp://www.critterai.org/cailic&quot%3b target=&quot%3b_parent&quot%3b&gt%3bLicense&lt%3b/a&gt%3b - CritterAI Documentation - Protected, SealedProtected - - Provides general utility features. - Provides computational geometry features. - Provides native interop utility features. - Provides core pathfinding and local steering features. - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use extensions related to navigation. (Pathfinding and local steering.) - Provides core features related to building navigation mesh data. (From source geometry.) - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use elements related to CAINav. (Navigation mesh generation, pathfinding, local steering, etc.) - Provides general <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use extentions. - Provides ease-of-use features related to building navigation meshes at design time. - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use features related to building navigation meshes at design time. - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> Editor ease-of-use extensions related to navigation. (Pathfinding and local steering.) - - HashedMemberName - True - hana - Summary, Parameter, Returns, AutoDocumentCtors, Namespace, TypeParameter, AutoDocumentDispose - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Explorer-StraightPath - Explorer - Straight Path - - - - - - - - - - - - - - - - - - - - - - - Value-MinRegionArea - Value: MinRegionArea - True - - - Heightfield-AABB - Heightfield: AABB - - - Heightfield-Columns - Heightfield: Columns - - - Heightfield-VoxelGrid - Heightfield: Voxel Grid - - - Heightfield-OpenField - Heightfield: Open Field - - - Heightfield-SolidField - Heightfield: Solid Field - - - Heightfield-SolidSpan - Heightfield: Solid Span - - - Heightfield-ColumnVoxels - Heightfield: ColumnVoxels - - - Stage-RawContour - Stage: Raw Contour - - - Stage-Regions - Stage: Regions - - - Stage-PolyMesh - Stage: Polygon Mesh - - - Stage-DetailMesh - Stage: Detail Mesh - - - Stage-OpenHeightfield - Stage: Open Heightfield - - - VoxelizedTriangle - Voxelized Triangle - - - Stage-SimplifiedContour - Stage: Simplified Contour - - - Example-AssignGeom - Example: Assign Geometry - - - Example-NMGenConfig - Example: NMGen Config - - - Example-InteriorEnvironment - Example: Interior Environment - - - Example-FinalMesh - Example: Final Mesh - - - PolyMeshDetail-Basic - Poly Mesh Detail-Basic - - - PolyMesh-Basic - Poly Mesh-Basic - - - Value-WalkableRadius - Value: WalkableRadius - True - - - Value-WalkableHeight - Value: Walkable Height - True - - - Value-WaklableStep - Value: Waklable Step - True - - - WrapDirection - Standard Wrap Direction - - - CaiNavComponents - High Level Components - - - Explorer-StraightPathLg - Explorer-Straight Path - - - Explorer-StraightPath - Explorer-Straight Path - - - CAINavDependencies - Dependencies - - - - - U3D-NavManagerOptions - U3D: NavSource Options - - - - - U3D-NavManagerStructure - U3D: NavSourceStructure - - - - - OffMeshConnection - Off Mesh Connection - - - - - NavmeshBuild-Standard - Standard Navmesh Build - - - - - NMGenBuildStandard - Standard NMGen Build - - - - - UnityNMGenMainAssets - Navmesh Build-Unity Main Assets - - - - - UnityInputBuildProcess - Unity Input Build Process - - - - - OverlappingAreaMarkers - Overlapping Area Markers - - - - - NavmeshBuildInspector - Navmesh Build Inspector - - - - - NavmeshBuildUpper - Navmesh Build Upper - - - NavmeshBuildInput - Navmesh Build Input - - - NavmeshBuildConfig - Navmesh Build Config - - - - - AdvancedBuild-Input - Advanced Build-Input - - - AdvancedBuild-Config - Advanced Build-Config - - - AdvancedBuild-Builder - Advanced Build-Builder - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/4a/4a84ceec5be9f1b9c6b0946037268355d5964e32.svn-base b/critterai/.svn/pristine/4a/4a84ceec5be9f1b9c6b0946037268355d5964e32.svn-base deleted file mode 100644 index 18402ef4..00000000 --- a/critterai/.svn/pristine/4a/4a84ceec5be9f1b9c6b0946037268355d5964e32.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nmbuild-u3d-editor")] -[assembly: AssemblyDescription("Design-time navigation mesh build extensions for the Unity Editor.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/4a/4a945cd198a13e2dc837388886368668edbcf353.svn-base b/critterai/.svn/pristine/4a/4a945cd198a13e2dc837388886368668edbcf353.svn-base deleted file mode 100644 index 267e96f1..00000000 --- a/critterai/.svn/pristine/4a/4a945cd198a13e2dc837388886368668edbcf353.svn-base +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.nav.rcn -{ - internal static class CrowdProximityGridEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern float dtpgGetCellSize(IntPtr grid); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtpgGetBounds(IntPtr grid - , [In, Out] int[] bounds); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtpgGetItemCountAt(IntPtr grid - , int x - , int y); - } -} diff --git a/critterai/.svn/pristine/4a/4acab54d724f2739a1a5a58b1b045c092b2a3d3e.svn-base b/critterai/.svn/pristine/4a/4acab54d724f2739a1a5a58b1b045c092b2a3d3e.svn-base deleted file mode 100644 index 520d5225..00000000 --- a/critterai/.svn/pristine/4a/4acab54d724f2739a1a5a58b1b045c092b2a3d3e.svn-base +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nmgen; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Applies to a - /// . - /// - public sealed class AreaConvexMarker - : AreaMarker - { - private readonly Vector3[] verts; - private readonly float ymin; - private readonly float ymax; - - private AreaConvexMarker(string name - , int priority - , byte area - , Vector3[] verts - , float ymin - , float ymax) - : base(name, priority, area) - { - this.verts = verts; - this.ymin = ymin; - this.ymax = ymax; - } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// The area will be applied during the - /// state. - /// - /// - /// The current build state. - /// The context to process. - /// False on error, otherwise true. - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - if (state != NMGenState.CompactFieldBuild) - return true; - - if (context.CompactField.MarkConvexPolyArea(context, verts, ymin, ymax, Area)) - { - context.Log(string.Format( - "{0}: Marked convex polygon area: Area: {1}, Priority: {2}" - , Name, Area, Priority) - , this); - - return true; - } - - context.Log(Name + ": Failed to mark convex polygon area.", this); - return false; - } - - /// - /// Creates a new marker. - /// - /// - /// Will return null on an invalid vertices array or invalid min/max values. - /// - /// The processor name. - /// The processor priority. - /// The area to apply. - /// A list of vertices that form a convex polygon. - /// The minimum y-axis world position. - /// The maximum y-axis world position. - /// A new marker, or null on error. - public static AreaConvexMarker Create(string name, int priority, byte area - , Vector3[] verts, float ymin, float ymax) - { - if (verts == null || verts.Length == 0 || ymin > ymax) - return null; - - return new AreaConvexMarker(name, priority, area, verts, ymin, ymax); - } - } -} diff --git a/critterai/.svn/pristine/4a/4ad8921e195c78210ddde93561fb1f0460aa5fb5.svn-base b/critterai/.svn/pristine/4a/4ad8921e195c78210ddde93561fb1f0460aa5fb5.svn-base deleted file mode 100644 index 5013a0af..00000000 Binary files a/critterai/.svn/pristine/4a/4ad8921e195c78210ddde93561fb1f0460aa5fb5.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/4b/4b466752b3cd19b28f2a034e6c249ac74cf4d17a.svn-base b/critterai/.svn/pristine/4b/4b466752b3cd19b28f2a034e6c249ac74cf4d17a.svn-base deleted file mode 100644 index 76e631cc..00000000 --- a/critterai/.svn/pristine/4b/4b466752b3cd19b28f2a034e6c249ac74cf4d17a.svn-base +++ /dev/null @@ -1,1337 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" -#include - - -static void calculateDistanceField(rcCompactHeightfield& chf, unsigned short* src, unsigned short& maxDist) -{ - const int w = chf.width; - const int h = chf.height; - - // Init distance and points. - for (int i = 0; i < chf.spanCount; ++i) - src[i] = 0xffff; - - // Mark boundary cells. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - const unsigned char area = chf.areas[i]; - - int nc = 0; - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); - if (area == chf.areas[ai]) - nc++; - } - } - if (nc != 4) - src[i] = 0; - } - } - } - - - // Pass 1 - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - - if (rcGetCon(s, 0) != RC_NOT_CONNECTED) - { - // (-1,0) - const int ax = x + rcGetDirOffsetX(0); - const int ay = y + rcGetDirOffsetY(0); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0); - const rcCompactSpan& as = chf.spans[ai]; - if (src[ai]+2 < src[i]) - src[i] = src[ai]+2; - - // (-1,-1) - if (rcGetCon(as, 3) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(3); - const int aay = ay + rcGetDirOffsetY(3); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 3); - if (src[aai]+3 < src[i]) - src[i] = src[aai]+3; - } - } - if (rcGetCon(s, 3) != RC_NOT_CONNECTED) - { - // (0,-1) - const int ax = x + rcGetDirOffsetX(3); - const int ay = y + rcGetDirOffsetY(3); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3); - const rcCompactSpan& as = chf.spans[ai]; - if (src[ai]+2 < src[i]) - src[i] = src[ai]+2; - - // (1,-1) - if (rcGetCon(as, 2) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(2); - const int aay = ay + rcGetDirOffsetY(2); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 2); - if (src[aai]+3 < src[i]) - src[i] = src[aai]+3; - } - } - } - } - } - - // Pass 2 - for (int y = h-1; y >= 0; --y) - { - for (int x = w-1; x >= 0; --x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - - if (rcGetCon(s, 2) != RC_NOT_CONNECTED) - { - // (1,0) - const int ax = x + rcGetDirOffsetX(2); - const int ay = y + rcGetDirOffsetY(2); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 2); - const rcCompactSpan& as = chf.spans[ai]; - if (src[ai]+2 < src[i]) - src[i] = src[ai]+2; - - // (1,1) - if (rcGetCon(as, 1) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(1); - const int aay = ay + rcGetDirOffsetY(1); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 1); - if (src[aai]+3 < src[i]) - src[i] = src[aai]+3; - } - } - if (rcGetCon(s, 1) != RC_NOT_CONNECTED) - { - // (0,1) - const int ax = x + rcGetDirOffsetX(1); - const int ay = y + rcGetDirOffsetY(1); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 1); - const rcCompactSpan& as = chf.spans[ai]; - if (src[ai]+2 < src[i]) - src[i] = src[ai]+2; - - // (-1,1) - if (rcGetCon(as, 0) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(0); - const int aay = ay + rcGetDirOffsetY(0); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 0); - if (src[aai]+3 < src[i]) - src[i] = src[aai]+3; - } - } - } - } - } - - maxDist = 0; - for (int i = 0; i < chf.spanCount; ++i) - maxDist = rcMax(src[i], maxDist); - -} - -static unsigned short* boxBlur(rcCompactHeightfield& chf, int thr, - unsigned short* src, unsigned short* dst) -{ - const int w = chf.width; - const int h = chf.height; - - thr *= 2; - - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - const unsigned short cd = src[i]; - if (cd <= thr) - { - dst[i] = cd; - continue; - } - - int d = (int)cd; - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); - d += (int)src[ai]; - - const rcCompactSpan& as = chf.spans[ai]; - const int dir2 = (dir+1) & 0x3; - if (rcGetCon(as, dir2) != RC_NOT_CONNECTED) - { - const int ax2 = ax + rcGetDirOffsetX(dir2); - const int ay2 = ay + rcGetDirOffsetY(dir2); - const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2); - d += (int)src[ai2]; - } - else - { - d += cd; - } - } - else - { - d += cd*2; - } - } - dst[i] = (unsigned short)((d+5)/9); - } - } - } - return dst; -} - - -static bool floodRegion(int x, int y, int i, - unsigned short level, unsigned short r, - rcCompactHeightfield& chf, - unsigned short* srcReg, unsigned short* srcDist, - rcIntArray& stack) -{ - const int w = chf.width; - - const unsigned char area = chf.areas[i]; - - // Flood fill mark region. - stack.resize(0); - stack.push((int)x); - stack.push((int)y); - stack.push((int)i); - srcReg[i] = r; - srcDist[i] = 0; - - unsigned short lev = level >= 2 ? level-2 : 0; - int count = 0; - - while (stack.size() > 0) - { - int ci = stack.pop(); - int cy = stack.pop(); - int cx = stack.pop(); - - const rcCompactSpan& cs = chf.spans[ci]; - - // Check if any of the neighbours already have a valid region set. - unsigned short ar = 0; - for (int dir = 0; dir < 4; ++dir) - { - // 8 connected - if (rcGetCon(cs, dir) != RC_NOT_CONNECTED) - { - const int ax = cx + rcGetDirOffsetX(dir); - const int ay = cy + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir); - if (chf.areas[ai] != area) - continue; - unsigned short nr = srcReg[ai]; - if (nr & RC_BORDER_REG) // Do not take borders into account. - continue; - if (nr != 0 && nr != r) - ar = nr; - - const rcCompactSpan& as = chf.spans[ai]; - - const int dir2 = (dir+1) & 0x3; - if (rcGetCon(as, dir2) != RC_NOT_CONNECTED) - { - const int ax2 = ax + rcGetDirOffsetX(dir2); - const int ay2 = ay + rcGetDirOffsetY(dir2); - const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2); - if (chf.areas[ai2] != area) - continue; - unsigned short nr2 = srcReg[ai2]; - if (nr2 != 0 && nr2 != r) - ar = nr2; - } - } - } - if (ar != 0) - { - srcReg[ci] = 0; - continue; - } - count++; - - // Expand neighbours. - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(cs, dir) != RC_NOT_CONNECTED) - { - const int ax = cx + rcGetDirOffsetX(dir); - const int ay = cy + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(cs, dir); - if (chf.areas[ai] != area) - continue; - if (chf.dist[ai] >= lev && srcReg[ai] == 0) - { - srcReg[ai] = r; - srcDist[ai] = 0; - stack.push(ax); - stack.push(ay); - stack.push(ai); - } - } - } - } - - return count > 0; -} - -static unsigned short* expandRegions(int maxIter, unsigned short level, - rcCompactHeightfield& chf, - unsigned short* srcReg, unsigned short* srcDist, - unsigned short* dstReg, unsigned short* dstDist, - rcIntArray& stack) -{ - const int w = chf.width; - const int h = chf.height; - - // Find cells revealed by the raised level. - stack.resize(0); - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - if (chf.dist[i] >= level && srcReg[i] == 0 && chf.areas[i] != RC_NULL_AREA) - { - stack.push(x); - stack.push(y); - stack.push(i); - } - } - } - } - - int iter = 0; - while (stack.size() > 0) - { - int failed = 0; - - memcpy(dstReg, srcReg, sizeof(unsigned short)*chf.spanCount); - memcpy(dstDist, srcDist, sizeof(unsigned short)*chf.spanCount); - - for (int j = 0; j < stack.size(); j += 3) - { - int x = stack[j+0]; - int y = stack[j+1]; - int i = stack[j+2]; - if (i < 0) - { - failed++; - continue; - } - - unsigned short r = srcReg[i]; - unsigned short d2 = 0xffff; - const unsigned char area = chf.areas[i]; - const rcCompactSpan& s = chf.spans[i]; - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(s, dir) == RC_NOT_CONNECTED) continue; - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); - if (chf.areas[ai] != area) continue; - if (srcReg[ai] > 0 && (srcReg[ai] & RC_BORDER_REG) == 0) - { - if ((int)srcDist[ai]+2 < (int)d2) - { - r = srcReg[ai]; - d2 = srcDist[ai]+2; - } - } - } - if (r) - { - stack[j+2] = -1; // mark as used - dstReg[i] = r; - dstDist[i] = d2; - } - else - { - failed++; - } - } - - // rcSwap source and dest. - rcSwap(srcReg, dstReg); - rcSwap(srcDist, dstDist); - - if (failed*3 == stack.size()) - break; - - if (level > 0) - { - ++iter; - if (iter >= maxIter) - break; - } - } - - return srcReg; -} - - -struct rcRegion -{ - inline rcRegion(unsigned short i) : - spanCount(0), - id(i), - areaType(0), - remap(false), - visited(false) - {} - - int spanCount; // Number of spans belonging to this region - unsigned short id; // ID of the region - unsigned char areaType; // Are type. - bool remap; - bool visited; - rcIntArray connections; - rcIntArray floors; -}; - -static void removeAdjacentNeighbours(rcRegion& reg) -{ - // Remove adjacent duplicates. - for (int i = 0; i < reg.connections.size() && reg.connections.size() > 1; ) - { - int ni = (i+1) % reg.connections.size(); - if (reg.connections[i] == reg.connections[ni]) - { - // Remove duplicate - for (int j = i; j < reg.connections.size()-1; ++j) - reg.connections[j] = reg.connections[j+1]; - reg.connections.pop(); - } - else - ++i; - } -} - -static void replaceNeighbour(rcRegion& reg, unsigned short oldId, unsigned short newId) -{ - bool neiChanged = false; - for (int i = 0; i < reg.connections.size(); ++i) - { - if (reg.connections[i] == oldId) - { - reg.connections[i] = newId; - neiChanged = true; - } - } - for (int i = 0; i < reg.floors.size(); ++i) - { - if (reg.floors[i] == oldId) - reg.floors[i] = newId; - } - if (neiChanged) - removeAdjacentNeighbours(reg); -} - -static bool canMergeWithRegion(const rcRegion& rega, const rcRegion& regb) -{ - if (rega.areaType != regb.areaType) - return false; - int n = 0; - for (int i = 0; i < rega.connections.size(); ++i) - { - if (rega.connections[i] == regb.id) - n++; - } - if (n > 1) - return false; - for (int i = 0; i < rega.floors.size(); ++i) - { - if (rega.floors[i] == regb.id) - return false; - } - return true; -} - -static void addUniqueFloorRegion(rcRegion& reg, int n) -{ - for (int i = 0; i < reg.floors.size(); ++i) - if (reg.floors[i] == n) - return; - reg.floors.push(n); -} - -static bool mergeRegions(rcRegion& rega, rcRegion& regb) -{ - unsigned short aid = rega.id; - unsigned short bid = regb.id; - - // Duplicate current neighbourhood. - rcIntArray acon; - acon.resize(rega.connections.size()); - for (int i = 0; i < rega.connections.size(); ++i) - acon[i] = rega.connections[i]; - rcIntArray& bcon = regb.connections; - - // Find insertion point on A. - int insa = -1; - for (int i = 0; i < acon.size(); ++i) - { - if (acon[i] == bid) - { - insa = i; - break; - } - } - if (insa == -1) - return false; - - // Find insertion point on B. - int insb = -1; - for (int i = 0; i < bcon.size(); ++i) - { - if (bcon[i] == aid) - { - insb = i; - break; - } - } - if (insb == -1) - return false; - - // Merge neighbours. - rega.connections.resize(0); - for (int i = 0, ni = acon.size(); i < ni-1; ++i) - rega.connections.push(acon[(insa+1+i) % ni]); - - for (int i = 0, ni = bcon.size(); i < ni-1; ++i) - rega.connections.push(bcon[(insb+1+i) % ni]); - - removeAdjacentNeighbours(rega); - - for (int j = 0; j < regb.floors.size(); ++j) - addUniqueFloorRegion(rega, regb.floors[j]); - rega.spanCount += regb.spanCount; - regb.spanCount = 0; - regb.connections.resize(0); - - return true; -} - -static bool isRegionConnectedToBorder(const rcRegion& reg) -{ - // Region is connected to border if - // one of the neighbours is null id. - for (int i = 0; i < reg.connections.size(); ++i) - { - if (reg.connections[i] == 0) - return true; - } - return false; -} - -static bool isSolidEdge(rcCompactHeightfield& chf, unsigned short* srcReg, - int x, int y, int i, int dir) -{ - const rcCompactSpan& s = chf.spans[i]; - unsigned short r = 0; - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir); - r = srcReg[ai]; - } - if (r == srcReg[i]) - return false; - return true; -} - -static void walkContour(int x, int y, int i, int dir, - rcCompactHeightfield& chf, - unsigned short* srcReg, - rcIntArray& cont) -{ - int startDir = dir; - int starti = i; - - const rcCompactSpan& ss = chf.spans[i]; - unsigned short curReg = 0; - if (rcGetCon(ss, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(ss, dir); - curReg = srcReg[ai]; - } - cont.push(curReg); - - int iter = 0; - while (++iter < 40000) - { - const rcCompactSpan& s = chf.spans[i]; - - if (isSolidEdge(chf, srcReg, x, y, i, dir)) - { - // Choose the edge corner - unsigned short r = 0; - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*chf.width].index + rcGetCon(s, dir); - r = srcReg[ai]; - } - if (r != curReg) - { - curReg = r; - cont.push(curReg); - } - - dir = (dir+1) & 0x3; // Rotate CW - } - else - { - int ni = -1; - const int nx = x + rcGetDirOffsetX(dir); - const int ny = y + rcGetDirOffsetY(dir); - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const rcCompactCell& nc = chf.cells[nx+ny*chf.width]; - ni = (int)nc.index + rcGetCon(s, dir); - } - if (ni == -1) - { - // Should not happen. - return; - } - x = nx; - y = ny; - i = ni; - dir = (dir+3) & 0x3; // Rotate CCW - } - - if (starti == i && startDir == dir) - { - break; - } - } - - // Remove adjacent duplicates. - if (cont.size() > 1) - { - for (int j = 0; j < cont.size(); ) - { - int nj = (j+1) % cont.size(); - if (cont[j] == cont[nj]) - { - for (int k = j; k < cont.size()-1; ++k) - cont[k] = cont[k+1]; - cont.pop(); - } - else - ++j; - } - } -} - -static bool filterSmallRegions(rcContext* ctx, int minRegionArea, int mergeRegionSize, - unsigned short& maxRegionId, - rcCompactHeightfield& chf, - unsigned short* srcReg) -{ - const int w = chf.width; - const int h = chf.height; - - const int nreg = maxRegionId+1; - rcRegion* regions = (rcRegion*)rcAlloc(sizeof(rcRegion)*nreg, RC_ALLOC_TEMP); - if (!regions) - { - ctx->log(RC_LOG_ERROR, "filterSmallRegions: Out of memory 'regions' (%d).", nreg); - return false; - } - - // Construct regions - for (int i = 0; i < nreg; ++i) - new(®ions[i]) rcRegion((unsigned short)i); - - // Find edge of a region and find connections around the contour. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - unsigned short r = srcReg[i]; - if (r == 0 || r >= nreg) - continue; - - rcRegion& reg = regions[r]; - reg.spanCount++; - - - // Update floors. - for (int j = (int)c.index; j < ni; ++j) - { - if (i == j) continue; - unsigned short floorId = srcReg[j]; - if (floorId == 0 || floorId >= nreg) - continue; - addUniqueFloorRegion(reg, floorId); - } - - // Have found contour - if (reg.connections.size() > 0) - continue; - - reg.areaType = chf.areas[i]; - - // Check if this cell is next to a border. - int ndir = -1; - for (int dir = 0; dir < 4; ++dir) - { - if (isSolidEdge(chf, srcReg, x, y, i, dir)) - { - ndir = dir; - break; - } - } - - if (ndir != -1) - { - // The cell is at border. - // Walk around the contour to find all the neighbours. - walkContour(x, y, i, ndir, chf, srcReg, reg.connections); - } - } - } - } - - // Remove too small regions. - rcIntArray stack(32); - rcIntArray trace(32); - for (int i = 0; i < nreg; ++i) - { - rcRegion& reg = regions[i]; - if (reg.id == 0 || (reg.id & RC_BORDER_REG)) - continue; - if (reg.spanCount == 0) - continue; - if (reg.visited) - continue; - - // Count the total size of all the connected regions. - // Also keep track of the regions connects to a tile border. - bool connectsToBorder = false; - int spanCount = 0; - stack.resize(0); - trace.resize(0); - - reg.visited = true; - stack.push(i); - - while (stack.size()) - { - // Pop - int ri = stack.pop(); - - rcRegion& creg = regions[ri]; - - spanCount += creg.spanCount; - trace.push(ri); - - for (int j = 0; j < creg.connections.size(); ++j) - { - if (creg.connections[j] & RC_BORDER_REG) - { - connectsToBorder = true; - continue; - } - rcRegion& neireg = regions[creg.connections[j]]; - if (neireg.visited) - continue; - if (neireg.id == 0 || (neireg.id & RC_BORDER_REG)) - continue; - // Visit - stack.push(neireg.id); - neireg.visited = true; - } - } - - // If the accumulated regions size is too small, remove it. - // Do not remove areas which connect to tile borders - // as their size cannot be estimated correctly and removing them - // can potentially remove necessary areas. - if (spanCount < minRegionArea && !connectsToBorder) - { - // Kill all visited regions. - for (int j = 0; j < trace.size(); ++j) - { - regions[trace[j]].spanCount = 0; - regions[trace[j]].id = 0; - } - } - } - - // Merge too small regions to neighbour regions. - int mergeCount = 0 ; - do - { - mergeCount = 0; - for (int i = 0; i < nreg; ++i) - { - rcRegion& reg = regions[i]; - if (reg.id == 0 || (reg.id & RC_BORDER_REG)) - continue; - if (reg.spanCount == 0) - continue; - - // Check to see if the region should be merged. - if (reg.spanCount > mergeRegionSize && isRegionConnectedToBorder(reg)) - continue; - - // Small region with more than 1 connection. - // Or region which is not connected to a border at all. - // Find smallest neighbour region that connects to this one. - int smallest = 0xfffffff; - unsigned short mergeId = reg.id; - for (int j = 0; j < reg.connections.size(); ++j) - { - if (reg.connections[j] & RC_BORDER_REG) continue; - rcRegion& mreg = regions[reg.connections[j]]; - if (mreg.id == 0 || (mreg.id & RC_BORDER_REG)) continue; - if (mreg.spanCount < smallest && - canMergeWithRegion(reg, mreg) && - canMergeWithRegion(mreg, reg)) - { - smallest = mreg.spanCount; - mergeId = mreg.id; - } - } - // Found new id. - if (mergeId != reg.id) - { - unsigned short oldId = reg.id; - rcRegion& target = regions[mergeId]; - - // Merge neighbours. - if (mergeRegions(target, reg)) - { - // Fixup regions pointing to current region. - for (int j = 0; j < nreg; ++j) - { - if (regions[j].id == 0 || (regions[j].id & RC_BORDER_REG)) continue; - // If another region was already merged into current region - // change the nid of the previous region too. - if (regions[j].id == oldId) - regions[j].id = mergeId; - // Replace the current region with the new one if the - // current regions is neighbour. - replaceNeighbour(regions[j], oldId, mergeId); - } - mergeCount++; - } - } - } - } - while (mergeCount > 0); - - // Compress region Ids. - for (int i = 0; i < nreg; ++i) - { - regions[i].remap = false; - if (regions[i].id == 0) continue; // Skip nil regions. - if (regions[i].id & RC_BORDER_REG) continue; // Skip external regions. - regions[i].remap = true; - } - - unsigned short regIdGen = 0; - for (int i = 0; i < nreg; ++i) - { - if (!regions[i].remap) - continue; - unsigned short oldId = regions[i].id; - unsigned short newId = ++regIdGen; - for (int j = i; j < nreg; ++j) - { - if (regions[j].id == oldId) - { - regions[j].id = newId; - regions[j].remap = false; - } - } - } - maxRegionId = regIdGen; - - // Remap regions. - for (int i = 0; i < chf.spanCount; ++i) - { - if ((srcReg[i] & RC_BORDER_REG) == 0) - srcReg[i] = regions[srcReg[i]].id; - } - - for (int i = 0; i < nreg; ++i) - regions[i].~rcRegion(); - rcFree(regions); - - return true; -} - -/// @par -/// -/// This is usually the second to the last step in creating a fully built -/// compact heightfield. This step is required before regions are built -/// using #rcBuildRegions or #rcBuildRegionsMonotone. -/// -/// After this step, the distance data is available via the rcCompactHeightfield::maxDistance -/// and rcCompactHeightfield::dist fields. -/// -/// @see rcCompactHeightfield, rcBuildRegions, rcBuildRegionsMonotone -bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD); - - if (chf.dist) - { - rcFree(chf.dist); - chf.dist = 0; - } - - unsigned short* src = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); - if (!src) - { - ctx->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'src' (%d).", chf.spanCount); - return false; - } - unsigned short* dst = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); - if (!dst) - { - ctx->log(RC_LOG_ERROR, "rcBuildDistanceField: Out of memory 'dst' (%d).", chf.spanCount); - rcFree(src); - return false; - } - - unsigned short maxDist = 0; - - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); - - calculateDistanceField(chf, src, maxDist); - chf.maxDistance = maxDist; - - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_DIST); - - ctx->startTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); - - // Blur - if (boxBlur(chf, 1, src, dst) != src) - rcSwap(src, dst); - - // Store distance. - chf.dist = src; - - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD_BLUR); - - ctx->stopTimer(RC_TIMER_BUILD_DISTANCEFIELD); - - rcFree(dst); - - return true; -} - -static void paintRectRegion(int minx, int maxx, int miny, int maxy, unsigned short regId, - rcCompactHeightfield& chf, unsigned short* srcReg) -{ - const int w = chf.width; - for (int y = miny; y < maxy; ++y) - { - for (int x = minx; x < maxx; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - if (chf.areas[i] != RC_NULL_AREA) - srcReg[i] = regId; - } - } - } -} - - -static const unsigned short RC_NULL_NEI = 0xffff; - -struct rcSweepSpan -{ - unsigned short rid; // row id - unsigned short id; // region id - unsigned short ns; // number samples - unsigned short nei; // neighbour id -}; - -/// @par -/// -/// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour. -/// Contours will form simple polygons. -/// -/// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be -/// re-assigned to the zero (null) region. -/// -/// Partitioning can result in smaller than necessary regions. @p mergeRegionArea helps -/// reduce unecessarily small regions. -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// The region data will be available via the rcCompactHeightfield::maxRegions -/// and rcCompactSpan::reg fields. -/// -/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions. -/// -/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig -bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int minRegionArea, const int mergeRegionArea) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_BUILD_REGIONS); - - const int w = chf.width; - const int h = chf.height; - unsigned short id = 1; - - rcScopedDelete srcReg = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount, RC_ALLOC_TEMP); - if (!srcReg) - { - ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'src' (%d).", chf.spanCount); - return false; - } - memset(srcReg,0,sizeof(unsigned short)*chf.spanCount); - - const int nsweeps = rcMax(chf.width,chf.height); - rcScopedDelete sweeps = (rcSweepSpan*)rcAlloc(sizeof(rcSweepSpan)*nsweeps, RC_ALLOC_TEMP); - if (!sweeps) - { - ctx->log(RC_LOG_ERROR, "rcBuildRegionsMonotone: Out of memory 'sweeps' (%d).", nsweeps); - return false; - } - - - // Mark border regions. - if (borderSize > 0) - { - // Make sure border will not overflow. - const int bw = rcMin(w, borderSize); - const int bh = rcMin(h, borderSize); - // Paint regions - paintRectRegion(0, bw, 0, h, id|RC_BORDER_REG, chf, srcReg); id++; - paintRectRegion(w-bw, w, 0, h, id|RC_BORDER_REG, chf, srcReg); id++; - paintRectRegion(0, w, 0, bh, id|RC_BORDER_REG, chf, srcReg); id++; - paintRectRegion(0, w, h-bh, h, id|RC_BORDER_REG, chf, srcReg); id++; - - chf.borderSize = borderSize; - } - - rcIntArray prev(256); - - // Sweep one line at a time. - for (int y = borderSize; y < h-borderSize; ++y) - { - // Collect spans from this row. - prev.resize(id+1); - memset(&prev[0],0,sizeof(int)*id); - unsigned short rid = 1; - - for (int x = borderSize; x < w-borderSize; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - if (chf.areas[i] == RC_NULL_AREA) continue; - - // -x - unsigned short previd = 0; - if (rcGetCon(s, 0) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(0); - const int ay = y + rcGetDirOffsetY(0); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0); - if ((srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai]) - previd = srcReg[ai]; - } - - if (!previd) - { - previd = rid++; - sweeps[previd].rid = previd; - sweeps[previd].ns = 0; - sweeps[previd].nei = 0; - } - - // -y - if (rcGetCon(s,3) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(3); - const int ay = y + rcGetDirOffsetY(3); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3); - if (srcReg[ai] && (srcReg[ai] & RC_BORDER_REG) == 0 && chf.areas[i] == chf.areas[ai]) - { - unsigned short nr = srcReg[ai]; - if (!sweeps[previd].nei || sweeps[previd].nei == nr) - { - sweeps[previd].nei = nr; - sweeps[previd].ns++; - prev[nr]++; - } - else - { - sweeps[previd].nei = RC_NULL_NEI; - } - } - } - - srcReg[i] = previd; - } - } - - // Create unique ID. - for (int i = 1; i < rid; ++i) - { - if (sweeps[i].nei != RC_NULL_NEI && sweeps[i].nei != 0 && - prev[sweeps[i].nei] == (int)sweeps[i].ns) - { - sweeps[i].id = sweeps[i].nei; - } - else - { - sweeps[i].id = id++; - } - } - - // Remap IDs - for (int x = borderSize; x < w-borderSize; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - if (srcReg[i] > 0 && srcReg[i] < rid) - srcReg[i] = sweeps[srcReg[i]].id; - } - } - } - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER); - - // Filter out small regions. - chf.maxRegions = id; - if (!filterSmallRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg)) - return false; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER); - - // Store the result out. - for (int i = 0; i < chf.spanCount; ++i) - chf.spans[i].reg = srcReg[i]; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS); - - return true; -} - -/// @par -/// -/// Non-null regions will consist of connected, non-overlapping walkable spans that form a single contour. -/// Contours will form simple polygons. -/// -/// If multiple regions form an area that is smaller than @p minRegionArea, then all spans will be -/// re-assigned to the zero (null) region. -/// -/// Watershed partitioning can result in smaller than necessary regions, especially in diagonal corridors. -/// @p mergeRegionArea helps reduce unecessarily small regions. -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// The region data will be available via the rcCompactHeightfield::maxRegions -/// and rcCompactSpan::reg fields. -/// -/// @warning The distance field must be created using #rcBuildDistanceField before attempting to build regions. -/// -/// @see rcCompactHeightfield, rcCompactSpan, rcBuildDistanceField, rcBuildRegionsMonotone, rcConfig -bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int minRegionArea, const int mergeRegionArea) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_BUILD_REGIONS); - - const int w = chf.width; - const int h = chf.height; - - rcScopedDelete buf = (unsigned short*)rcAlloc(sizeof(unsigned short)*chf.spanCount*4, RC_ALLOC_TEMP); - if (!buf) - { - ctx->log(RC_LOG_ERROR, "rcBuildRegions: Out of memory 'tmp' (%d).", chf.spanCount*4); - return false; - } - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_WATERSHED); - - rcIntArray stack(1024); - rcIntArray visited(1024); - - unsigned short* srcReg = buf; - unsigned short* srcDist = buf+chf.spanCount; - unsigned short* dstReg = buf+chf.spanCount*2; - unsigned short* dstDist = buf+chf.spanCount*3; - - memset(srcReg, 0, sizeof(unsigned short)*chf.spanCount); - memset(srcDist, 0, sizeof(unsigned short)*chf.spanCount); - - unsigned short regionId = 1; - unsigned short level = (chf.maxDistance+1) & ~1; - - // TODO: Figure better formula, expandIters defines how much the - // watershed "overflows" and simplifies the regions. Tying it to - // agent radius was usually good indication how greedy it could be. -// const int expandIters = 4 + walkableRadius * 2; - const int expandIters = 8; - - if (borderSize > 0) - { - // Make sure border will not overflow. - const int bw = rcMin(w, borderSize); - const int bh = rcMin(h, borderSize); - // Paint regions - paintRectRegion(0, bw, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; - paintRectRegion(w-bw, w, 0, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; - paintRectRegion(0, w, 0, bh, regionId|RC_BORDER_REG, chf, srcReg); regionId++; - paintRectRegion(0, w, h-bh, h, regionId|RC_BORDER_REG, chf, srcReg); regionId++; - - chf.borderSize = borderSize; - } - - while (level > 0) - { - level = level >= 2 ? level-2 : 0; - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_EXPAND); - - // Expand current regions until no empty connected cells found. - if (expandRegions(expandIters, level, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg) - { - rcSwap(srcReg, dstReg); - rcSwap(srcDist, dstDist); - } - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_EXPAND); - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FLOOD); - - // Mark new regions with IDs. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - if (chf.dist[i] < level || srcReg[i] != 0 || chf.areas[i] == RC_NULL_AREA) - continue; - if (floodRegion(x, y, i, level, regionId, chf, srcReg, srcDist, stack)) - regionId++; - } - } - } - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FLOOD); - } - - // Expand current regions until no empty connected cells found. - if (expandRegions(expandIters*8, 0, chf, srcReg, srcDist, dstReg, dstDist, stack) != srcReg) - { - rcSwap(srcReg, dstReg); - rcSwap(srcDist, dstDist); - } - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_WATERSHED); - - ctx->startTimer(RC_TIMER_BUILD_REGIONS_FILTER); - - // Filter out small regions. - chf.maxRegions = regionId; - if (!filterSmallRegions(ctx, minRegionArea, mergeRegionArea, chf.maxRegions, chf, srcReg)) - return false; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS_FILTER); - - // Write the result out. - for (int i = 0; i < chf.spanCount; ++i) - chf.spans[i].reg = srcReg[i]; - - ctx->stopTimer(RC_TIMER_BUILD_REGIONS); - - return true; -} - - diff --git a/critterai/.svn/pristine/4b/4bba00b03f0213e590a2787506d5b5f1e76cefaa.svn-base b/critterai/.svn/pristine/4b/4bba00b03f0213e590a2787506d5b5f1e76cefaa.svn-base deleted file mode 100644 index a7158550..00000000 --- a/critterai/.svn/pristine/4b/4bba00b03f0213e590a2787506d5b5f1e76cefaa.svn-base +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - - - The IncrementalBuilder implements a flexible build process that can be used at - design time to create PolyMesh and DetailMesh objects. INMGenProcessor's - are used to customize the process for almost any need. - - - - - - - This builder is not suitable for use at run-time since it is designed for flexibility - rather than high performance. - - - - There are a lot of configuration settings to deal with during the build process. See the NMGenParams - documentation for details, including recommendations. - - - - - - Only one builder is needed if the navigation mesh will contain only a single tile. Multi-tile meshes require - one builder for each tile. (Builders are single use.) - - - - - // Example: A simple NMGen build. - - // Where 'mesh' is a TriangleMesh object containing all of the input triangles - // and 'config' is a NMGenParams object containing the configuration. - - // Create an input geometry object. - byte[] areas = NMGen.CreateDefaultAreaBuffer(mesh.triCount); - InputGeometryBuilder gbuilder = InputGeometryBuilder.Create(mesh, areas, 45.5f); - gbuilder.BuildAll(); - InputGeometry geom = gbuilder.Result; - - // Create the incremental builder. - NMGenAssetFlag resultFlags = NMGenAssetFlag.PolyMesh | NMGenAssetFlag.DetailMesh; - IncrementalBuilder builder = IncrementalBuilder.Create(config - , resultFlags - , geom - , ProcessorSet.CreateStandard(ProcessorSet.StandardOptions)); - - // Perform the build and check the result. - builder.BuildAll(); - - switch (builder.State) - { - case NMGenState.Aborted: - - // Handle the error. - // Check builder messages for details. - - case NMGenState.Complete: - - NMGenAssets result = builder.Result; - - // Use the poly and detail mesh data. - - case NMGenState.NoResult: - - // No result was produced. - // Unexpected for single-tile builds. Not uncommon for multi-tile builds. - // Check builder messages for details. - } - - - - - -
- - The Process - - - - - The incremental builder follows the process described by topic. - - - - - - -
- -
- - The Polygon Mesh - - - - - The IncrementalBuilder's main output is a PolyMesh object. - The polygon mesh is made up of convex polygons with between three and - F:org.critterai.nmgen.NMGen.MaxAllowedVertsPerPoly - vertices. Each polygon includes edge link, area, flag data. - - - - Polygons may overlap, based on the value of - P:org.critterai.nmgen.NMGenParams.WalkableHeight used during the build. - - - - At the end of the build process all polygons should have at least one flag set. Usually - F:org.critterai.nmbuild.NMBuild.DefaultFlag. - - - - All polygons will have a non-zero area id. (<= F:org.critterai.nmgen.NMGen.MaxArea) - - - - - - -
- -
- - The Detail Mesh - - - - An common optional output of the IncrementalBuilder is a DetailMesh object. - - - Pathfinding only uses the PolyMesh. For storage efficiency and speed the polygon mesh doesn't have a lot of height accuracy. - But some secondary navigation features require more accurate height data. The detail mesh provides the extra detail. - - - - The detail mesh consists of sub-meshes, one for each polygon in the polygon mesh. Each sub-mesh is a - triangle mesh that contains all the vertices of its associated polygon, plus additional vertices - that provide the extra height detail. - - - - -
- -
- - The NMGen Processors - - - - The NMGen processors provided by the ProcessorSet are what give the incremental builder its flexibility and power. - Without any processors, only a very simple polygon mesh can be created. - - Processors are called during the post-processor step of each stage, in ascending priority. A processor may perform processing - during a single stage or multiple stages. - - - - Any oject that implements INMGenProcessor can act as a processor. The - T:org.critterai.nmbuild.NMGenProcessor abstract class provides a good base to start from. - - - Two common uses for processors include polygon area and flag assignment. - -
- - Area Assignment - - - - - Area assignment can happen via the InputGeometry object. But sometimes that isn't convenient or possible. Another choice - is to mark areas into the compact heightfield. You can use the T:org.critterai.nmbuild.AreaBoxMarker, - T:org.critterai.nmbuild.AreaCylinderMarker, and - T:org.critterai.nmbuild.AreaConvexMarker processors to do this. - - - - Because processors are prioritized, area markers can overwrite each other in useful ways. For example, lets say you have a swamp area with - a dry island contained within it. The swamp area needs to be assigned one area while the island needs to be a assigned a different area. - If you mark the swamp, the island will be included. This can't be helped since all markers are convex. But by marking the island with a higher - priority marker, it will be assigned the proper area. - - - - Another powerful use of area markers is applying F:org.critterai.nmgen.NMGen.NullArea. - Sometimes the build process will create polygons in areas you don't like. For example, there may be clutter on the ground that can technically - be walked across, but looks bad when it is. If you mark the area with F:org.critterai.nmgen.NMGen.NullArea, - then the area will be excluded from the final polygon mesh. - - - - -
- -
- - Polygon Flag Assignment - - - - - Polygon flags can be managed entirely in the Navmesh object. But sometimes the flags are best assigned to the PolyMesh - during the build process. For example, you may want to assign the 'swim' flag to all 'water' area polygons. - - - - The T:org.critterai.nmbuild.ApplyPolygonFlags processor can be used to add flags to all polygons. - - - - The T:org.critterai.nmbuild.AreaFlagMapper processor can be used to add flags to polygons based on - the area id of each polygon. - - - - -
- -
- -
- - - - T:org.critterai.nmbuild.IncrementalBuilder - T:org.critterai.nmbuild.NMGenAssets - T:org.critterai.nmgen.NMGenParams - - - - - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/4c/4cbb700b2f5c1716c841227816c584697fd45b5a.svn-base b/critterai/.svn/pristine/4c/4cbb700b2f5c1716c841227816c584697fd45b5a.svn-base deleted file mode 100644 index 880c024f..00000000 Binary files a/critterai/.svn/pristine/4c/4cbb700b2f5c1716c841227816c584697fd45b5a.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/4c/4cf924580bbd4018acd43a0b690ade9d92a0b993.svn-base b/critterai/.svn/pristine/4c/4cf924580bbd4018acd43a0b690ade9d92a0b993.svn-base deleted file mode 100644 index 8c0caa47..00000000 --- a/critterai/.svn/pristine/4c/4cf924580bbd4018acd43a0b690ade9d92a0b993.svn-base +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - - -/** - * Provides operations related to 2-dimensional rectangles. - *

This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No checks are performed to ensure that maximums are greater than minimums.

- *

Static operations are thread safe.

- */ -public class Rectangle2 -{ - - private Rectangle2() { } - - /** - * Indicates whether or not a point is contained within an axis-aligned rectangle. - * The test is inclusive of the edges of the rectangle. I.e. If the point lies - * on the edge of the rectangle, then it is contained by the rectangle. - * @param minX The minimum x-axis bounds of the rectangle. - * @param minY The minimum y-axis bounds of the rectangle. - * @param maxX The maximum x-axis bounds of the rectangle. - * @param maxY The maximum y-axis bounds of the rectangle. - * @param x The x-value of the point (x, y) to test. - * @param y The y-value of the point (x, y) to test. - * @return TRUE if the point lies within the rectangle. Otherwise FALSE. - */ - public static boolean contains(float minX, float minY, float maxX, float maxY, float x, float y) - { - return !(x < minX || y < minY || x > maxX || y > maxY); - } - - /** - * Indicates whether or not an axis-alighed rectangle (B) is contained within another - * axis-aligned rectangle (A). - * The test is inclusive of the edges of the rectangles. - * @param minXA The minimum x-axis bounds of rectangle A. - * @param minYA The minimum y-axis bounds of rectangle A. - * @param maxXA The maximum x-axis bounds of rectangle A. - * @param maxYA The maximum y-axis bounds of rectangle A. - * @param minXB The minimum x-axis bounds of rectangle B. - * @param minYB The minimum y-axis bounds of rectangle B. - * @param maxXB The maximum x-axis bounds of rectangle B. - * @param maxYB The maximum y-axis bounds of rectangle B. - * @return TRUE if rectangle B is fully contained by rectangle A. Otherwise FALSE. - */ - public static boolean contains(float minXA, float minYA, float maxXA, float maxYA - , float minXB, float minYB, float maxXB, float maxYB) - { - return (minXB >= minXA && minYB >= minYA && maxXB <= maxXA && maxYB <= maxYA); - } - - /** - * Indicates whether or not two axis-aligned rectangles intersect. - * The test is inclusive of the edges of the rectangles. - * @param minAX The minimum x-axis bounds of rectangle A. - * @param minAY The minimum y-axis bounds of rectangle A. - * @param maxAX The maximum x-axis bounds of rectangle A. - * @param maxAY The maximum y-axis bounds of rectangle A. - * @param minBX The minimum x-axis bounds of rectangle B. - * @param minBY The minimum y-axis bounds of rectangle B. - * @param maxBX The maximum x-axis bounds of rectangle B. - * @param maxBY The maximum y-axis bounds of rectangle B. - * @return TRUE if the two rectangles intersect in any manner. Otherwise FALSE. - */ - public static boolean intersectsAABB(float minAX, float minAY, float maxAX, float maxAY - , float minBX, float minBY, float maxBX, float maxBY) - { - return !(maxBX < minAX || maxAX < minBX || maxBY < minAY || maxAY < minBY ); - } - -} diff --git a/critterai/.svn/pristine/4c/4cfa2f51cf71e1d0769af34a1cc5930b13ba6715.svn-base b/critterai/.svn/pristine/4c/4cfa2f51cf71e1d0769af34a1cc5930b13ba6715.svn-base deleted file mode 100644 index 1345d44a..00000000 --- a/critterai/.svn/pristine/4c/4cfa2f51cf71e1d0769af34a1cc5930b13ba6715.svn-base +++ /dev/null @@ -1,134 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; - -import org.junit.Test; -import org.junit.Before; - -/** - * Tests related to the ContourSetBuilder.removeVerticalSegments() - * operation. - */ -public class RemoveVerticalSegmentTests -{ - /* - * Design notes: - * - * These tests are simplified to assume that the second - * vertex in a vertical segment is removed. - */ - private static final int REGION_S = 58; - - private final ArrayList mBadQuad = new ArrayList(16); - - @Before - public void setup() - { - - /* - * Base Quad - * - * 1/2 - 3 - * | | - * 0 - 4/5 - */ - - mBadQuad.add(1); - mBadQuad.add(5); - mBadQuad.add(2); - mBadQuad.add(0); - - mBadQuad.add(1); - mBadQuad.add(5); - mBadQuad.add(3); - mBadQuad.add(0); - - mBadQuad.add(1); - mBadQuad.add(6); - mBadQuad.add(3); - mBadQuad.add(0); - - mBadQuad.add(2); - mBadQuad.add(5); - mBadQuad.add(3); - mBadQuad.add(0); - - mBadQuad.add(2); - mBadQuad.add(5); - mBadQuad.add(2); - mBadQuad.add(0); - - mBadQuad.add(2); - mBadQuad.add(4); - mBadQuad.add(2); - mBadQuad.add(0); - } - - @Test - public void testQuadOffset0() - { - - ContourSetBuilder.removeVerticalSegments(REGION_S, mBadQuad); - assertTrue(mBadQuad.size() == 16); - - assertTrue(mBadQuad.get(0) == 1); - assertTrue(mBadQuad.get(2) == 2); - - assertTrue(mBadQuad.get(4) == 1); - assertTrue(mBadQuad.get(6) == 3); - - assertTrue(mBadQuad.get(8) == 2); - assertTrue(mBadQuad.get(10) == 3); - - assertTrue(mBadQuad.get(12) == 2); - assertTrue(mBadQuad.get(14) == 2); - } - - @Test - public void testQuadOffset1() - { - // This test assumes that the second vertex is removed. - - ContourUtil.shiftContour(mBadQuad); - ContourSetBuilder.removeVerticalSegments(REGION_S, mBadQuad); - assertTrue(mBadQuad.size() == 16); - - assertTrue(mBadQuad.get(0) == 1); - assertTrue(mBadQuad.get(2) == 2); - - assertTrue(mBadQuad.get(4) == 1); - assertTrue(mBadQuad.get(6) == 3); - - assertTrue(mBadQuad.get(8) == 2); - assertTrue(mBadQuad.get(10) == 3); - - assertTrue(mBadQuad.get(12) == 2); - assertTrue(mBadQuad.get(14) == 2); - } - - @Test - public void testQuadOffset2() - { - // This test assumes that the second vertex is removed. - - ContourUtil.shiftContour(mBadQuad); - ContourUtil.shiftContour(mBadQuad); - ContourSetBuilder.removeVerticalSegments(REGION_S, mBadQuad); - assertTrue(mBadQuad.size() == 16); - - assertTrue(mBadQuad.get(0) == 2); - assertTrue(mBadQuad.get(2) == 2); - - assertTrue(mBadQuad.get(4) == 1); - assertTrue(mBadQuad.get(6) == 2); - - assertTrue(mBadQuad.get(8) == 1); - assertTrue(mBadQuad.get(10) == 3); - - assertTrue(mBadQuad.get(12) == 2); - assertTrue(mBadQuad.get(14) == 3); - } - -} diff --git a/critterai/.svn/pristine/4d/4d14afb41da69f4476a197c49f734ab8004f0d55.svn-base b/critterai/.svn/pristine/4d/4d14afb41da69f4476a197c49f734ab8004f0d55.svn-base deleted file mode 100644 index fe230bf6..00000000 --- a/critterai/.svn/pristine/4d/4d14afb41da69f4476a197c49f734ab8004f0d55.svn-base +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.geom; -using System.Collections.Generic; -using org.critterai.nmgen; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Used to compile input geometry in a dynamic fashion. - /// - /// - /// - /// The standard use case is to use this class to compile input - /// geometry from various sources, then use to create - /// the finalized input geometry for the build. - /// - /// - /// - /// - public sealed class InputGeometryCompiler - { - private readonly List mVerts; - private readonly List mTris; - private readonly List mAreas; - - /// - /// The number of loaded vertices. - /// - public int VertCount { get { return mVerts.Count; } } - - /// - /// The number of loaded triangles. - /// - public int TriCount { get { return mTris.Count / 3; } } - - /// - /// Constructor. - /// - /// The initial vertex buffer size. - /// The initial triangle buffer size. - public InputGeometryCompiler(int initVertCount, int initTriCount) - { - initVertCount = System.Math.Max(9, initVertCount); - initTriCount = System.Math.Max(1, initTriCount); - - mVerts = new List(initVertCount); - mTris = new List(initTriCount * 3); - mAreas = new List(initTriCount); - } - - /// - /// Adds a single triangle. - /// - /// Vertex A of triangle ABC. - /// Vertex B of triangle ABC. - /// Vertex C of triangle ABC. - /// The triangle area. - public void AddTriangle(Vector3 vertA, Vector3 vertB, Vector3 vertC, byte area) - { - mTris.Add(mVerts.Count); - mVerts.Add(vertA); - - mTris.Add(mVerts.Count); - mVerts.Add(vertB); - - mTris.Add(mVerts.Count); - mVerts.Add(vertC); - - mAreas.Add(area); - } - - /// - /// Adds an arbitrary group of triangles. - /// - /// - /// - /// All triangles will default to if the - /// parameter is null. - /// - /// - /// - /// The triangle vertices. [Length: >= ] - /// - /// The number of vertices. [Length: >= 3] - /// - /// The triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount] - /// [Length: >= 3 * ] - /// - /// - /// The triangle areas. (Optional) [Length: >= ] - /// - /// The number of triangles. [Limit: > 0] - /// True if the triangles were successfully added. - public bool AddTriangles(Vector3[] verts, int vertCount - , int[] tris, byte[] areas, int triCount) - { - if (triCount < 1 || vertCount < 3 - || verts == null || verts.Length < vertCount - || tris == null || tris.Length < triCount * 3 - || areas != null && areas.Length < triCount) - { - return false; - } - - if (areas == null) - areas = NMGen.CreateDefaultAreaBuffer(triCount); - - int iVertOffset = mVerts.Count; - - if (vertCount == verts.Length) - mVerts.AddRange(verts); - else - { - mVerts.Capacity += vertCount; - - for (int p = 0; p < vertCount; p++) - { - mVerts.Add(verts[p]); - } - } - - int length = triCount * 3; - - mTris.Capacity += length; - - for (int p = 0; p < length; p++) - { - mTris.Add(tris[p] + iVertOffset); - } - - if (areas.Length == triCount) - mAreas.AddRange(areas); - else - { - mAreas.Capacity += triCount; - - for (int i = 0; i < triCount; i++) - { - mAreas.Add(areas[i]); - } - } - - return true; - } - - /// - /// Adds a triangle mesh. - /// - /// - /// - /// All triangles will default to if the - /// parameter is null. - /// - /// - /// Will return false if the mesh triangle count is zero. - /// - /// - /// The triangle mesh. - /// - /// The triangle areas. (Optional)[Length: >= mesh.triCount] - /// - /// True if the triangles were successfully added. - public bool AddTriangles(TriangleMesh mesh, byte[] areas) - { - if (mesh == null || mesh.triCount == 0) - return false; - - return AddTriangles(mesh.verts, mesh.vertCount, mesh.tris, areas, mesh.triCount); - } - - /// - /// Checks for an removes invalid triangles. - /// - /// - /// - /// A triangle is considered invalid in the following cases: - /// - ///
    - ///
  • A vertex index is out of range.
  • - ///
  • The triangle contains duplicate vertices. (E.g. vertAIndex = vertBIndex)
  • - ///
- ///
- /// The number of triangles removed. - public int CleanTriangles() - { - int triCount = TriCount; - int vertCount = mVerts.Count; - - if (triCount == 0) - return 0; - - int result = 0; - - for (int i = triCount - 1; i >= 0; i--) - { - int p = i * 3; - - int a = mTris[p + 0]; - int b = mTris[p + 1]; - int c = mTris[p + 2]; - - if (a < 0 || a >= vertCount - || b < 0 || b >= vertCount - || c < 0 || c >= vertCount - || a == b || b == c || c == a) - { - // Bad triangle. - mTris.RemoveRange(p, 3); - mAreas.RemoveAt(i); - result++; - } - } - - return result; - } - - /// - /// Creates geometry from the compiled data. - /// - /// The triangle areas. - /// The triangle mesh, or null if the compiler is empty. - public TriangleMesh CreateGeometry(out byte[] areas) - { - if (mTris.Count == 0) - { - areas = null; - return null; - } - - areas = mAreas.ToArray(); - - return new TriangleMesh(mVerts.ToArray(), mVerts.Count - , mTris.ToArray(), mTris.Count / 3); - } - - /// - /// Resets the compiler to an empty state. - /// - public void Reset() - { - mTris.Clear(); - mVerts.Clear(); - mAreas.Clear(); - } - } -} diff --git a/critterai/.svn/pristine/4d/4d840b2f715d6b447f6f63a938bafa84b4fe76a8.svn-base b/critterai/.svn/pristine/4d/4d840b2f715d6b447f6f63a938bafa84b4fe76a8.svn-base deleted file mode 100644 index 645da407..00000000 --- a/critterai/.svn/pristine/4d/4d840b2f715d6b447f6f63a938bafa84b4fe76a8.svn-base +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.nmgen; -using System.Collections.Generic; -using org.critterai.nav; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(MeshAreaDef))] -public sealed class MeshAreaDefEditor - : Editor -{ - private CAINavEditorSettingsEditor.AreaGUIControl mAreaControl; - - void OnEnable() - { - mAreaControl = CAINavEditorSettingsEditor.CreateAreaControl(""); - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - MeshAreaDef targ = (MeshAreaDef)target; - - // Has someone done something naughty? - - if (targ.areas == null || targ.meshes == null) - { - Debug.LogError(targ.name + "Data null reference. Resetting component."); - targ.areas = new List(); - targ.meshes = new List(); - } - - List areas = targ.areas; - List meshes = targ.meshes; - - if (areas.Count > meshes.Count) - { - areas.RemoveRange(meshes.Count, areas.Count - meshes.Count); - Debug.LogError(targ.name + "Data size mismatch. Area list truncated."); - } - else if (meshes.Count > areas.Count) - { - meshes.RemoveRange(areas.Count, meshes.Count - areas.Count); - Debug.LogError(targ.name + "Data size mismatch. Mesh list truncated."); - } - - EditorGUILayout.Separator(); - - targ.SetPriority(EditorGUILayout.IntField("Priority", targ.Priority)); - - EditorGUILayout.Separator(); - - targ.matchType = (MatchType) - EditorGUILayout.EnumPopup("Match Type", targ.matchType); - - EditorGUILayout.Separator(); - - GUILayout.Label("Mesh / Area"); - - EditorGUILayout.Separator(); - - if (areas.Count > 0) - { - EditorGUILayout.BeginVertical(); - - int delChoice = -1; - - for (int i = 0; i < areas.Count; i++) - { - EditorGUILayout.BeginHorizontal(); - - Mesh mesh = (Mesh) - EditorGUILayout.ObjectField(meshes[i], typeof(Mesh), false); - - if (mesh == null) - delChoice = i; - else if (mesh == meshes[i] || !meshes.Contains(mesh)) - meshes[i] = mesh; - - areas[i] = mAreaControl.OnGUI(areas[i]); - - if (GUILayout.Button("X", GUILayout.Width(30))) - delChoice = i; - - EditorGUILayout.EndHorizontal(); - } - - if (delChoice >= 0) - { - meshes.RemoveAt(delChoice); - areas.RemoveAt(delChoice); - } - - EditorGUILayout.EndVertical(); - } - - EditorGUILayout.BeginVertical(); - EditorGUILayout.Separator(); - - EditorGUILayout.BeginHorizontal(); - - Mesh nmesh = (Mesh) - EditorGUILayout.ObjectField("Add", null, typeof(Mesh), false); - - if (nmesh != null && !meshes.Contains(nmesh)) - { - meshes.Add(nmesh); - areas.Add(NMGen.MaxArea); - } - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.EndVertical(); - - EditorGUILayout.Separator(); - - string msg = "Input Build Processor\n\nApplies areas to " + typeof(MeshFilter).Name - + " compoents based on the " + typeof(Mesh).Name + " object they reference.\n\n"; - - switch (targ.matchType) - { - case MatchType.Strict: - - msg += "Will match only on strict mesh equality."; - break; - - case MatchType.NameBeginsWith: - - msg += "Will match any mesh that starts with the mesh names. Example: If the" - + " source mesh name is 'Column', then 'ColumnWooden' and 'Column Iron' will" - + " match."; - break; - - case MatchType.AnyInstance: - - msg += "Will match any instance, based on name. The check is lazy. Example:" - + " If the source mesh name is 'SwampMesh', then both 'SwampMesh Instance' and " - + " 'SwampMesh NotReallyAnInstance' will match."; - break; - } - - GUILayout.Box(msg, EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Area Definition : Mesh", false, NMBEditorUtil.AreaGroup)] - static void CreateAsset() - { - MeshAreaDef item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/4d/4d9f300b2a1cfaa1f80bedce789f711b6e445415.svn-base b/critterai/.svn/pristine/4d/4d9f300b2a1cfaa1f80bedce789f711b6e445415.svn-base deleted file mode 100644 index f9035737..00000000 --- a/critterai/.svn/pristine/4d/4d9f300b2a1cfaa1f80bedce789f711b6e445415.svn-base +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.geom; -using System.Collections.Generic; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Provides utility methods related to the UnityEngine.Terrain class. - /// - internal static class TerrainUtil - { - public static TriangleMesh TriangulateSurface(Terrain terrain, float resolution) - { - if (terrain == null || terrain.terrainData == null || resolution <= 0) - return null; - - Vector3 origin = terrain.transform.position; - - int xCount; - int zCount; - Vector3 scale = DeriveScale(terrain, resolution, out xCount, out zCount); - - TriangleMesh m = new TriangleMesh(xCount * zCount, (xCount - 1) * (zCount - 1) * 2); - - TriangulateSurface(terrain, origin, scale, xCount, zCount, 0, m); - - return m; - } - - public static TriangleMesh TriangulateSurface(Terrain terrain - , float xmin, float zmin, float xmax, float zmax - , float resolution - , float yOffset) - { - if (terrain == null || terrain.terrainData == null - || resolution <= 0 - || xmin > xmax || zmin > zmax) - { - return null; - } - - int xCount; - int zCount; - Vector3 scale = DeriveScale(terrain, resolution, out xCount, out zCount); - - Vector3 origin = terrain.transform.position; - - /* - * We are generating part of a larger mesh. The vertices must match that of the larger - * mesh. - * - * Convert input values to local grid space. - * Clamp to the heightfield bounds. - * Convert back to worldspace. - */ - xmin = origin.x + Mathf.Max(0, Mathf.Floor((xmin - origin.x) / scale.x)) * scale.x; - zmin = origin.z + Mathf.Max(0, Mathf.Floor((zmin - origin.z) / scale.z)) * scale.z; - xmax = origin.x + Mathf.Min(xCount, Mathf.Ceil((xmax - origin.x) / scale.x)) * scale.x; - zmax = origin.z + Mathf.Min(xCount, Mathf.Ceil((zmax - origin.z) / scale.z)) * scale.z; - - if (xmin + scale.x > xmax || zmin + scale.z > zmax) - // Triangulation zone is too small. - return null; - - // Everyting is already snapped to the grid. But there may be floating point errors. - // So round it. - xCount = Mathf.RoundToInt((xmax - xmin) / scale.x); - zCount = Mathf.RoundToInt((zmax - zmin) / scale.z); - - TriangleMesh m = new TriangleMesh(xCount * zCount, (xCount - 1) * (zCount - 1) * 2); - - TriangulateSurface(terrain - , new Vector3(xmin, origin.y, zmin) - , scale - , xCount, zCount - , yOffset - , m); - - return m; - } - - private static void TriangulateSurface(Terrain terrain - , Vector3 origin - , Vector3 scale - , int xCount - , int zCount - , float yOffset - , TriangleMesh buffer) - { - - // Create the vertices by sampling the terrain. - for (int ix = 0; ix < xCount; ix++) - { - float x = origin.x + ix * scale.x; - for (int iz = 0; iz < zCount; iz++) - { - float z = origin.z + iz * scale.z; - Vector3 pos = new Vector3(x, origin.y, z); - pos.y += terrain.SampleHeight(pos) + yOffset; - buffer.verts[buffer.vertCount] = pos; - buffer.vertCount++; - } - } - - // Triangulate surface sample points. - for (int ix = 0; ix < xCount - 1; ix++) - { - for (int iz = 0; iz < zCount - 1; iz++) - { - int i = iz + (ix * zCount); - int irow = i + zCount; - - buffer.tris[buffer.triCount * 3 + 0] = i; - buffer.tris[buffer.triCount * 3 + 1] = irow + 1; - buffer.tris[buffer.triCount * 3 + 2] = irow; - buffer.triCount++; - - buffer.tris[buffer.triCount * 3 + 0] = i; - buffer.tris[buffer.triCount * 3 + 1] = i + 1; - buffer.tris[buffer.triCount * 3 + 2] = irow + 1; - buffer.triCount++; - } - } - } - - public static void TriangluateTrees(Terrain terrain - , byte area - , InputGeometryCompiler compiler) - { - if (terrain == null || terrain.terrainData == null || compiler == null) - return; - - TerrainData data = terrain.terrainData; - - // Note: This array may be loaded with nulls. - // This is required to keep indices in sync. - Mesh[] protoMeshes = new Mesh[data.treePrototypes.Length]; - - for (int i = 0; i < protoMeshes.Length; i++) - { - TreePrototype prototype = data.treePrototypes[i]; - MeshFilter filter = prototype.prefab.GetComponent(); - - if (filter == null || filter.sharedMesh == null) - { - Debug.LogWarning(string.Format( - "{0} : There is no mesh attached the {1} tree prototype." - + "Trees based on this prototype will be ignored." - , terrain.name - , prototype.prefab.name)); - protoMeshes[i] = null; - } - else - protoMeshes[i] = filter.sharedMesh; - } - - Vector3 terrainPos = terrain.transform.position; - Vector3 terrainSize = terrain.terrainData.size; - - Queue combineInstances = - new Queue(data.treeInstances.Length); - - foreach (TreeInstance tree in data.treeInstances) - { - if (protoMeshes[tree.prototypeIndex] == null) - // Prototype for this tree doesn't have a mesh. - continue; - - Vector3 pos = tree.position; - pos.x *= terrainSize.x; - pos.y *= terrainSize.y; - pos.z *= terrainSize.z; - pos += terrainPos; - - Vector3 scale = - new Vector3(tree.widthScale, tree.heightScale, tree.widthScale); - - CombineInstance ci = new CombineInstance(); - ci.mesh = protoMeshes[tree.prototypeIndex]; - ci.transform = Matrix4x4.TRS(pos, Quaternion.identity, scale); - - combineInstances.Enqueue(ci); - } - - protoMeshes = null; - - if (combineInstances.Count == 0) - return; - - MeshUtil.CombineMeshes(combineInstances, area, compiler); - } - - public static Vector3 DeriveScale(Terrain terrain, float resolution - , out int widthCount, out int depthCount) - { - widthCount = 0; - depthCount = 0; - - if (terrain == null || terrain.terrainData == null || resolution <= 0) - return Vector3.zero; - - Vector3 scale = terrain.terrainData.heightmapScale; - widthCount = terrain.terrainData.heightmapWidth; - depthCount = terrain.terrainData.heightmapHeight; - - if (resolution > 0 && resolution < 1) - { - Vector3 size = terrain.terrainData.size; - widthCount = Mathf.FloorToInt(size.x / scale.x * resolution); - depthCount = Mathf.FloorToInt(size.z / scale.z * resolution); - - scale.x = size.x / (float)widthCount; - scale.z = size.z / (float)depthCount; - - // For the vertices along the maximum bounds... - widthCount++; - depthCount++; - } - - return scale; - } - } -} diff --git a/critterai/.svn/pristine/4d/4da5e153fe2ebfa721b60c0ac495a0178f445277.svn-base b/critterai/.svn/pristine/4d/4da5e153fe2ebfa721b60c0ac495a0178f445277.svn-base deleted file mode 100644 index 7a7fe94e..00000000 --- a/critterai/.svn/pristine/4d/4da5e153fe2ebfa721b60c0ac495a0178f445277.svn-base +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// A processor used during the NMGen build process. - /// - public interface INMGenProcessor - : IPriorityItem - { - /// - /// The name of the processor. - /// - string Name { get; } - - /// - /// True if the processor is safe to use across multiple threads at the same time. - /// - bool IsThreadSafe { get; } - - /// - /// The build assets that should be preserved past their normal disposal point. - /// - /// - /// - /// Most processors will return zero. Use judiciously since it can result in large - /// increases in memory consumption during a build. - /// - /// - /// Builders usually dispose of assets as soon as the asset is no longer needed for - /// a 'normal' build. For example, the is usually disposed as - /// soon as the is created. So if a processor needs - /// the heightfield for processing after heightfield post-processing, it should indicate - /// so through this field. - /// - /// - NMGenAssetFlag PreserveAssets { get; } - - /// - /// Process the build context. - /// - /// - /// - /// The processor will never return the context in an invalid state. If it - /// wants the build to abort it will return false rather than resetting or nulling - /// values in the context. - /// - /// - /// The processor will always log a message to the context when it returns false. - /// It may also log summary messages for use in debugging. - /// - /// - /// The current build state. - /// The context to process. - /// False if the build should abort. Otherwise true. - bool ProcessBuild(NMGenContext context, NMGenState state); - } -} diff --git a/critterai/.svn/pristine/4d/4df7f0ad5ddb1db2d802f1e07fef2d8b8603c004.svn-base b/critterai/.svn/pristine/4d/4df7f0ad5ddb1db2d802f1e07fef2d8b8603c004.svn-base deleted file mode 100644 index 3d23912f..00000000 Binary files a/critterai/.svn/pristine/4d/4df7f0ad5ddb1db2d802f1e07fef2d8b8603c004.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/4e/4e60a9a46871f009eb4ee25488b4abd88a4887ba.svn-base b/critterai/.svn/pristine/4e/4e60a9a46871f009eb4ee25488b4abd88a4887ba.svn-base deleted file mode 100644 index b3084bca..00000000 --- a/critterai/.svn/pristine/4e/4e60a9a46871f009eb4ee25488b4abd88a4887ba.svn-base +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nav.rcn; -using org.critterai.interop; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Represents an agent managed by a object. - /// - /// - /// - /// Objects of this type can only be obtained from a object. - /// - /// - /// Behavior is undefined if used after disposal. Disposal is controled by the - /// that owns the agent. - /// - /// - /// - public sealed class CrowdAgent - { - /* - * Design notes: - * - * The difficulty in the design of the agent is that the - * structure on the native side contains embedded classes. - * (Rather than pointers to instances.) And interop can't seem to - * handle that. So I'm forced into a less efficient design. - * - */ - - private IntPtr root; // dtCrowdAgent - private CrowdManager mManager; - internal int managerIndex; - - /// - /// The the agent belongs to. - /// - public CrowdManager Manager - { - get { return mManager; } - } - - /// - /// The type of mesh polygon the agent is traversing. - /// - public CrowdAgentState State - { - get { return mManager.agentStates[managerIndex].state; } - } - - /// - /// The number of neighbor agents. (In vicinity of agent.) - /// - public int NeighborCount - { - get { return mManager.agentStates[managerIndex].neighborCount; } - } - - /// - /// The desired agent speed. (Derived) - /// - public float DesiredSpeed - { - get { return mManager.agentStates[managerIndex].desiredSpeed; } - } - - /// - /// The position of the agent. - /// - public Vector3 Position - { - get { return mManager.agentStates[managerIndex].position; } - } - - /// - /// The reference of the polygon containing the agent position. - /// - public uint PositionPoly - { - get { return mManager.agentStates[managerIndex].positionPoly; } - } - - /// - /// The agent's target. (Location the agent is moving toward.) - /// - /// - /// - /// The same as the path corridor target. - /// - /// - public Vector3 Target - { - get { return mManager.agentStates[managerIndex].target; } - } - - /// - /// The reference of the polygon containing the target. - /// - public uint TargetPoly - { - get { return mManager.agentStates[managerIndex].targetPoly; } - } - - /// - /// The next corner in the path corridor. - /// - /// - /// - /// The same as the next corner in the agent's path corridor. - /// - /// - public Vector3 NextCorner - { - get { return mManager.agentStates[managerIndex].nextCorner; } - } - - /// - /// The reference of the polygon containing the next corner. - /// - /// - /// - /// This is the polygon being entered at the corner, or zero if the next corner is the - /// target. - /// - /// - public uint NextCornerPoly - { - get { return mManager.agentStates[managerIndex].nextCornerPoly; } - } - - /// - /// The desired agent velocity. (Derived) - /// - public Vector3 DesiredVelocity - { - get { return mManager.agentStates[managerIndex].desiredVelocity; } - } - - /// - /// The actual agent velocity. - /// - public Vector3 Velocity - { - get { return mManager.agentStates[managerIndex].velocity; } - } - - /// - /// Indicates whether the object's resources have been disposed. - /// - public bool IsDisposed { get { return (root == IntPtr.Zero); } } - - internal CrowdAgent(CrowdManager manager - , IntPtr agent - , int mangerIndex) - { - mManager = manager; - root = agent; - managerIndex = mangerIndex; - } - - internal void Dispose() - { - root = IntPtr.Zero; - mManager = null; - managerIndex = -1; - } - - /// - /// Gets the agent configuration. - /// - /// The agent configuration. - public CrowdAgentParams GetConfig() - { - CrowdAgentParams config = new CrowdAgentParams(); - if (!IsDisposed) - CrowdAgentEx.dtcaGetAgentParams(root, ref config); - return config; - } - - /// - /// Updates the configuration for an agent. - /// - /// The new agent configuration. - public void SetConfig(CrowdAgentParams config) - { - if (!IsDisposed) - CrowdManagerEx.dtcUpdateAgentParameters(mManager.root - , managerIndex - , ref config); - } - - /// - /// Submits a new move request for the agent. - /// - /// - /// - /// This method is used when a new target is set. Use when - /// only small local adjustments are needed. (Such as happens when following a moving - /// target.) - /// - /// - /// The position will be constrained to the surface of the navigation mesh. - /// - /// - /// The request will be processed during the next . - /// - /// - /// The target position. - /// True if the target was successfully set. - public bool RequestMoveTarget(NavmeshPoint target) - { - if (IsDisposed) - return false; - - return CrowdManagerEx.dtcRequestMoveTarget(mManager.root - , managerIndex - , target); - } - - /// - /// Adjusts the position of an agent's target. - /// - /// - /// - /// This method is used to make small local adjustments to the target. (Such as happens - /// when following a moving target.) Use when a new - /// target is needed. - /// - /// - /// The new target position. - /// True if the adjustment was successful. - public bool AdjustMoveTarget(NavmeshPoint position) - { - if (IsDisposed) - return false; - - return CrowdManagerEx.dtcAdjustMoveTarget(mManager.root - , managerIndex - , position); - } - - /// - /// Gets the corridor data related to the agent. - /// - /// - /// - /// Only available after after a update. - /// - /// - /// Warning: The buffer object must be sized to a maximum path size equal to - /// ! - /// - /// - /// - /// A buffer to load with the corridor data. (Out) - /// [Length: Maximum Path Size = - /// ] - /// - /// True if the data was sucessfully retrieved. - public bool GetCorridor(PathCorridorData buffer) - { - // Only a partial validation. - if (IsDisposed - || buffer == null - || buffer.path.Length != PathCorridorData.MarshalBufferSize) - { - return false; - } - CrowdAgentEx.dtcaGetPathCorridorData(root, buffer); - return true; - } - - /// - /// Gets the local boundary data for the agent. - /// - /// - /// - /// Only available after after a update. - /// - /// - /// This data is not updated every frame. So the boundary center will not always - /// equal the position of the agent. - /// - /// - /// A buffer to load with the boundary data. (Out) - /// - public void GetBoundary(LocalBoundaryData buffer) - { - if (!IsDisposed) - CrowdAgentEx.dtcaGetLocalBoundary(root, buffer); - } - - /// - /// Gets data related to the neighbors in the vicinity of the agent. - /// - /// - /// - /// Only available after after a update. - /// - /// - /// - /// A buffer to load with the neighbor data. - /// [Length: >= ] - /// - /// The number of neighbors in the buffer, or -1 on error. - public int GetNeighbors(CrowdNeighbor[] buffer) - { - if (IsDisposed - || buffer == null - || buffer.Length < CrowdNeighbor.MaxNeighbors) - { - return -1; - } - - int count = CrowdAgentEx.dtcaGetAgentNeighbors(root - , buffer - , buffer.Length); - - return count; - } - - /// - /// Gets the agent associated with the specified neighbor. - /// - /// The agent neighbor data. - /// The agent associated with the neighbor data, or null on error. - public CrowdAgent GetNeighbor(CrowdNeighbor neighbor) - { - if (IsDisposed || neighbor.index >= mManager.MaxAgents) - return null; - return mManager.mAgents[neighbor.index]; - } - - /// - /// Gets the local corner data for the agent. - /// - /// - /// - /// Only available after after a update. - /// - /// - /// Warning: The buffer object must be sized to ! - /// - /// - /// - /// The buffer to load with corner data. (Out) [Required: - /// = ] - /// - /// True if the data was sucessfully retrieved. - public bool GetCornerData(CornerData buffer) - { - // This is only a partial argument validation. - if (IsDisposed - || buffer == null - || buffer.polyRefs.Length != CornerData.MarshalBufferSize) - { - return false; - } - CrowdAgentEx.dtcaGetAgentCorners(root, buffer); - return true; - } - } -} diff --git a/critterai/.svn/pristine/4e/4e618ef01eadf3150a513af7de7c46ce0c636a7e.svn-base b/critterai/.svn/pristine/4e/4e618ef01eadf3150a513af7de7c46ce0c636a7e.svn-base deleted file mode 100644 index fbdbfed1..00000000 Binary files a/critterai/.svn/pristine/4e/4e618ef01eadf3150a513af7de7c46ce0c636a7e.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/4e/4ea8f2cd3e7425d2f01082c1e273473dfc676b23.svn-base b/critterai/.svn/pristine/4e/4ea8f2cd3e7425d2f01082c1e273473dfc676b23.svn-base deleted file mode 100644 index ae6f0e77..00000000 --- a/critterai/.svn/pristine/4e/4ea8f2cd3e7425d2f01082c1e273473dfc676b23.svn-base +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav.rcn -{ - internal static class NavmeshTileEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtnmBuildTileData(NavmeshTileBuildData sourceData - , [In, Out] NavmeshTileData resultTile); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtnmBuildTileDataRaw([In] byte[] rawData - , int dataSize - , [In, Out] NavmeshTileData resultTile); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtnmFreeTileData(NavmeshTileData tileData); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmGetTileDataHeader([In] byte[] rawData - , int dataSize - , ref NavmeshTileHeader resultHeader); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmGetTileDataHeaderAlt(IntPtr rawData - , int dataSize - , ref NavmeshTileHeader resultHeader); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern uint dtnmGetTileRef(IntPtr navmesh, IntPtr tile); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileStateSize(IntPtr navmesh, IntPtr tile); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmStoreTileState(IntPtr navmesh - , IntPtr tile - , [In, Out] byte[] stateData - , int dataSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmRestoreTileState(IntPtr navmesh - , IntPtr tile - , [In] byte[] stateData - , int dataSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtnmGetTileHeader(IntPtr tile); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern uint dtnmGetPolyRefBase(IntPtr navmesh, IntPtr tile); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileVerts(IntPtr tile - , [In, Out] Vector3[] verts - , int vertsCount); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTilePolys(IntPtr tile - , [In, Out] NavmeshPoly[] polys - , int polysSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileDetailVerts(IntPtr tile - , [In, Out] Vector3[] verts - , int vertsCount); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileDetailTris(IntPtr tile - , [In, Out] byte[] tris - , int trisSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileDetailMeshes(IntPtr tile - , [In, Out] NavmeshDetailMesh[] detailMeshes - , int meshesSize); - - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileLinks(IntPtr tile - , [In, Out] NavmeshLink[] links - , int linksSize); - - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileBVTree(IntPtr tile - , [In, Out] NavmeshBVNode[] nodes - , int nodesSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTileConnections(IntPtr tile - , [In, Out] NavmeshConnection[] conns - , int connsSize); - } -} diff --git a/critterai/.svn/pristine/4e/4ed2a1d5584479d4074398c33b033fcc3d864f92.svn-base b/critterai/.svn/pristine/4e/4ed2a1d5584479d4074398c33b033fcc3d864f92.svn-base deleted file mode 100644 index 3cf933a4..00000000 --- a/critterai/.svn/pristine/4e/4ed2a1d5584479d4074398c33b033fcc3d864f92.svn-base +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmgen -{ - /// - /// Contour vertex flags. (Applied to the forth element of the vertices arrays.) - /// - /// - /// - /// Contour vertices take the form (x, y, z, r). The r-value can contain these flags. - /// - /// - [System.Flags] - public enum ContourFlags - { - /// - /// The vertex is the start of a border edge. - /// - BorderVertex = 0x10000, - - /// - /// The vertex is the start of an edge that forms a boundary between areas. - /// - AreaBorder = 0x20000 - } -} diff --git a/critterai/.svn/pristine/4f/4fff278f3bb85ffccc6808aa8b70da627a58d0a8.svn-base b/critterai/.svn/pristine/4f/4fff278f3bb85ffccc6808aa8b70da627a58d0a8.svn-base deleted file mode 100644 index 6828a941..00000000 --- a/critterai/.svn/pristine/4f/4fff278f3bb85ffccc6808aa8b70da627a58d0a8.svn-base +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmgen; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class InputBuilder - { - private InputBuildState mState; - private readonly InputBuildContext mContext; - private readonly IInputBuildProcessor[] mInputProcessors; - - private InputAssets mAssets = new InputAssets(); - - public InputBuildState State { get { return mState; } } - - public int MessageCount - { - get { return (IsFinished ? mContext.MessageCount : 0); } - } - - public string[] Messages - { - get { return (IsFinished ? mContext.GetMessages() : new string[0]); } - } - - public InputAssets Result - { - get - { - return (mState == InputBuildState.Complete - ? mAssets - : new InputAssets()); - } - } - - public bool IsFinished - { - get - { - return (mState == InputBuildState.Complete - || mState == InputBuildState.Aborted); - } - } - - private InputBuilder(InputBuildContext context, IInputBuildProcessor[] processors) - { - mContext = context; - mInputProcessors = processors; - - System.Array.Sort(mInputProcessors, new PriorityComparer(true)); - - mState = InputBuildState.LoadComponents; - } - - public InputBuildState Build() - { - switch (mState) - { - case InputBuildState.LoadComponents: - LoadSceneItems(); - break; - case InputBuildState.FilterComponents: - FilterSceneItems(); - break; - case InputBuildState.ApplyAreaModifiers: - ApplyAreaModifiers(); - break; - case InputBuildState.CompileInput: - CompileInput(); - break; - case InputBuildState.PostProcess: - PostProcess(); - break; - } - return mState; - } - - public void BuildAll() - { - while (!IsFinished) { Build(); } - } - - private void LoadSceneItems() - { - if (RunProcessors() && ValidateSceneItems()) - { - mContext.Log(string.Format("{0} complete: {1} components." - , mState, mContext.components.Count) - , this); - - mState = InputBuildState.FilterComponents; - } - } - - private bool RunProcessors() - { - foreach (IInputBuildProcessor item in mInputProcessors) - { - if (!item.ProcessInput(mContext, mState)) - { - FinalizeOnAbort(string.Format("Processor requested abort: {0} ({1})" - , item.Name, mState)); - return false; - } - } - return true; - } - - private bool ValidateSceneItems() - { - List items = mContext.components; - - int orig = items.Count; - - // Remove nulls. - for (int i = items.Count - 1; i >= 0; i--) - { - if (items[i] == null) - items.RemoveAt(i); - } - - int purgedNull = orig - items.Count; - - orig = items.Count; - - // Remove duplicates. - for (int i = 0; i < items.Count; i++) - { - Component item = items[i]; - int j = items.LastIndexOf(item); - while (j > i) - { - items.RemoveAt(j); - j = items.LastIndexOf(item); - } - } - - int purgedDup = orig - items.Count; - - if (items.Count == 0) - { - FinalizeOnAbort(string.Format("No components available. ({0})", mState)); - return false; - } - - if (purgedNull > 0) - { - mContext.Log(string.Format("Purged null components: {0} ({1})" - , purgedNull, mState) - , this); - } - - if (purgedDup > 0) - { - mContext.Log(string.Format("Purged duplicate components: {0} ({1})" - , purgedDup, mState) - , this); - } - - return true; - } - - private void FilterSceneItems() - { - List items = mContext.components; - - int before = items.Count; - mContext.info.compCountPre = before; - - if (RunProcessors() && ValidateSceneItems()) - { - string msg = string.Format("{0} complete. {1} components. {2} removed." - , mState, mContext.components.Count, before - items.Count); - - mContext.Log(msg, this); - - mContext.info.compCountPost = items.Count; - - mState = InputBuildState.ApplyAreaModifiers; - } - } - - private void ApplyAreaModifiers() - { - List items = mContext.components; - List areas = mContext.areas; - int count = items.Count; - - areas.Clear(); - - for (int i = 0; i < count; i++) - { - areas.Add(NMGen.MaxArea); - } - - if (!RunProcessors()) - return; - - if (items.Count != count || areas.Count != count || items.Contains(null)) - { - FinalizeOnAbort(string.Format("Custom processors corrupted component list." - + " (Detected nulls or count mismatch.) ({0})" - , mState)); - } - else - { - mContext.Log(mState + " complete.", this); - mState = InputBuildState.CompileInput; - } - } - - private void CompileInput() - { - // Just in case input processors were naughty. - mContext.processors.Clear(); - mContext.connCompiler.Reset(); - mContext.geomCompiler.Reset(); - - if (RunProcessors()) - { - mContext.Log(mState + " complete.", this); - mState = InputBuildState.PostProcess; - } - } - - private void PostProcess() - { - if ((mContext.Options & InputBuildOption.AutoCleanGeometry) != 0) - { - int removed = mContext.geomCompiler.CleanTriangles(); - mContext.Log("Cleaned geometry. " + removed + " invalid triangles removed.", this); - } - - if (RunProcessors()) - { - mContext.Log(mState + " complete.", this); - FinalizeBuild(); - } - } - - private void ResetLocals() - { - mContext.connCompiler.Reset(); - mContext.geomCompiler.Reset(); - mContext.processors.Clear(); - mContext.areas.Clear(); - mContext.components.Clear(); - } - - private void FinalizeOnAbort(string message) - { - mAssets = new InputAssets(); - mContext.LogError(message, this); - ResetLocals(); - mState = InputBuildState.Aborted; - } - - private void FinalizeBuild() - { - mAssets.info = mContext.info; - - mAssets.geometry = mContext.geomCompiler.CreateGeometry(out mAssets.areas); - - if (mAssets.geometry == null) - { - FinalizeOnAbort(string.Format("No geometry was produced. ({0})", mState)); - return; - } - - mAssets.processors = mContext.processors.ToArray(); - mAssets.conns = mContext.connCompiler.CreateConnectionSet(); - - string msg = string.Format("Final geometry: Triangles: {0}, Vertices: {1}" - , mAssets.geometry.triCount, mAssets.geometry.vertCount); - - mContext.Log(msg, this); - - mContext.Log("Final Off-Mesh Connections: " + mAssets.conns.Count, this); - - if (mAssets.processors.Length < 10) - { - foreach (INMGenProcessor p in mAssets.processors) - { - mContext.Log("NMGen Processor: " + p.Name, this); - } - } - else - mContext.Log("NMGen processor count: " + mAssets.processors.Length, this); - - ResetLocals(); - mState = InputBuildState.Complete; - } - - public static InputBuilder Create(ISceneQuery filter - , IInputBuildProcessor[] processors - , InputBuildOption options) - { - IInputBuildProcessor[] lprocessors = ArrayUtil.Compress(processors); - - if (lprocessors == null || lprocessors.Length == 0) - return null; - - for (int i = lprocessors.Length - 1; i >= 0; i--) - { - IInputBuildProcessor processor = lprocessors[i]; - - if (processor.DuplicatesAllowed) - continue; - - System.Type ta = processor.GetType(); - - for (int j = i - 1; j >= 0; j--) - { - System.Type tb = lprocessors[j].GetType(); - - if (ta.IsAssignableFrom(tb) || tb.IsAssignableFrom(ta)) - return null; - } - } - - if (lprocessors == processors) - lprocessors = (IInputBuildProcessor[])lprocessors.Clone(); - - InputBuildContext context = new InputBuildContext(filter, options); - - return new InputBuilder(context, lprocessors); - } - - public static float ToProgress(InputBuildState state) - { - float inc = 1 / 5f; - switch (state) - { - case InputBuildState.LoadComponents: - return inc * 1; - case InputBuildState.FilterComponents: - return inc * 2; - case InputBuildState.ApplyAreaModifiers: - return inc * 3; - case InputBuildState.CompileInput: - return inc * 4; - case InputBuildState.PostProcess: - return inc * 5; - case InputBuildState.Aborted: - return 1.0f; - case InputBuildState.Complete: - return 1.0f; - } - return 0; - } - - public static string ToLabel(InputBuildState state) - { - switch (state) - { - case InputBuildState.LoadComponents: - return "Loading scene objects..."; - case InputBuildState.FilterComponents: - return "Filtering scene objects..."; - case InputBuildState.ApplyAreaModifiers: - return "Applying area modifiers..."; - case InputBuildState.CompileInput: - return "Compiling input..."; - case InputBuildState.PostProcess: - return "Post-processing..."; - case InputBuildState.Aborted: - return "Aborted."; - case InputBuildState.Complete: - return "Input gathered."; - } - return "Unhandled state: " + state; - } - } -} diff --git a/critterai/.svn/pristine/50/5062587d4c5c3ccf74972d47b62ffa60f8405f36.svn-base b/critterai/.svn/pristine/50/5062587d4c5c3ccf74972d47b62ffa60f8405f36.svn-base deleted file mode 100644 index 142212ce..00000000 --- a/critterai/.svn/pristine/50/5062587d4c5c3ccf74972d47b62ffa60f8405f36.svn-base +++ /dev/null @@ -1,699 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// - /// - internal class BuildController - { - private enum ControlType : byte - { - Build = 0x01, - Config = 0x02, - Input = 0x04, - } - - private static GUIStyle mSelectedStyle; - private static GUIStyle mUnselectedStyle; - - private const float MarginSize = ControlUtil.MarginSize; - private const float SelectAreaHeight = 20; - - private readonly ControlContext mContext; - private readonly DebugViewContext mDebugContext; - private readonly UnityBuildContext mLogger = new UnityBuildContext(); - - private bool mIsActive = false; - private NavmeshBuildState mLastBuildState; - - private readonly InputCompileControl mInputCon; - private readonly NMGenConfigControl mConfigCon; - private IBuildControl mBuildCon; // Can be null; - - private ControlType mSelectedControl = 0; - - private IBuildControl mOverrideControl; - - public NavmeshBuild Build { get { return mContext.Build; } } - public int ActiveTasks { get { return mContext.TaskCount; } } - - public bool BuildIsActive - { - get - { - NavmeshBuildState bs = mContext.Build.BuildState; - return ((bs != NavmeshBuildState.Inactive && bs != NavmeshBuildState.Invalid) - || mInputCon.HasInputData); - } - - } - - public BuildController(NavmeshBuild build, BuildTaskProcessor manager) - { - if (!build || manager == null) - throw new System.ArgumentNullException(); - - mContext = new ControlContext(build, manager); - mDebugContext = new DebugViewContext(build, mContext.Selection); - - mInputCon = new InputCompileControl(); - mConfigCon = new NMGenConfigControl(); - } - - public bool Enter() - { - // Note: Never returns false. Displays a failure control instead. - - if (mIsActive) - return true; - - NavmeshBuild build = mContext.Build; - - if (!build) - { - SetCriticalFailure("The build object has been deleted."); - return true; - } - - build.CleanBuild(); - - if (build.HasBuildData) - { - Debug.LogWarning("Build component contains intermediate build data." - + " Potential causes:\n" - + "Editor reset or entered play mode in the middle of a build.\n" - + "User forgot to exit the build.\n" - + "User keeping the data around for later use.\n" - , build); - } - - if (build.BuildState == NavmeshBuildState.NeedsRecovery) - { - // Special handling is needed since the normal state transition - // never expects this state. - if (SetInputControl(true)) - { - SetConfigControl(true); - } - mSelectedControl = ControlType.Input; - mLastBuildState = NavmeshBuildState.NeedsRecovery; - } - else - PerformStateTransition(); - - mIsActive = true; - return true; - } - - public void Exit() - { - ExitChildControls(); - - if (mContext.Build != null) - { - mContext.AbortAllReqests("Build controller exiting"); - mContext.Build.CleanBuild(); - } - - mLogger.ResetLog(); - mIsActive = false; - } - - public void Update() - { - if (!mIsActive) - return; - - NavmeshBuild build = mContext.Build; - - if (!build) - // Asset was deleted. - return; - - NavmeshBuildState buildState = build.BuildState; - - if (HasCriticalFailure) - { - if (buildState == NavmeshBuildState.Inactive) - { - // A reset has been performed. OK to go back to normal - // operation. - PerformStateTransition(); - } - // Never do more than a recovery during an update. - return; - } - - if (mLastBuildState != buildState) - PerformStateTransition(); - - if (mOverrideControl != null) - { - mOverrideControl.Update(); - // No other operations allowed. - } - else - { - if (mInputCon.IsActive) - mInputCon.Update(); - - if (mConfigCon.IsActive) - mInputCon.Update(); - - if (mBuildCon != null) - mBuildCon.Update(); - - ManageNMGenRequests(); - ManageTileRequests(); - } - - if (build.IsDirty) - { - EditorUtility.SetDirty(build); - build.IsDirty = false; - } - } - - private void ManageNMGenRequests() - { - mLogger.ResetLog(); - - TileBuildData tdata = mContext.Build.BuildData; - - // Due to concurrency with the input build, this method - // does not log things via the context. - - List requests = mContext.NMGenTasks; - - for (int i = requests.Count - 1; i >= 0; i--) - { - NMGenTask item = requests[i]; - - if (item.IsFinished) - { - requests.RemoveAt(i); - - NavmeshBuild build = mContext.Build; - - if (!build) - // Asset was deleted. - continue; - - string tileText = string.Format("({0},{1})", item.TileX, item.TileZ); - - switch (item.TaskState) - { - case BuildTaskState.Aborted: - - mLogger.Log(item.Messages); - mLogger.PostError("Tile build failed: " + tileText, build); - - tdata.SetAsFailed(item.TileX, item.TileZ); - - break; - - case BuildTaskState.Complete: - - NMGenAssets r = item.Result; - - if (r.NoResult) - { - mLogger.PostTrace("NMGen build complete. Tile is empty: " + tileText - , item.Messages, build); - - tdata.SetAsEmpty(r.TileX, r.TileZ); - } - else - { - tdata.SetWorkingData(r.TileX, r.TileZ, r.PolyMesh, r.DetailMesh); - - mLogger.PostTrace("NMGen build complete: " + tileText - , item.Messages, build); - - mContext.QueueTask(mLogger,r.TileX, r.TileZ - , r.PolyMesh, r.DetailMesh - , (build.Config.BuildFlags & NMGenBuildFlag.BVTreeEnabled) != 0 - , item.Priority); - } - - break; - } - } - else if (item.TaskState == BuildTaskState.InProgress - && tdata.GetState(item.TileX, item.TileZ) != TileBuildState.InProgress) - { - // Transition to the in-progress state. - tdata.SetAsInProgress(item.TileX, item.TileZ); - } - } - } - - private void ManageTileRequests() - { - TileBuildData tdata = mContext.Build.BuildData; - - mLogger.ResetLog(); - - // Due to concurrency with the input build, this method - // does not log things via the context. - - List requests = mContext.TileTasks; - - for (int i = requests.Count - 1; i >= 0; i--) - { - TileBuildTask item = requests[i]; - - if (item.IsFinished) - { - requests.RemoveAt(i); - - NavmeshBuild build = mContext.Build; - - if (!build) - // Asset was deleted. - continue; - - string tileText = string.Format("({0},{1})", item.TileX, item.TileZ); - - switch (item.TaskState) - { - case BuildTaskState.Aborted: - - mLogger.Log(item.Messages); - mLogger.PostError("Tile build failed: " + tileText, build); - - tdata.SetAsFailed(item.TileX, item.TileZ); - - break; - - case BuildTaskState.Complete: - - TileBuildAssets r = item.Result; - - string msg; - - if (r.NoResult) - { - msg = "Tile build complete. Tile is empty: " + tileText; - tdata.SetAsEmpty(r.TileX, r.TileZ); - } - else - { - msg = "Tile build complete: " + tileText; - tdata.SetWorkingData(r.TileX, r.TileZ, r.Tile, r.PolyCount); - } - - mLogger.PostTrace(msg, item.Messages, build); - - break; - } - } - } - } - - public void OnGUI(Rect area, bool includeMain) - { - if (!mIsActive) - return; - - if (mSelectedStyle == null) - { - // Initial setup required. - mSelectedStyle = new GUIStyle(GUI.skin.box); - mSelectedStyle.normal.textColor = ControlUtil.StandardHighlight; - - mUnselectedStyle = new GUIStyle(GUI.skin.box); - - Color c = Color.white; - c.a = 0.75f; - - mUnselectedStyle.normal.textColor = c; - - } - - // Setup... - - mContext.HideMain = !includeMain; - - Rect selectArea = new Rect(area.x - , area.y - , area.width - ControlUtil.ButtonAreaWidth - MarginSize - , SelectAreaHeight); - - Rect ma = new Rect(area.x - , selectArea.yMax + MarginSize - , selectArea.width - , area.height - selectArea.height - MarginSize); - - mContext.MainArea = ma; - - mContext.ButtonArea = new Rect(selectArea.xMax + MarginSize - , area.y - , ControlUtil.ButtonAreaWidth - , area.height); - - // Handle the main display area. - - if (mOverrideControl != null) - mOverrideControl.OnGUI(); - else - { - switch (mSelectedControl) - { - case ControlType.Build: - - mBuildCon.OnGUI(); - break; - - case ControlType.Config: - - mConfigCon.OnGUI(); - break; - - case ControlType.Input: - - mInputCon.OnGUI(); - break; - } - } - - if (includeMain) - { - // Draw the panel selection controls. - - const float bwidth = 100; - - GUILayout.BeginArea(selectArea); - GUILayout.BeginHorizontal(); - - GUI.enabled = mInputCon.IsActive; - - GUIStyle style = (GUI.enabled && mSelectedControl == ControlType.Input) - ? mSelectedStyle : mUnselectedStyle; - - if (GUILayout.Button("Input", style, GUILayout.Width(bwidth))) - mSelectedControl = ControlType.Input; - - GUI.enabled = mConfigCon.IsActive; - - style = (GUI.enabled && mSelectedControl == ControlType.Config) - ? mSelectedStyle : mUnselectedStyle; - - if (GUILayout.Button("Configuration", style, GUILayout.Width(bwidth))) - mSelectedControl = ControlType.Config; - - GUI.enabled = (mBuildCon != null); - - style = (GUI.enabled && mSelectedControl == ControlType.Build) - ? mSelectedStyle : mUnselectedStyle; - - if (GUILayout.Button("Builder", style, GUILayout.Width(bwidth))) - mSelectedControl = ControlType.Build; - - GUI.enabled = true; - - GUILayout.FlexibleSpace(); - - UnityBuildContext.TraceEnabled = - GUILayout.Toggle(UnityBuildContext.TraceEnabled, "Trace"); - - GUILayout.Space(MarginSize); - - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - } - - if (mDebugContext.NeedsRepaint || mContext.Selection.IsDirty) - { - // Debug.Log("Build Controller: Repaint Triggered"); - mDebugContext.NeedsRepaint = false; - mContext.Selection.IsDirty = false; - SceneView.RepaintAll(); - } - } - - public void OnSceneGUI() - { - mDebugContext.OnSceneGUI(); - } - - private void PerformStateTransition() - { - mContext.Selection.ClearSelection(); - - mSelectedControl = 0; // Will always change during a transition. - - if (mOverrideControl != null) - { - // Always get rid of the override control. A new one - // will be created as needed. - mOverrideControl.Exit(); - mOverrideControl = null; - } - - NavmeshBuild build = mContext.Build; // Note: Caller already checked for null. - NavmeshBuildState buildState = build.BuildState; - - // No early exits after this point. - - // Debug.Log("Transition: " + buildState); - - switch (buildState) - { - case NavmeshBuildState.Inactive: - - // Needs first time compile of input data. - - ExitChildControls(); - - if (SetInputControl(true)) - mSelectedControl = ControlType.Input; - - break; - - case NavmeshBuildState.InputCompiled: - - // Let user update config before preparing the build. - - SetBuildControl(false); - - if (SetConfigControl(true) && SetInputControl(true)) - mSelectedControl = ControlType.Config; - - break; - - case NavmeshBuildState.NeedsRecovery: - - ExitChildControls(); - SetCriticalFailure("Internal error: Unexpected loss of input data."); - - break; - - case NavmeshBuildState.Buildable: - - if (SetBuildControl(true) - && SetConfigControl(true) - && SetInputControl(true)) - { - mSelectedControl = ControlType.Build; - } - - break; - - case NavmeshBuildState.Invalid: - - ExitChildControls(); - - mOverrideControl = new CoreFailureControl(); - mOverrideControl.Enter(mContext, mDebugContext); - - break; - - default: - - SetCriticalFailure("Internal error. Unhandled build state: " + buildState); - break; - } - - // Note: Don't requery the build. This is the state that was - // handled. - mLastBuildState = buildState; - - mDebugContext.NeedsRepaint = true; - } - - private bool SetInputControl(bool enabled) - { - if (enabled) - { - if (!mInputCon.IsActive) - { - if (!mInputCon.Enter(mContext, mDebugContext)) - { - SetCriticalFailure(mInputCon.GetType()); - return false; - } - } - } - else if (mInputCon.IsActive) - mInputCon.Exit(); - - return true; - } - - private bool SetConfigControl(bool enabled) - { - if (enabled) - { - if (!mConfigCon.IsActive) - { - if (!mConfigCon.Enter(mContext, mDebugContext)) - { - SetCriticalFailure(mConfigCon.GetType()); - return false; - } - } - } - else if (mConfigCon.IsActive) - mConfigCon.Exit(); - - return true; - } - - private bool SetBuildControl(bool enabled) - { - // Note: Can't be used to change tye type of the build control. - - if (enabled) - { - if (mBuildCon != null) - return true; - - IBuildControl con; - - if (mContext.Build.BuildData.IsTiled) - con = new MultiTileBuildControl(); - else - con = new SingleTileBuildControl(); - - if (con.Enter(mContext, mDebugContext)) - { - mBuildCon = con; - return true; - } - - return false; - } - - if (mBuildCon != null) - { - mBuildCon.Exit(); - mBuildCon = null; - } - - return true; - } - - private void ExitChildControls() - { - if (mOverrideControl != null) - { - mOverrideControl.Exit(); - mOverrideControl = null; - } - - SetInputControl(false); - SetConfigControl(false); - SetBuildControl(false); - - mSelectedControl = 0; - } - - private bool HasCriticalFailure - { - get { return (mOverrideControl is FailureControl); } - } - - private void SetCriticalFailure(string message) - { - ExitChildControls(); - - // Cleanup, just in case the critical failure effected task - // management... - mContext.AbortAllReqests("Critical failure."); - - mOverrideControl = new FailureControl(message); - mOverrideControl.Enter(mContext, mDebugContext); - } - - private void SetCriticalFailure(System.Type type) - { - SetCriticalFailure("Internal error: Coult not initialize control: " - + type.ToString()); - } - - public static string FlattenMessages(string[] msgs) - { - if (msgs == null || msgs.Length == 0) - return ""; - - if (msgs.Length == 0) - return ""; - - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - - foreach (string msg in msgs) - { - sb.AppendLine(msg); - } - - return sb.ToString().Trim(); - } - - public static void PostError(System.Type typ - , string summary - , string[] messages - , Object context) - { - Debug.LogError(string.Format("{0}: {1}\n{2}" - , typ.Name - , summary - , FlattenMessages(messages)), context); - } - - public static void PostTrace(System.Type typ - , string summary - , string[] messages - , Object context) - { - Debug.Log(string.Format("{0}: {1}\n{2}" - , typ.Name - , summary - , FlattenMessages(messages)), context); - } - } -} diff --git a/critterai/.svn/pristine/50/50afd32cfd1aeeb57400ab0401d137beef4d5ba8.svn-base b/critterai/.svn/pristine/50/50afd32cfd1aeeb57400ab0401d137beef4d5ba8.svn-base deleted file mode 100644 index c88f2492..00000000 --- a/critterai/.svn/pristine/50/50afd32cfd1aeeb57400ab0401d137beef4d5ba8.svn-base +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEditor; -using org.critterai.nav.u3d; -using org.critterai.u3d.editor; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Provides various navmesh build utility constants. (Editor Only) - /// - public static class NMBEditorUtil - { - /// - /// The standard label for NMGen and navmesh build related assets. - /// - public const string AssetLabel = "NMGen"; - - /// - /// The menu priority for the hight level build assets. - /// - public const int BuildGroup = EditorUtil.AssetGroup; - - /// - /// The menu priority for scene query assets. - /// - public const int SceneGroup = BuildGroup + 100; - - /// - /// The menu priority for input processor filter assets. - /// - public const int FilterGroup = BuildGroup + 200; - - /// - /// The menu priority for input processor area definition assets. - /// - public const int AreaGroup = BuildGroup + 300; - - /// - /// The menu priority for input processor compiler assets. - /// - public const int CompilerGroup = BuildGroup + 400; - - /// - /// The menu priority for input post-processor assets. - /// - public const int PostProcessGroup = BuildGroup + 500; - - internal static NavmeshBuildInfo GetConfig(NavmeshBuild build) - { - if (!build) - return null; - - NMGenParams config = build.Config.GetConfig(); - - NavmeshBuildInfo result = new NavmeshBuildInfo(); - - result.tileSize = config.TileSize; - result.walkableHeight = config.WalkableHeight; - result.walkableRadius = config.WalkableRadius; - result.walkableStep = config.WalkableStep; - result.xzCellSize = config.XZCellSize; - result.yCellSize = config.YCellSize; - result.borderSize = config.BorderSize; - result.inputScene = EditorApplication.currentScene; - - return result; - } - } -} diff --git a/critterai/.svn/pristine/50/50cbc32e2d36c45c2ee23809e5d2965de0db9bb8.svn-base b/critterai/.svn/pristine/50/50cbc32e2d36c45c2ee23809e5d2965de0db9bb8.svn-base deleted file mode 100644 index c80d1717..00000000 --- a/critterai/.svn/pristine/50/50cbc32e2d36c45c2ee23809e5d2965de0db9bb8.svn-base +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNAVMESHBUILDER_H -#define DETOURNAVMESHBUILDER_H - -#include "DetourAlloc.h" - -/// Represents the source data used to build an navigation mesh tile. -/// @ingroup detour -struct dtNavMeshCreateParams -{ - - /// @name Polygon Mesh Attributes - /// Used to create the base navigation graph. - /// See #rcPolyMesh for details related to these attributes. - /// @{ - - const unsigned short* verts; ///< The polygon mesh vertices. [(x, y, z) * #vertCount] [Unit: vx] - int vertCount; ///< The number vertices in the polygon mesh. [Limit: >= 3] - const unsigned short* polys; ///< The polygon data. [Size: #polyCount * 2 * #nvp] - const unsigned short* polyFlags; ///< The user defined flags assigned to each polygon. [Size: #polyCount] - const unsigned char* polyAreas; ///< The user defined area ids assigned to each polygon. [Size: #polyCount] - int polyCount; ///< Number of polygons in the mesh. [Limit: >= 1] - int nvp; ///< Number maximum number of vertices per polygon. [Limit: >= 3] - - /// @} - /// @name Height Detail Attributes (Optional) - /// See #rcPolyMeshDetail for details related to these attributes. - /// @{ - - const unsigned int* detailMeshes; ///< The height detail sub-mesh data. [Size: 4 * #polyCount] - const float* detailVerts; ///< The detail mesh vertices. [Size: 3 * #detailVertsCount] [Unit: wu] - int detailVertsCount; ///< The number of vertices in the detail mesh. - const unsigned char* detailTris; ///< The detail mesh triangles. [Size: 4 * #detailTriCount] - int detailTriCount; ///< The number of triangles in the detail mesh. - - /// @} - /// @name Off-Mesh Connections Attributes (Optional) - /// Used to define a custom point-to-point edge within the navigation graph, an - /// off-mesh connection is a user defined traversable connection made up to two vertices, - /// at least one of which resides within a navigation mesh polygon. - /// @{ - - /// Off-mesh connection vertices. [(ax, ay, az, bx, by, bz) * #offMeshConCount] [Unit: wu] - const float* offMeshConVerts; - /// Off-mesh connection radii. [Size: #offMeshConCount] [Unit: wu] - const float* offMeshConRad; - /// User defined flags assigned to the off-mesh connections. [Size: #offMeshConCount] - const unsigned short* offMeshConFlags; - /// User defined area ids assigned to the off-mesh connections. [Size: #offMeshConCount] - const unsigned char* offMeshConAreas; - /// The permitted travel direction of the off-mesh connections. [Size: #offMeshConCount] - /// - /// 0 = Travel only from endpoint A to endpoint B.
- /// #DT_OFFMESH_CON_BIDIR = Bidirectional travel. - const unsigned char* offMeshConDir; - /// The user defined ids of the off-mesh connection. [Size: #offMeshConCount] - const unsigned int* offMeshConUserID; - /// The number of off-mesh connections. [Limit: >= 0] - int offMeshConCount; - - /// @} - /// @name Tile Attributes - /// @note The tile grid/layer data can be left at zero if the destination is a single tile mesh. - /// @{ - - unsigned int userId; ///< The user defined id of the tile. - int tileX; ///< The tile's x-grid location within the multi-tile destination mesh. (Along the x-axis.) - int tileY; ///< The tile's y-grid location within the multi-tile desitation mesh. (Along the z-axis.) - int tileLayer; ///< The tile's layer within the layered destination mesh. [Limit: >= 0] (Along the y-axis.) - float bmin[3]; ///< The minimum bounds of the tile. [(x, y, z)] [Unit: wu] - float bmax[3]; ///< The maximum bounds of the tile. [(x, y, z)] [Unit: wu] - - /// @} - /// @name General Configuration Attributes - /// @{ - - float walkableHeight; ///< The agent height. [Unit: wu] - float walkableRadius; ///< The agent radius. [Unit: wu] - float walkableClimb; ///< The agent maximum traversable ledge. (Up/Down) [Unit: wu] - float cs; ///< The xz-plane cell size of the polygon mesh. [Limit: > 0] [Unit: wu] - float ch; ///< The y-axis cell height of the polygon mesh. [Limit: > 0] [Unit: wu] - - /// True if a bounding volume tree should be built for the tile. - /// @note The BVTree is not normally needed for layered navigation meshes. - bool buildBvTree; - - /// @} -}; - -/// Builds navigation mesh tile data from the provided tile creation data. -/// @ingroup detour -/// @param[in] params Tile creation data. -/// @param[out] outData The resulting tile data. -/// @param[out] outDataSize The size of the tile data array. -/// @return True if the tile data was successfully created. -bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize); - -/// Swaps the endianess of the tile data's header (#dtMeshHeader). -/// @param[in,out] data The tile data array. -/// @param[in] dataSize The size of the data array. -bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize); - -/// Swaps endianess of the tile data. -/// @param[in,out] data The tile data array. -/// @param[in] dataSize The size of the data array. -bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize); - -#endif // DETOURNAVMESHBUILDER_H - -// This section contains detailed documentation for members that don't have -// a source file. It reduces clutter in the main section of the header. - -/** - -@struct dtNavMeshCreateParams -@par - -This structure is used to marshal data between the Recast mesh generation pipeline and Detour navigation components. - -See the rcPolyMesh and rcPolyMeshDetail documentation for detailed information related to mesh structure. - -Units are usually in voxels (vx) or world units (wu). The units for voxels, grid size, and cell size -are all based on the values of #cs and #ch. - -The standard navigation mesh build process is to create tile data using dtCreateNavMeshData, then add the tile -to a navigation mesh using either the dtNavMesh single tile init() function or the dtNavMesh::addTile() -function. - -@see dtCreateNavMeshData - -*/ \ No newline at end of file diff --git a/critterai/.svn/pristine/51/5101ae5fca309e1a49e8aee4e3f85755c03b47bd.svn-base b/critterai/.svn/pristine/51/5101ae5fca309e1a49e8aee4e3f85755c03b47bd.svn-base deleted file mode 100644 index c5768dea..00000000 --- a/critterai/.svn/pristine/51/5101ae5fca309e1a49e8aee4e3f85755c03b47bd.svn-base +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal class TileSelection - { - public const int NoSelection = -1; - - private readonly NavmeshBuild mBuild; - - private bool mIsDirty; - - private int mSelectedX = NoSelection; - private int mSelectedZ = NoSelection; - private int mZoneSize = 1; - - public NavmeshBuild Build { get { return mBuild ? mBuild : null; } } - - public int SelectedX { get { return mSelectedX; } } - public int SelectedZ { get { return mSelectedZ; } } - - public int ZoneSize - { - get { return mZoneSize; } - set - { - if (mZoneSize != value) - { - mZoneSize = Mathf.Max(0, value); - mIsDirty = true; - } - } - } - - public bool IsDirty - { - get { return mIsDirty; } - set { mIsDirty = value; } - } - - public TileZone Zone - { - get - { - if (!mBuild) - return new TileZone(); - - return new TileZone(Mathf.Max(0, mSelectedX - mZoneSize) - , Mathf.Max(0, mSelectedZ - mZoneSize) - , Mathf.Min(mBuild.TileSetDefinition.Width - 1, mSelectedX + mZoneSize) - , Mathf.Min(mBuild.TileSetDefinition.Depth - 1, mSelectedZ + mZoneSize)); - } - } - - public bool HasSelection - { - get - { - return mBuild && !(mSelectedX == NoSelection || mBuild.TileSetDefinition == null); - } - } - - public TileSelection(NavmeshBuild build) - { - if (!build) - throw new System.ArgumentNullException(); - - mBuild = build; - } - - public bool Validate() - { - SetSelection(mSelectedX, mSelectedZ); - return (mSelectedX != NoSelection); - } - - public void SetSelection(int tx, int tz) - { - if (!mBuild) - return; - - TileSetDefinition tdef = mBuild.TileSetDefinition; - - if (tx < 0 || tz < 0 - || tdef == null - || tx > tdef.Width - 1 - || tz > tdef.Depth - 1) - { - ClearSelection(); - return; - } - - if (mSelectedX != tx) - { - mSelectedX = tx; - mIsDirty = true; - } - - if (mSelectedZ != tz) - { - mSelectedZ = tz; - mIsDirty = true; - } - } - - public void ClearSelection() - { - if (mSelectedX == NoSelection) - return; - - mSelectedX = NoSelection; - mSelectedZ = NoSelection; - - mIsDirty = true; - } - } -} diff --git a/critterai/.svn/pristine/52/521e1693738d9e85d22006b6be1e86fc2a2c46cc.svn-base b/critterai/.svn/pristine/52/521e1693738d9e85d22006b6be1e86fc2a2c46cc.svn-base deleted file mode 100644 index 01f94cb6..00000000 --- a/critterai/.svn/pristine/52/521e1693738d9e85d22006b6be1e86fc2a2c46cc.svn-base +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include "DetourNavMeshQuery.h" -#include "DetourEx.h" - -// Returns a random number [0..1) -static float frand() -{ - return (float)rand()/(float)RAND_MAX; -} - -extern "C" -{ - EXPORT_API dtStatus dtnqBuildDTNavQuery(dtNavMesh* pNavMesh - , const int maxNodes - , dtNavMeshQuery** ppNavQuery) - { - // Initialize the build context. - - if (!pNavMesh) - return DT_FAILURE + DT_INVALID_PARAM; - - dtNavMeshQuery* pNavQuery = dtAllocNavMeshQuery(); - if (!pNavQuery) - return DT_FAILURE + DT_OUT_OF_MEMORY; - - dtStatus status = pNavQuery->init(pNavMesh, maxNodes); - if (dtStatusFailed(status)) - { - dtFreeNavMeshQuery(pNavQuery); - return status; - } - - *ppNavQuery = pNavQuery; - - return DT_SUCCESS; - } - - EXPORT_API void dtnqFree(dtNavMeshQuery** pNavQuery) - { - dtFreeNavMeshQuery(*pNavQuery); - } - - EXPORT_API dtStatus dtqGetPolyWallSegments(dtNavMeshQuery* query - , dtPolyRef ref - , const dtQueryFilter* filter - , float* segmentVerts - , dtPolyRef* segmentRefs - , int* segmentCount - , const int maxSegments) - { - return query->getPolyWallSegments(ref - , filter - , segmentVerts - , segmentRefs - , segmentCount - , maxSegments); - } - - EXPORT_API dtStatus dtqFindNearestPoly(dtNavMeshQuery* query - , const float* center - , const float* extents - , const dtQueryFilter* filter - , rcnNavmeshPoint* nearest) - { - return query->findNearestPoly(center - , extents - , filter - , &nearest->polyRef - , &nearest->point[0]); - } - - EXPORT_API dtStatus dtqQueryPolygons(dtNavMeshQuery* query - , const float* center - , const float* extents - , const dtQueryFilter* filter - , dtPolyRef* polyIds - , int* polyCount - , const int maxPolys) - { - return query->queryPolygons(center - , extents - , filter - , polyIds - , polyCount - , maxPolys); - } - - EXPORT_API dtStatus dtqFindPolysAroundCircle(dtNavMeshQuery* query - , dtPolyRef startRef - , const float* centerPos - , const float radius - , const dtQueryFilter* filter - , dtPolyRef* resultPolyRefs - , dtPolyRef* resultParentRefs - , float* resultCosts - , int* resultCount - , const int maxResult) - { - return query->findPolysAroundCircle(startRef - , centerPos - , radius - , filter - , resultPolyRefs - , resultParentRefs - , resultCosts - , resultCount - , maxResult); - } - - EXPORT_API dtStatus dtqFindPolysAroundShape(dtNavMeshQuery* query - , dtPolyRef startRef - , const float* verts - , const int nverts - , const dtQueryFilter* filter - , dtPolyRef* resultRef - , dtPolyRef* resultParent - , float* resultCost - , int* resultCount - , const int maxResult) - { - return query->findPolysAroundShape(startRef - , verts - , nverts - , filter - , resultRef - , resultParent - , resultCost - , resultCount - , maxResult); - } - - EXPORT_API dtStatus dtqFindLocalNeighbourhood(dtNavMeshQuery* query - , dtPolyRef startRef - , const float* centerPos - , const float radius - , const dtQueryFilter* filter - , dtPolyRef* resultRef - , dtPolyRef* resultParent - , int* resultCount - , const int maxResult) - { - return query->findLocalNeighbourhood(startRef - , centerPos - , radius - , filter - , resultRef - , resultParent - , resultCount - , maxResult); - } - - EXPORT_API dtStatus dtqClosestPointOnPoly(dtNavMeshQuery* query - , dtPolyRef ref - , const float* pos - , float* closest) - { - return query->closestPointOnPoly(ref, pos, closest); - } - - EXPORT_API dtStatus dtqClosestPointOnPolyBoundary(dtNavMeshQuery* query - , dtPolyRef ref - , const float* pos - , float* closest) - { - return query->closestPointOnPolyBoundary(ref, pos, closest); - } - - EXPORT_API dtStatus dtqGetPolyHeight(dtNavMeshQuery* query - , rcnNavmeshPoint pos - , float* height) - { - return query->getPolyHeight(pos.polyRef, &pos.point[0], height); - } - - EXPORT_API dtStatus dtqFindDistanceToWall(dtNavMeshQuery* query - , rcnNavmeshPoint centerPos - , const float maxRadius - , const dtQueryFilter* filter - , float* hitDist - , float* hitPos - , float* hitNormal) - { - return query->findDistanceToWall(centerPos.polyRef - , ¢erPos.point[0] - , maxRadius - , filter - , hitDist - , hitPos - , hitNormal); - } - - EXPORT_API dtStatus dtqFindPath(dtNavMeshQuery* query - , rcnNavmeshPoint startPos - , rcnNavmeshPoint endPos - , const dtQueryFilter* filter - , dtPolyRef* path - , int* pathCount - , const int maxPath) - { - return query->findPath(startPos.polyRef - , endPos.polyRef - , &startPos.point[0] - , &endPos.point[0] - , filter - , path - , pathCount - , maxPath); - } - - EXPORT_API dtStatus dtqFindPathExt(dtNavMeshQuery* query - , rcnNavmeshPoint* startPos - , rcnNavmeshPoint* endPos - , const float* extents - , const dtQueryFilter* filter - , dtPolyRef* path - , int* pathCount - , const int maxPath) - { - if (startPos->polyRef == 0) - { - dtStatus status = query->findNearestPoly(&startPos->point[0] - , extents - , filter - , &startPos->polyRef - , &startPos->point[0]); - if (dtStatusFailed(status)) - return status; - } - - if (endPos->polyRef == 0) - { - dtStatus status = query->findNearestPoly(&endPos->point[0] - , extents - , filter - , &endPos->polyRef - , &endPos->point[0]); - if (dtStatusFailed(status)) - return status; - } - - if (startPos->polyRef == 0 || endPos->polyRef == 0) - // One of the searches failed. - return DT_FAILURE | DT_INVALID_PARAM; - - return query->findPath(startPos->polyRef - , endPos->polyRef - , &startPos->point[0] - , &endPos->point[0] - , filter - , path - , pathCount - , maxPath); - } - - EXPORT_API bool dtqIsInClosedList(dtNavMeshQuery* query - , dtPolyRef ref) - { - return query->isInClosedList(ref); - } - - EXPORT_API bool dtqIsValidPolyRef(dtNavMeshQuery* query - , dtPolyRef ref - , const dtQueryFilter* filter) - { - return query->isValidPolyRef(ref, filter); - } - - EXPORT_API dtStatus dtqRaycast(dtNavMeshQuery* query - , rcnNavmeshPoint startPos - , const float* endPos - , const dtQueryFilter* filter - , float* t - , float* hitNormal - , dtPolyRef* path - , int* pathCount - , const int maxPath) - { - return query->raycast(startPos.polyRef - , &startPos.point[0] - , endPos - , filter - , t - , hitNormal - , path - , pathCount - , maxPath); - } - - EXPORT_API dtStatus dtqFindStraightPath(dtNavMeshQuery* query - , const float* startPos - , const float* endPos - , const dtPolyRef* path - , const int pathStart - , const int pathSize - , float* straightPath - , unsigned char* straightPathFlags - , dtPolyRef* straightPathRefs - , int* straightPathCount - , const int maxStraightPath) - { - return query->findStraightPath(startPos - , endPos - , &path[pathStart] - , pathSize - , straightPath - , straightPathFlags - , straightPathRefs - , straightPathCount - , maxStraightPath); - } - - EXPORT_API dtStatus dtqMoveAlongSurface(dtNavMeshQuery* query - , rcnNavmeshPoint startPos - , const float* endPos - , const dtQueryFilter* filter - , float* resultPos - , dtPolyRef* visited - , int* visitedCount - , const int maxVisitedSize) - { - return query->moveAlongSurface(startPos.polyRef - , &startPos.point[0] - , endPos - , filter - , resultPos - , visited - , visitedCount - , maxVisitedSize); - } - - EXPORT_API dtStatus dtqInitSlicedFindPath(dtNavMeshQuery* query - , rcnNavmeshPoint startPos - , rcnNavmeshPoint endPos - , const dtQueryFilter* filter) - { - return query->initSlicedFindPath(startPos.polyRef - , endPos.polyRef - , &startPos.point[0] - , &endPos.point[0] - , filter); - } - - EXPORT_API dtStatus dtqUpdateSlicedFindPath(dtNavMeshQuery* query - , const int maxIter - , int* doneIters) - { - return query->updateSlicedFindPath(maxIter, doneIters); - } - - EXPORT_API dtStatus dtqFinalizeSlicedFindPath(dtNavMeshQuery* query - , dtPolyRef* path - , int* pathCount - , const int maxPath) - { - return query->finalizeSlicedFindPath(path, pathCount, maxPath); - } - - EXPORT_API dtStatus dtqFindRandomPoint(dtNavMeshQuery* query - , const dtQueryFilter* filter - , rcnNavmeshPoint* randomPt) - { - return query->findRandomPoint(filter, frand, &randomPt->polyRef, &randomPt->point[0]); - } - - EXPORT_API dtStatus dtqFindRandomPointCircle(dtNavMeshQuery* query - , rcnNavmeshPoint start - , const float radius - , const dtQueryFilter* filter - , rcnNavmeshPoint* randomPt) - { - return query->findRandomPointAroundCircle(start.polyRef, &start.point[0], radius - , filter, frand - , &randomPt->polyRef, &randomPt->point[0]); - } - -} \ No newline at end of file diff --git a/critterai/.svn/pristine/52/5242b11c5fc5c3dd26362b7d65914aba8e09d8af.svn-base b/critterai/.svn/pristine/52/5242b11c5fc5c3dd26362b7d65914aba8e09d8af.svn-base deleted file mode 100644 index cb90382f..00000000 --- a/critterai/.svn/pristine/52/5242b11c5fc5c3dd26362b7d65914aba8e09d8af.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-util-u3d-editor")] -[assembly: AssemblyDescription("Shared editor utilities for CAI Unity products.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAI")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.5.0.0")] -[assembly: AssemblyFileVersion("0.5.0.0")] diff --git a/critterai/.svn/pristine/53/53f8da90f2819003ffe592bfc0c2cefa97dbc5c6.svn-base b/critterai/.svn/pristine/53/53f8da90f2819003ffe592bfc0c2cefa97dbc5c6.svn-base deleted file mode 100644 index d5d5bd84..00000000 --- a/critterai/.svn/pristine/53/53f8da90f2819003ffe592bfc0c2cefa97dbc5c6.svn-base +++ /dev/null @@ -1,733 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include -#include -#include "DetourNavMesh.h" -#include "DetourCommon.h" -#include "DetourNavMeshBuilder.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" - -static unsigned short MESH_NULL_IDX = 0xffff; - - -struct BVItem -{ - unsigned short bmin[3]; - unsigned short bmax[3]; - int i; -}; - -static int compareItemX(const void* va, const void* vb) -{ - const BVItem* a = (const BVItem*)va; - const BVItem* b = (const BVItem*)vb; - if (a->bmin[0] < b->bmin[0]) - return -1; - if (a->bmin[0] > b->bmin[0]) - return 1; - return 0; -} - -static int compareItemY(const void* va, const void* vb) -{ - const BVItem* a = (const BVItem*)va; - const BVItem* b = (const BVItem*)vb; - if (a->bmin[1] < b->bmin[1]) - return -1; - if (a->bmin[1] > b->bmin[1]) - return 1; - return 0; -} - -static int compareItemZ(const void* va, const void* vb) -{ - const BVItem* a = (const BVItem*)va; - const BVItem* b = (const BVItem*)vb; - if (a->bmin[2] < b->bmin[2]) - return -1; - if (a->bmin[2] > b->bmin[2]) - return 1; - return 0; -} - -static void calcExtends(BVItem* items, const int /*nitems*/, const int imin, const int imax, - unsigned short* bmin, unsigned short* bmax) -{ - bmin[0] = items[imin].bmin[0]; - bmin[1] = items[imin].bmin[1]; - bmin[2] = items[imin].bmin[2]; - - bmax[0] = items[imin].bmax[0]; - bmax[1] = items[imin].bmax[1]; - bmax[2] = items[imin].bmax[2]; - - for (int i = imin+1; i < imax; ++i) - { - const BVItem& it = items[i]; - if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0]; - if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1]; - if (it.bmin[2] < bmin[2]) bmin[2] = it.bmin[2]; - - if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0]; - if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1]; - if (it.bmax[2] > bmax[2]) bmax[2] = it.bmax[2]; - } -} - -inline int longestAxis(unsigned short x, unsigned short y, unsigned short z) -{ - int axis = 0; - unsigned short maxVal = x; - if (y > maxVal) - { - axis = 1; - maxVal = y; - } - if (z > maxVal) - { - axis = 2; - maxVal = z; - } - return axis; -} - -static void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNode, dtBVNode* nodes) -{ - int inum = imax - imin; - int icur = curNode; - - dtBVNode& node = nodes[curNode++]; - - if (inum == 1) - { - // Leaf - node.bmin[0] = items[imin].bmin[0]; - node.bmin[1] = items[imin].bmin[1]; - node.bmin[2] = items[imin].bmin[2]; - - node.bmax[0] = items[imin].bmax[0]; - node.bmax[1] = items[imin].bmax[1]; - node.bmax[2] = items[imin].bmax[2]; - - node.i = items[imin].i; - } - else - { - // Split - calcExtends(items, nitems, imin, imax, node.bmin, node.bmax); - - int axis = longestAxis(node.bmax[0] - node.bmin[0], - node.bmax[1] - node.bmin[1], - node.bmax[2] - node.bmin[2]); - - if (axis == 0) - { - // Sort along x-axis - qsort(items+imin, inum, sizeof(BVItem), compareItemX); - } - else if (axis == 1) - { - // Sort along y-axis - qsort(items+imin, inum, sizeof(BVItem), compareItemY); - } - else - { - // Sort along z-axis - qsort(items+imin, inum, sizeof(BVItem), compareItemZ); - } - - int isplit = imin+inum/2; - - // Left - subdivide(items, nitems, imin, isplit, curNode, nodes); - // Right - subdivide(items, nitems, isplit, imax, curNode, nodes); - - int iescape = curNode - icur; - // Negative index means escape. - node.i = -iescape; - } -} - -static int createBVTree(const unsigned short* verts, const int /*nverts*/, - const unsigned short* polys, const int npolys, const int nvp, - const float cs, const float ch, - const int /*nnodes*/, dtBVNode* nodes) -{ - // Build tree - BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP); - for (int i = 0; i < npolys; i++) - { - BVItem& it = items[i]; - it.i = i; - // Calc polygon bounds. - const unsigned short* p = &polys[i*nvp*2]; - it.bmin[0] = it.bmax[0] = verts[p[0]*3+0]; - it.bmin[1] = it.bmax[1] = verts[p[0]*3+1]; - it.bmin[2] = it.bmax[2] = verts[p[0]*3+2]; - - for (int j = 1; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - unsigned short x = verts[p[j]*3+0]; - unsigned short y = verts[p[j]*3+1]; - unsigned short z = verts[p[j]*3+2]; - - if (x < it.bmin[0]) it.bmin[0] = x; - if (y < it.bmin[1]) it.bmin[1] = y; - if (z < it.bmin[2]) it.bmin[2] = z; - - if (x > it.bmax[0]) it.bmax[0] = x; - if (y > it.bmax[1]) it.bmax[1] = y; - if (z > it.bmax[2]) it.bmax[2] = z; - } - // Remap y - it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs); - it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs); - } - - int curNode = 0; - subdivide(items, npolys, 0, npolys, curNode, nodes); - - dtFree(items); - - return curNode; -} - -static unsigned char classifyOffMeshPoint(const float* pt, const float* bmin, const float* bmax) -{ - static const unsigned char XP = 1<<0; - static const unsigned char ZP = 1<<1; - static const unsigned char XM = 1<<2; - static const unsigned char ZM = 1<<3; - - unsigned char outcode = 0; - outcode |= (pt[0] >= bmax[0]) ? XP : 0; - outcode |= (pt[2] >= bmax[2]) ? ZP : 0; - outcode |= (pt[0] < bmin[0]) ? XM : 0; - outcode |= (pt[2] < bmin[2]) ? ZM : 0; - - switch (outcode) - { - case XP: return 0; - case XP|ZP: return 1; - case ZP: return 2; - case XM|ZP: return 3; - case XM: return 4; - case XM|ZM: return 5; - case ZM: return 6; - case XP|ZM: return 7; - }; - return 0xff; -} - -// TODO: Better error handling. - -/// @par -/// -/// The output data array is allocated using the detour allocator (dtAlloc()). The method -/// used to free the memory will be determined by how the tile is added to the navigation -/// mesh. -/// -/// @see dtNavMesh, dtNavMesh::addTile() -bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize) -{ - if (params->nvp > DT_VERTS_PER_POLYGON) - return false; - if (params->vertCount >= 0xffff) - return false; - if (!params->vertCount || !params->verts) - return false; - if (!params->polyCount || !params->polys) - return false; - - const int nvp = params->nvp; - - // Classify off-mesh connection points. We store only the connections - // whose start point is inside the tile. - unsigned char* offMeshConClass = 0; - int storedOffMeshConCount = 0; - int offMeshConLinkCount = 0; - - if (params->offMeshConCount > 0) - { - offMeshConClass = (unsigned char*)dtAlloc(sizeof(unsigned char)*params->offMeshConCount*2, DT_ALLOC_TEMP); - if (!offMeshConClass) - return false; - - for (int i = 0; i < params->offMeshConCount; ++i) - { - offMeshConClass[i*2+0] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+0)*3], params->bmin, params->bmax); - offMeshConClass[i*2+1] = classifyOffMeshPoint(¶ms->offMeshConVerts[(i*2+1)*3], params->bmin, params->bmax); - - // Cound how many links should be allocated for off-mesh connections. - if (offMeshConClass[i*2+0] == 0xff) - offMeshConLinkCount++; - if (offMeshConClass[i*2+1] == 0xff) - offMeshConLinkCount++; - - if (offMeshConClass[i*2+0] == 0xff) - storedOffMeshConCount++; - } - } - - // Off-mesh connectionss are stored as polygons, adjust values. - const int totPolyCount = params->polyCount + storedOffMeshConCount; - const int totVertCount = params->vertCount + storedOffMeshConCount*2; - - // Find portal edges which are at tile borders. - int edgeCount = 0; - int portalCount = 0; - for (int i = 0; i < params->polyCount; ++i) - { - const unsigned short* p = ¶ms->polys[i*2*nvp]; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - edgeCount++; - - if (p[nvp+j] & 0x8000) - { - unsigned short dir = p[nvp+j] & 0xf; - if (dir != 0xf) - portalCount++; - } - } - } - - const int maxLinkCount = edgeCount + portalCount*2 + offMeshConLinkCount*2; - - // Find unique detail vertices. - int uniqueDetailVertCount = 0; - int detailTriCount = 0; - if (params->detailMeshes) - { - // Has detail mesh, count unique detail vertex count and use input detail tri count. - detailTriCount = params->detailTriCount; - for (int i = 0; i < params->polyCount; ++i) - { - const unsigned short* p = ¶ms->polys[i*nvp*2]; - int ndv = params->detailMeshes[i*4+1]; - int nv = 0; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - nv++; - } - ndv -= nv; - uniqueDetailVertCount += ndv; - } - } - else - { - // No input detail mesh, build detail mesh from nav polys. - uniqueDetailVertCount = 0; // No extra detail verts. - detailTriCount = 0; - for (int i = 0; i < params->polyCount; ++i) - { - const unsigned short* p = ¶ms->polys[i*nvp*2]; - int nv = 0; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - nv++; - } - detailTriCount += nv-2; - } - } - - // Calculate data size - const int headerSize = dtAlign4(sizeof(dtMeshHeader)); - const int vertsSize = dtAlign4(sizeof(float)*3*totVertCount); - const int polysSize = dtAlign4(sizeof(dtPoly)*totPolyCount); - const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount); - const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount); - const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount); - const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount); - const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0; - const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount); - - const int dataSize = headerSize + vertsSize + polysSize + linksSize + - detailMeshesSize + detailVertsSize + detailTrisSize + - bvTreeSize + offMeshConsSize; - - unsigned char* data = (unsigned char*)dtAlloc(sizeof(unsigned char)*dataSize, DT_ALLOC_PERM); - if (!data) - { - dtFree(offMeshConClass); - return false; - } - memset(data, 0, dataSize); - - unsigned char* d = data; - dtMeshHeader* header = (dtMeshHeader*)d; d += headerSize; - float* navVerts = (float*)d; d += vertsSize; - dtPoly* navPolys = (dtPoly*)d; d += polysSize; - d += linksSize; - dtPolyDetail* navDMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - float* navDVerts = (float*)d; d += detailVertsSize; - unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize; - dtBVNode* navBvtree = (dtBVNode*)d; d += bvTreeSize; - dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshConsSize; - - - // Store header - header->magic = DT_NAVMESH_MAGIC; - header->version = DT_NAVMESH_VERSION; - header->x = params->tileX; - header->y = params->tileY; - header->layer = params->tileLayer; - header->userId = params->userId; - header->polyCount = totPolyCount; - header->vertCount = totVertCount; - header->maxLinkCount = maxLinkCount; - dtVcopy(header->bmin, params->bmin); - dtVcopy(header->bmax, params->bmax); - header->detailMeshCount = params->polyCount; - header->detailVertCount = uniqueDetailVertCount; - header->detailTriCount = detailTriCount; - header->bvQuantFactor = 1.0f / params->cs; - header->offMeshBase = params->polyCount; - header->walkableHeight = params->walkableHeight; - header->walkableRadius = params->walkableRadius; - header->walkableClimb = params->walkableClimb; - header->offMeshConCount = storedOffMeshConCount; - header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0; - - const int offMeshVertsBase = params->vertCount; - const int offMeshPolyBase = params->polyCount; - - // Store vertices - // Mesh vertices - for (int i = 0; i < params->vertCount; ++i) - { - const unsigned short* iv = ¶ms->verts[i*3]; - float* v = &navVerts[i*3]; - v[0] = params->bmin[0] + iv[0] * params->cs; - v[1] = params->bmin[1] + iv[1] * params->ch; - v[2] = params->bmin[2] + iv[2] * params->cs; - } - // Off-mesh link vertices. - int n = 0; - for (int i = 0; i < params->offMeshConCount; ++i) - { - // Only store connections which start from this tile. - if (offMeshConClass[i*2+0] == 0xff) - { - const float* linkv = ¶ms->offMeshConVerts[i*2*3]; - float* v = &navVerts[(offMeshVertsBase + n*2)*3]; - dtVcopy(&v[0], &linkv[0]); - dtVcopy(&v[3], &linkv[3]); - n++; - } - } - - // Store polygons - // Mesh polys - const unsigned short* src = params->polys; - for (int i = 0; i < params->polyCount; ++i) - { - dtPoly* p = &navPolys[i]; - p->vertCount = 0; - p->flags = params->polyFlags[i]; - p->setArea(params->polyAreas[i]); - p->setType(DT_POLYTYPE_GROUND); - for (int j = 0; j < nvp; ++j) - { - if (src[j] == MESH_NULL_IDX) break; - p->verts[j] = src[j]; - if (src[nvp+j] & 0x8000) - { - // Border or portal edge. - unsigned short dir = src[nvp+j] & 0xf; - if (dir == 0xf) // Border - p->neis[j] = 0; - else if (dir == 0) // Portal x- - p->neis[j] = DT_EXT_LINK | 4; - else if (dir == 1) // Portal z+ - p->neis[j] = DT_EXT_LINK | 2; - else if (dir == 2) // Portal x+ - p->neis[j] = DT_EXT_LINK | 0; - else if (dir == 3) // Portal z- - p->neis[j] = DT_EXT_LINK | 6; - } - else - { - // Normal connection - p->neis[j] = src[nvp+j]+1; - } - - p->vertCount++; - } - src += nvp*2; - } - // Off-mesh connection vertices. - n = 0; - for (int i = 0; i < params->offMeshConCount; ++i) - { - // Only store connections which start from this tile. - if (offMeshConClass[i*2+0] == 0xff) - { - dtPoly* p = &navPolys[offMeshPolyBase+n]; - p->vertCount = 2; - p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0); - p->verts[1] = (unsigned short)(offMeshVertsBase + n*2+1); - p->flags = params->offMeshConFlags[i]; - p->setArea(params->offMeshConAreas[i]); - p->setType(DT_POLYTYPE_OFFMESH_CONNECTION); - n++; - } - } - - // Store detail meshes and vertices. - // The nav polygon vertices are stored as the first vertices on each mesh. - // We compress the mesh data by skipping them and using the navmesh coordinates. - if (params->detailMeshes) - { - unsigned short vbase = 0; - for (int i = 0; i < params->polyCount; ++i) - { - dtPolyDetail& dtl = navDMeshes[i]; - const int vb = (int)params->detailMeshes[i*4+0]; - const int ndv = (int)params->detailMeshes[i*4+1]; - const int nv = navPolys[i].vertCount; - dtl.vertBase = (unsigned int)vbase; - dtl.vertCount = (unsigned char)(ndv-nv); - dtl.triBase = (unsigned int)params->detailMeshes[i*4+2]; - dtl.triCount = (unsigned char)params->detailMeshes[i*4+3]; - // Copy vertices except the first 'nv' verts which are equal to nav poly verts. - if (ndv-nv) - { - memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv)); - vbase += (unsigned short)(ndv-nv); - } - } - // Store triangles. - memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount); - } - else - { - // Create dummy detail mesh by triangulating polys. - int tbase = 0; - for (int i = 0; i < params->polyCount; ++i) - { - dtPolyDetail& dtl = navDMeshes[i]; - const int nv = navPolys[i].vertCount; - dtl.vertBase = 0; - dtl.vertCount = 0; - dtl.triBase = (unsigned int)tbase; - dtl.triCount = (unsigned char)(nv-2); - // Triangulate polygon (local indices). - for (int j = 2; j < nv; ++j) - { - unsigned char* t = &navDTris[tbase*4]; - t[0] = 0; - t[1] = (unsigned char)(j-1); - t[2] = (unsigned char)j; - // Bit for each edge that belongs to poly boundary. - t[3] = (1<<2); - if (j == 2) t[3] |= (1<<0); - if (j == nv-1) t[3] |= (1<<4); - tbase++; - } - } - } - - // Store and create BVtree. - // TODO: take detail mesh into account! use byte per bbox extent? - if (params->buildBvTree) - { - createBVTree(params->verts, params->vertCount, params->polys, params->polyCount, - nvp, params->cs, params->ch, params->polyCount*2, navBvtree); - } - - // Store Off-Mesh connections. - n = 0; - for (int i = 0; i < params->offMeshConCount; ++i) - { - // Only store connections which start from this tile. - if (offMeshConClass[i*2+0] == 0xff) - { - dtOffMeshConnection* con = &offMeshCons[n]; - con->poly = (unsigned short)(offMeshPolyBase + n); - // Copy connection end-points. - const float* endPts = ¶ms->offMeshConVerts[i*2*3]; - dtVcopy(&con->pos[0], &endPts[0]); - dtVcopy(&con->pos[3], &endPts[3]); - con->rad = params->offMeshConRad[i]; - con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0; - con->side = offMeshConClass[i*2+1]; - if (params->offMeshConUserID) - con->userId = params->offMeshConUserID[i]; - n++; - } - } - - dtFree(offMeshConClass); - - *outData = data; - *outDataSize = dataSize; - - return true; -} - -bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/) -{ - dtMeshHeader* header = (dtMeshHeader*)data; - - int swappedMagic = DT_NAVMESH_MAGIC; - int swappedVersion = DT_NAVMESH_VERSION; - dtSwapEndian(&swappedMagic); - dtSwapEndian(&swappedVersion); - - if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) && - (header->magic != swappedMagic || header->version != swappedVersion)) - { - return false; - } - - dtSwapEndian(&header->magic); - dtSwapEndian(&header->version); - dtSwapEndian(&header->x); - dtSwapEndian(&header->y); - dtSwapEndian(&header->layer); - dtSwapEndian(&header->userId); - dtSwapEndian(&header->polyCount); - dtSwapEndian(&header->vertCount); - dtSwapEndian(&header->maxLinkCount); - dtSwapEndian(&header->detailMeshCount); - dtSwapEndian(&header->detailVertCount); - dtSwapEndian(&header->detailTriCount); - dtSwapEndian(&header->bvNodeCount); - dtSwapEndian(&header->offMeshConCount); - dtSwapEndian(&header->offMeshBase); - dtSwapEndian(&header->walkableHeight); - dtSwapEndian(&header->walkableRadius); - dtSwapEndian(&header->walkableClimb); - dtSwapEndian(&header->bmin[0]); - dtSwapEndian(&header->bmin[1]); - dtSwapEndian(&header->bmin[2]); - dtSwapEndian(&header->bmax[0]); - dtSwapEndian(&header->bmax[1]); - dtSwapEndian(&header->bmax[2]); - dtSwapEndian(&header->bvQuantFactor); - - // Freelist index and pointers are updated when tile is added, no need to swap. - - return true; -} - -/// @par -/// -/// @warning This function assumes that the header is in the correct endianess already. -/// Call #dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess -/// to start with. Call #dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from -/// native to foreign endianess. -bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) -{ - // Make sure the data is in right format. - dtMeshHeader* header = (dtMeshHeader*)data; - if (header->magic != DT_NAVMESH_MAGIC) - return false; - if (header->version != DT_NAVMESH_VERSION) - return false; - - // Patch header pointers. - const int headerSize = dtAlign4(sizeof(dtMeshHeader)); - const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount); - const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount); - const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount)); - const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount); - const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount); - const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount); - const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount); - const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); - - unsigned char* d = data + headerSize; - float* verts = (float*)d; d += vertsSize; - dtPoly* polys = (dtPoly*)d; d += polysSize; - /*dtLink* links = (dtLink*)d;*/ d += linksSize; - dtPolyDetail* detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - float* detailVerts = (float*)d; d += detailVertsSize; - /*unsigned char* detailTris = (unsigned char*)d;*/ d += detailTrisSize; - dtBVNode* bvTree = (dtBVNode*)d; d += bvtreeSize; - dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize; - - // Vertices - for (int i = 0; i < header->vertCount*3; ++i) - { - dtSwapEndian(&verts[i]); - } - - // Polys - for (int i = 0; i < header->polyCount; ++i) - { - dtPoly* p = &polys[i]; - // poly->firstLink is update when tile is added, no need to swap. - for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j) - { - dtSwapEndian(&p->verts[j]); - dtSwapEndian(&p->neis[j]); - } - dtSwapEndian(&p->flags); - } - - // Links are rebuild when tile is added, no need to swap. - - // Detail meshes - for (int i = 0; i < header->detailMeshCount; ++i) - { - dtPolyDetail* pd = &detailMeshes[i]; - dtSwapEndian(&pd->vertBase); - dtSwapEndian(&pd->triBase); - } - - // Detail verts - for (int i = 0; i < header->detailVertCount*3; ++i) - { - dtSwapEndian(&detailVerts[i]); - } - - // BV-tree - for (int i = 0; i < header->bvNodeCount; ++i) - { - dtBVNode* node = &bvTree[i]; - for (int j = 0; j < 3; ++j) - { - dtSwapEndian(&node->bmin[j]); - dtSwapEndian(&node->bmax[j]); - } - dtSwapEndian(&node->i); - } - - // Off-mesh Connections. - for (int i = 0; i < header->offMeshConCount; ++i) - { - dtOffMeshConnection* con = &offMeshCons[i]; - for (int j = 0; j < 6; ++j) - dtSwapEndian(&con->pos[j]); - dtSwapEndian(&con->rad); - dtSwapEndian(&con->poly); - } - - return true; -} diff --git a/critterai/.svn/pristine/54/544a6c58263054b2475fa0dd0339d3c1e83b8821.svn-base b/critterai/.svn/pristine/54/544a6c58263054b2475fa0dd0339d3c1e83b8821.svn-base deleted file mode 100644 index 3cf65228..00000000 --- a/critterai/.svn/pristine/54/544a6c58263054b2475fa0dd0339d3c1e83b8821.svn-base +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURASSERT_H -#define DETOURASSERT_H - -// Note: This header file's only purpose is to include define assert. -// Feel free to change the file and include your own implementation instead. - -#ifdef NDEBUG -// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ -# define dtAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false) -#else -# include -# define dtAssert assert -#endif - -#endif // DETOURASSERT_H diff --git a/critterai/.svn/pristine/54/549ae506823751964505ecfa1120a68151aa2a83.svn-base b/critterai/.svn/pristine/54/549ae506823751964505ecfa1120a68151aa2a83.svn-base deleted file mode 100644 index 831297ca..00000000 --- a/critterai/.svn/pristine/54/549ae506823751964505ecfa1120a68151aa2a83.svn-base +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#if NUNITY -using Vector2 = org.critterai.Vector2; -#else -using Vector2 = UnityEngine.Vector2; -#endif - -namespace org.critterai.geom -{ - /// - /// Provides 2D line and line segment utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Line2 - { - /// - /// Indicates whether or not line AB intersects line BC. (Integer version.) - /// - /// The x-value for point A on line AB. - /// The y-value for point A on line AB. - /// The x-value for point B on line AB. - /// The y-value for point B on line AB. - /// The x-value for point C on line CD. - /// The y-value for point C on line CD. - /// The x-value for point D on line CD. - /// The y-value for point D on line CD. - /// True if the two lines are either collinear or intersect at one point. - public static bool LinesIntersect(int ax, int ay, int bx, int by - , int cx, int cy, int dx, int dy) - { - int numerator = - ((ay - cy) * (dx - cx)) - ((ax - cx) * (dy - cy)); - int denominator = - ((bx - ax) * (dy - cy)) - ((by - ay) * (dx - cx)); - if (denominator == 0 && numerator != 0) - // Lines are parallel. - return false; - // Lines are collinear or intersect at a single point. - return true; - } - - /// - /// Indicates whether or not line AB intersects line BC. - /// - /// Point A on line AB. - /// Point B on ling AB. - /// Point C on line CD. - /// Point D on line CD. - /// True if the two lines are either collinear or intersect at one point. - public static bool LinesIntersect(Vector2 a, Vector2 b, Vector2 c, Vector2 d) - { - float numerator = ((a.y - c.y) * (d.x - c.x)) - ((a.x - c.x) * (d.y - c.y)); - float denominator = ((b.x - a.x) * (d.y - c.y)) - ((b.y - a.y) * (d.x - c.x)); - - if (denominator == 0 && numerator != 0) - // Lines are parallel. - return false; - - // Lines are collinear or intersect at a single point. - return true; - } - - /// - /// Returns the distance squared from point P to the nearest point on line segment AB. - /// - /// The point. - /// Endpoint A of line segment AB. - /// Endpoing B of line segment AB. - /// The distance squared from the point to line segment AB. - public static float GetPointSegmentDistanceSq(Vector2 p, Vector2 a, Vector2 b) - { - /* - * Reference: - * http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line AB that - * is closest to P and then calculate the distance between P and - * that point. - */ - - Vector2 deltaAB = b - a; - Vector2 deltaAP = p - a; - - float segmentABLengthSq = deltaAB.x * deltaAB.x + deltaAB.y * deltaAB.y; - - if (segmentABLengthSq < MathUtil.Epsilon) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y; - - float u = (deltaAP.x * deltaAB.x + deltaAP.y * deltaAB.y) / segmentABLengthSq; - - if (u < 0) - // Closest point on line AB is outside segment AB and - // closer to A. So return distanceSq from P to A. - return deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer - // to B. So return distanceSq from P to B. - return (p.x - b.x) * (p.x - b.x) + (p.y - b.y) * (p.y - b.y); - - // Closest point on lineAB is inside segment AB. So find the exact - // point on AB and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on - // the line segment. - float deltaX = (a.x + u * deltaAB.x) - p.x; - float deltaY = (a.y + u * deltaAB.y) - p.y; - - return deltaX * deltaX + deltaY * deltaY; - } - - /// - /// Returns the distance squared from point P to the nearest point on line AB. - /// - /// The point. - /// Point A on line AB. - /// Point B on line AB. - /// The distance squared from the point to line AB. - public static float GetPointLineDistanceSq(Vector2 p, Vector2 a, Vector2 b) - { - /* - * Reference: - * http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line AB that is - * closest to P and then calculate the distance between P and that - * point. - */ - - Vector2 deltaAB = b - a; - Vector2 deltaAP = p - a; - - float segmentABLengthSq = deltaAB.x * deltaAB.x + deltaAB.y * deltaAB.y; - - if (segmentABLengthSq < MathUtil.Epsilon) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAP.x * deltaAP.x + deltaAP.y * deltaAP.y; - - float u = (deltaAP.x * deltaAB.x + deltaAP.y * deltaAB.y) / segmentABLengthSq; - - // The calculation in parenthesis is the location of the point on - // the line segment. - float deltaX = (a.x + u * deltaAB.x) - p.x; - float deltaY = (a.y + u * deltaAB.y) - p.y; - - return deltaX * deltaX + deltaY * deltaY; - } - - /// - /// Returns the normalized vector that is perpendicular to line AB. (Costly method!) - /// - /// - /// - /// The direction of the vector will be to the right when viewed from point A to point B - /// along the line. - /// - /// - /// Special Case: A zero length vector will be returned if the points are collocated. - /// - /// - /// Point A on line AB. - /// Point B on line AB. - /// - /// The normalized vector that is perpendicular to line AB, or a zero length vector if the - /// points are collocated. - /// - public static Vector2 GetNormalAB(Vector2 a, Vector2 b) - { - if (Vector2Util.SloppyEquals(a, b, MathUtil.Tolerance)) - // Points do not form a line. - return new Vector2(); - - Vector2 result = Vector2Util.GetDirectionAB(a, b); - - float origX = result.x; - result.x = result.y; - result.y = -origX; - - return result; - } - - /// - /// Determines the relationship between lines AB and CD. - /// - /// - /// - /// While this check is technically inclusive of segment end points, floating point errors - /// can result in end point intersection being missed. If this matters, a - /// - /// SloppyEquals or similar test of the intersection point can be performed. - /// - /// - /// Point A on line AB. - /// Point B on ling AB. - /// Point C on line CD. - /// Point D on line CD. - /// The point of intersection, if applicable. - /// The relationship between lines AB and CD. - public static LineRelType GetRelationship(Vector2 a, Vector2 b, Vector2 c, Vector2 d - , out Vector2 intersectPoint) - { - Vector2 deltaAB = b - a; - Vector2 deltaCD = d - c; - Vector2 deltaCA = a - c; - - float numerator = (deltaCA.y * deltaCD.x) - (deltaCA.x * deltaCD.y); - float denominator = (deltaAB.x * deltaCD.y) - (deltaAB.y * deltaCD.x); - - // Exit early if the lines do not intersect at a single point. - if (denominator == 0) - { - intersectPoint = Vector2Util.Zero; - if (numerator == 0) - return LineRelType.Collinear; - return LineRelType.Parallel; - } - - // Lines definitely intersect at a single point. - - float factorAB = numerator / denominator; - float factorCD = ((deltaCA.y * deltaAB.x) - (deltaCA.x * deltaAB.y)) / denominator; - - intersectPoint = - new Vector2(a.x + (factorAB * deltaAB.x), a.y + (factorAB * deltaAB.y)); - - // Determine the type of intersection - if ((factorAB >= 0.0f) - && (factorAB <= 1.0f) - && (factorCD >= 0.0f) - && (factorCD <= 1.0f)) - { - return LineRelType.SegmentsIntersect; - } - else if ((factorCD >= 0.0f) && (factorCD <= 1.0f)) - { - return LineRelType.ALineCrossesBSeg; - } - else if ((factorAB >= 0.0f) && (factorAB <= 1.0f)) - { - return LineRelType.BLineCrossesASeg; - } - - return LineRelType.LinesIntersect; - } - } -} diff --git a/critterai/.svn/pristine/54/54f2a2343f2ec46813bb1ff25a540bb74617a209.svn-base b/critterai/.svn/pristine/54/54f2a2343f2ec46813bb1ff25a540bb74617a209.svn-base deleted file mode 100644 index dce23f6e..00000000 --- a/critterai/.svn/pristine/54/54f2a2343f2ec46813bb1ff25a540bb74617a209.svn-base +++ /dev/null @@ -1,5 +0,0 @@ -The source code in the 'Assets' directory structure is in the same -layout it should be if deployed directly to a Unity project. -(I.e. The 'Assets/CAI' directory can be dragged and dropped into -a Unity project.) The porject documentation contains some important -notes when using a source distribution. diff --git a/critterai/.svn/pristine/55/5500396da7eb3a61b7066a84d13c968a2b9458af.svn-base b/critterai/.svn/pristine/55/5500396da7eb3a61b7066a84d13c968a2b9458af.svn-base deleted file mode 100644 index 93905d8a..00000000 Binary files a/critterai/.svn/pristine/55/5500396da7eb3a61b7066a84d13c968a2b9458af.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/55/558c27f2e4410cbbb02704fa6c932fc39a6a139e.svn-base b/critterai/.svn/pristine/55/558c27f2e4410cbbb02704fa6c932fc39a6a139e.svn-base deleted file mode 100644 index 63a53370..00000000 --- a/critterai/.svn/pristine/55/558c27f2e4410cbbb02704fa6c932fc39a6a139e.svn-base +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmbuild.u3d.editor; -using org.critterai.u3d.editor; -using UnityEditor; -using UnityEngine; - -/// -/// Handles setting configuration values related to the Navmesh build. (Editor Only) -/// -/// -public sealed class NMBuildSettings - : EditorWindow -{ - private const string MaxConcurrKey = "org.critterai.nmbuild.MaxConcurrency"; - private const string WindowTitle = "Build Config"; - - void OnEnable() - { - minSize = new Vector2(250, 160); - } - - void OnGUI() - { - Rect area = new Rect(ControlUtil.MarginSize - , ControlUtil.MarginSize - , position.width - 2 * ControlUtil.MarginSize - , position.height - 2 * ControlUtil.MarginSize); - - GUILayout.BeginArea(area); - - GUILayout.Label("Maximum Concurrency"); - - int orig = BuildProcessor.MaxConcurrency; - - int val = (int)EditorGUILayout.Slider(orig, 1, System.Environment.ProcessorCount); - - if (orig != val) - BuildProcessor.MaxConcurrency = val; - - // TODO: Review threading recommendation after below noted bug is fixed. - GUILayout.Box("Recommended: " + BuildProcessor.DefaultConcurrency - + "\nWill take effect next processor start." - + "\nWarning: Threading bugs in Unity Editor 3.5 can cause problems if set" - + " to a higher value." - , EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - - GUILayout.Space(ControlUtil.MarginSize * 2); - - if (GUILayout.Button("Force Processor Reset")) - NavmeshBuildManager.ForceProcessorReset(); - - GUILayout.EndArea(); - } - - /// - /// Opens and focuses the build settings window. - /// - [MenuItem("CritterAI/Navmesh Build Settings", false, EditorUtil.ManagerGroup + 10)] - public static void OpenWindow() - { - NMBuildSettings window = EditorWindow.GetWindow(true - , WindowTitle); - - window.Show(); - window.Focus(); - } -} diff --git a/critterai/.svn/pristine/55/55a5f0d9cbc1bca4c65b7c847199529e172a65c0.svn-base b/critterai/.svn/pristine/55/55a5f0d9cbc1bca4c65b7c847199529e172a65c0.svn-base deleted file mode 100644 index 63f8b0fe..00000000 --- a/critterai/.svn/pristine/55/55a5f0d9cbc1bca4c65b7c847199529e172a65c0.svn-base +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * All unit tests for classes in the org.critterai.math.geom package. - */ -@RunWith(Suite.class) -@SuiteClasses( {Line2Tests.class - , Triangle2Test.class - , Rectangle2Tests.class - , Polygon3Tests.class - , Triangle3Tests.class} ) -public class AllTests { } diff --git a/critterai/.svn/pristine/55/55b21a3e3c22196a380052930fe3b394f03a9a73.svn-base b/critterai/.svn/pristine/55/55b21a3e3c22196a380052930fe3b394f03a9a73.svn-base deleted file mode 100644 index ced6ffb5..00000000 --- a/critterai/.svn/pristine/55/55b21a3e3c22196a380052930fe3b394f03a9a73.svn-base +++ /dev/null @@ -1,117 +0,0 @@ -package org.critterai.nmgen; - -/** - * Utilities useful for tests involving the open height field. - */ -public final class OpenHeightFieldUtil -{ - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private OpenHeightFieldUtil() { } - - /** - * Validates that the base spans in both regions are all in - * the same layout and region. - */ - public static boolean isSameRegionLayout(OpenHeightfield fieldA - , OpenHeightfield fieldB) - { - if (fieldA.regionCount() != fieldB.regionCount()) - return false; - if (fieldA.width() != fieldB.width() - || fieldA.depth() != fieldB.depth()) - return false; - - for (int w = 0; w < fieldA.width(); w++) - { - for (int d = 0; d < fieldA.depth(); d++) - { - OpenHeightSpan spanA = fieldA.getData(w, d); - OpenHeightSpan spanB = fieldB.getData(w, d); - if (spanA == null && spanB != null - || spanB == null && spanA != null) - return false; - if (spanA != null && spanA.regionID() != spanB.regionID()) - return false; - } - } - return true; - } - - /** - * Performs neighbor links of all base spans within a field. - * No checks are performed on validity neighbors. - */ - public static void linkAllBaseSpans(OpenHeightfield field) - { - for (int w = 0; w < field.width(); w++) - { - for (int d = 0; d < field.depth(); d++) - { - OpenHeightSpan span = field.getData(w, d); - if (span == null) - continue; - for (int dir = 0; dir < 4; dir++) - { - int woff = w + OpenHeightfield.getDirOffsetWidth(dir); - int doff = d + OpenHeightfield.getDirOffsetDepth(dir); - if (woff < 0 || woff >= field.width() - || doff < 0 || doff >= field.depth()) - continue; - OpenHeightSpan nSpan = field.getData(woff, doff); - if (nSpan != null) - span.setNeighbor(dir, nSpan); - } - } - } - } - - /** - * A square single level patch with a null region fully encompassed - * by a single region. (RegionID = 1) - * Only the region information and neighbor links are implemented. - * - * W - * 0 1 2 3 4 5 - * ----------- - * 5 | a a a a a a - * 4 | a a a a a a - * 3 | a a x x a a x - null region span - * D 2 | a a x x a a a - region 1 span - * 1 | a a a a a a All linked. - * 0 | a a a a a a - * - */ - public static OpenHeightfield getEncompassedNullRegionPatch() - { - - float[] gridBoundsMin = { 0, 0, 0 }; - float[] gridBoundsMax = { 10, 10, 10 }; - - OpenHeightfield field = new OpenHeightfield(gridBoundsMin - , gridBoundsMax - , 1 - , 1); - - for (int w = 0; w < 6; w++) - { - for (int d = 0; d < 6; d++) - { - OpenHeightSpan span = new OpenHeightSpan(w, d + 1); - span.setRegionID(1); - field.addData(w, d, span); - } - } - linkAllBaseSpans(field); - - field.getData(2, 2).setRegionID(NULL_REGION); - field.getData(2, 3).setRegionID(NULL_REGION); - field.getData(3, 2).setRegionID(NULL_REGION); - field.getData(3, 3).setRegionID(NULL_REGION); - - field.setRegionCount(2); - - return field; - } - -} diff --git a/critterai/.svn/pristine/55/55cdc5916f9ba4821dbd6731fc6f80d4bb0f2756.svn-base b/critterai/.svn/pristine/55/55cdc5916f9ba4821dbd6731fc6f80d4bb0f2756.svn-base deleted file mode 100644 index 7d6d0439..00000000 --- a/critterai/.svn/pristine/55/55cdc5916f9ba4821dbd6731fc6f80d4bb0f2756.svn-base +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen.rcn -{ - internal static class NMGenEx - { - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmgMarkWalkableTriangles(IntPtr ctx - , float walkableSlopeAngle - , [In] Vector3[] verts - , int nv - , [In] int[] tris - , int nt - , [In, Out] byte[] areas); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmgClearUnwalkableTriangles(IntPtr ctx - , float walkableSlopeAngle - , [In] Vector3[] verts - , int nv - , [In] int[] tris - , int nt - , [In, Out] byte[] areas); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmgFreeSerializationData(ref IntPtr data); - } -} diff --git a/critterai/.svn/pristine/56/56392c2ba9848fb0ef1a3755fe7eaa238935d9e2.svn-base b/critterai/.svn/pristine/56/56392c2ba9848fb0ef1a3755fe7eaa238935d9e2.svn-base deleted file mode 100644 index 58507c26..00000000 --- a/critterai/.svn/pristine/56/56392c2ba9848fb0ef1a3755fe7eaa238935d9e2.svn-base +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.critterai.math.geom.Rectangle2.contains; -import static org.critterai.math.geom.Rectangle2.intersectsAABB; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.critterai.math.MathUtil; -import org.critterai.math.geom.Rectangle2; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Rectangle2} class. - */ -public class Rectangle2Tests { - - private static final float XMIN = -3; - private static final float YMIN = 2; - private static final float XMAX = 2; - private static final float YMAX = 6; - - private static final float TOLERANCE = MathUtil.TOLERANCE_STD; - private static final float OFFSET = 1.5f; - - @Before - public void setUp() - throws Exception - { - - } - - @Test - public void testContainsPoint() - { - - // Wall tests. - - // On x min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN, YMIN + OFFSET)); - // On y min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMIN)); - // On x max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX , YMIN + OFFSET)); - // On y max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMAX)); - - // Inside x min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + TOLERANCE, YMIN + OFFSET)); - // Inside y min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMIN + TOLERANCE)); - // Inside x max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX - TOLERANCE , YMIN + OFFSET)); - // Inside y max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMAX - TOLERANCE)); - - // Outside x min bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN - TOLERANCE, YMIN + OFFSET)); - // Outside y min bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMIN - TOLERANCE)); - // Outside x max bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX + TOLERANCE , YMIN + OFFSET)); - // Outside y max bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMAX + TOLERANCE)); - - // Corner tests. - - // On minX/minY corner - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN, YMIN)); - // On minX/maxY corner - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN, YMAX)); - // On maxX/maxY corner. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX , YMAX)); - // On maxX/minY corner. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX, YMIN)); - - // Outside minX/minY corner - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN - TOLERANCE, YMIN - TOLERANCE)); - // Outside minX/maxY corner - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN - TOLERANCE, YMAX + TOLERANCE)); - // Outside maxX/maxY corner. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX + TOLERANCE , YMAX + TOLERANCE)); - // Outside maxX/minY corner. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX + TOLERANCE, YMIN - TOLERANCE)); - - } - - @Test - public void testContainsAABB() - { - - // A == B - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN, XMAX, YMAX)); - // B contains A - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - TOLERANCE, YMIN - TOLERANCE, XMAX + TOLERANCE, YMAX + TOLERANCE)); - // B slightly smaller than A. - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + TOLERANCE, YMIN + TOLERANCE, XMAX - TOLERANCE, YMAX - TOLERANCE)); - - // X-axis wall tests - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN + OFFSET, XMAX - TOLERANCE, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN + OFFSET, XMAX + TOLERANCE, YMAX - OFFSET)); - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + TOLERANCE, YMIN + OFFSET, XMAX, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - TOLERANCE, YMIN + OFFSET, XMAX, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN + OFFSET, XMIN + TOLERANCE, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMIN + OFFSET, XMAX + OFFSET, YMAX - OFFSET)); - - // Y-axis wall tests - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN, XMAX - OFFSET, YMAX - TOLERANCE)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN, XMAX - OFFSET, YMAX + TOLERANCE)); - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN + TOLERANCE, XMAX - OFFSET, YMAX)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN - TOLERANCE, XMAX - OFFSET, YMAX)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN - OFFSET, XMAX - OFFSET, YMIN + TOLERANCE)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMAX + TOLERANCE, XMAX - OFFSET, YMAX + OFFSET)); - - // Corner tests - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN - OFFSET, XMIN + TOLERANCE, YMIN + TOLERANCE)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMAX - TOLERANCE, XMIN + TOLERANCE, YMAX + OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMAX - TOLERANCE, YMAX - TOLERANCE, XMAX + OFFSET, YMAX + OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMAX - TOLERANCE, YMIN - OFFSET, XMAX + OFFSET, YMIN + TOLERANCE)); - - } - - // Leave this test in place until the associated code is permanently - // removed from the rectangle class. -// @Test -// public void testContainsStd() -// { -// // Wall tests. -// -// // On x min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN, YMIN + OFFSET)); -// // On y min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMIN)); -// // On x max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX , YMIN + OFFSET)); -// // On y max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMAX)); -// -// // Inside x min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + TOLERANCE, YMIN + OFFSET)); -// // Inside y min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMIN + TOLERANCE)); -// // Inside x max bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX - TOLERANCE , YMIN + OFFSET)); -// // Inside y max bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMAX - TOLERANCE)); -// -// // Outside x min bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN - TOLERANCE, YMIN + OFFSET)); -// // Outside y min bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMIN - TOLERANCE)); -// // Outside x max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX + TOLERANCE , YMIN + OFFSET)); -// // Outside y max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMAX + TOLERANCE)); -// -// // Corner tests. -// -// // On minX/minY corner -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN, YMIN)); -// // On minX/maxY corner -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN, YMAX)); -// // On maxX/maxY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX , YMAX)); -// // On maxX/minY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX, YMIN)); -// -// // Outside minX/minY corner -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN - TOLERANCE, YMIN - TOLERANCE)); -// // Outside minX/maxY corner -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN - TOLERANCE, YMAX + TOLERANCE)); -// // Outside maxX/maxY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX + TOLERANCE , YMAX + TOLERANCE)); -// // Outside maxX/minY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX + TOLERANCE, YMIN - TOLERANCE)); -// } - - @Test - public void testIntersects() - { - // Complete overlap - assertTrue(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN, XMAX, YMAX)); - - // A fully contains B - assertTrue(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN + TOLERANCE, YMIN + TOLERANCE, XMAX - TOLERANCE, YMAX - TOLERANCE)); - - // Wall tests - - // A xmin overlaps B xmax - assertTrue(intersectsAABB(XMIN , YMIN , XMAX, YMAX - , XMIN - OFFSET, YMIN + OFFSET, XMIN, YMAX - OFFSET)); - // A xmax overlaps B xmin - assertTrue(intersectsAABB(XMIN, YMIN , XMAX , YMAX - , XMAX, YMIN + OFFSET, XMAX + OFFSET, YMAX - OFFSET)); - // A ymin overlaps B ymax - assertTrue(intersectsAABB(XMIN , YMIN , XMAX , YMAX - , XMIN + OFFSET, YMIN - OFFSET, XMAX - OFFSET, YMIN)); - // A ymax overlaps B ymin - assertTrue(intersectsAABB(XMIN , YMIN, XMAX , YMAX - , XMIN + OFFSET, YMAX, XMAX - OFFSET, YMAX + OFFSET)); - - // A xmin above B xmax - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN + OFFSET, XMIN - TOLERANCE, YMAX - OFFSET)); - // A xmax below B xmin - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMIN + OFFSET, XMAX + OFFSET, YMAX - OFFSET)); - // A ymin above B ymax - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN - OFFSET, XMAX - OFFSET, YMIN - TOLERANCE)); - // A ymax below B ymin - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMAX + TOLERANCE, XMAX - OFFSET, YMAX + OFFSET)); - - // Corner tests. - - // B fully below A xmin and A ymin - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN - OFFSET, XMIN - TOLERANCE, YMIN - TOLERANCE)); - // B fully above A xmax and A ymax - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMAX + TOLERANCE, XMAX + OFFSET, YMAX + OFFSET)); - // B above and to right of A - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMAX + TOLERANCE, XMIN - TOLERANCE, YMAX + OFFSET)); - // B below and to the left of A - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMIN - OFFSET, XMAX + OFFSET, YMIN - TOLERANCE)); - - } - -} diff --git a/critterai/.svn/pristine/56/56645e84fae448d11a44bc7bacf731ef69af112c.svn-base b/critterai/.svn/pristine/56/56645e84fae448d11a44bc7bacf731ef69af112c.svn-base deleted file mode 100644 index c7b63621..00000000 --- a/critterai/.svn/pristine/56/56645e84fae448d11a44bc7bacf731ef69af112c.svn-base +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nmgen; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Applies to a . - /// - public sealed class AreaBoxMarker - : AreaMarker - { - private readonly Vector3 mBoundsMin; - private readonly Vector3 mBoundsMax; - - private AreaBoxMarker(string name, int priority, byte area - , Vector3 boundsMin, Vector3 boundsMax) - : base(name, priority, area) - { - mBoundsMin = boundsMin; - mBoundsMax = boundsMax; - } - - /// - /// The mimimum world bounds of the area to mark. - /// - public Vector3 BoundsMin { get { return mBoundsMin; } } - - /// - /// The maximum world bounds of the area to mark. - /// - public Vector3 BoundsMax { get { return mBoundsMax; } } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// The area will be applied during the state. - /// - /// - /// The current build state. - /// The context to process. - /// False on error, otherwise true. - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - if (state != NMGenState.CompactFieldBuild) - return true; - - if (context.CompactField.MarkBoxArea(context, mBoundsMin, mBoundsMax, Area)) - { - context.Log(string.Format("{0} : Marked box area: Area: {1}, Priority: {2}" - , Name, Area, Priority) - , this); - return true; - } - - context.Log(Name + ": Failed to mark box area.", this); - return false; - } - - /// - /// Creates a new marker. - /// - /// - /// - /// Will return null if the bounds are invalid. - /// - /// - /// The processor name. - /// The processor priority. - /// The area to apply. - /// The mimimum world bounds of the area to mark. - /// The maximum world bounds of the area to mark. - /// A new marker, or null on error. - public static AreaBoxMarker Create(string name, int priority, byte area - , Vector3 boundsMin, Vector3 boundsMax) - { - if (org.critterai.geom.TriangleMesh.IsBoundsValid(boundsMin, boundsMax)) - return new AreaBoxMarker(name, priority, area, boundsMin, boundsMax); - - return null; - } - } -} diff --git a/critterai/.svn/pristine/56/56c6435c1047f6cd143bc6935d9dd5c0076f77fc.svn-base b/critterai/.svn/pristine/56/56c6435c1047f6cd143bc6935d9dd5c0076f77fc.svn-base deleted file mode 100644 index c5fdb16f..00000000 --- a/critterai/.svn/pristine/56/56c6435c1047f6cd143bc6935d9dd5c0076f77fc.svn-base +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import org.critterai.nmgen.SolidHeightfield.SolidHeightFieldIterator; - -/** - * A class used to build solid heightfields from source geometry using a - * given configuration. The solid heightfield represents the space obstructed - * by the source geometry. - *

Each triangle in the source geometry is voxelized using conservative - * voxelization and added to the field. Conservative voxelization is an - * algorithm that ensures that polygon surfaces are completely encompassed - * by the the generated voxels.

- *

At the end of the process, spans with the {@link SpanFlags#WALKABLE} - * flag have survived the following tests:

- *
    - *
  • The top of the span is at least a minimum distance from the bottom of - * the span above it. (The tallest agent can "stand" on the span without - * colliding with an obstruction above.)
  • - *
  • The top voxel of the span represents geometry with a slope below a - * maximum allowed value. (The slope is low enough to be traversable by - * agents.)
  • - *
  • If ledge culling is enabled, the top of the span does not represent - * a ledge. (Agents can legally "step down" from the span to any of its - * neighbors.)
  • - *
- * @see The Voxelization Process - * @see Introduction to Heightfields - * @see Conservative Voxelization (PDF) - */ -public final class SolidHeightfieldBuilder -{ - - /* - * Design notes: - * - * Recast reference: - * rcCreateHeightfield in Recast.cpp - * rcMarkWalkableTriangles in Recast.cpp - * rcRasterizeTriangles in RecastRasterization.cpp - * rcFilterLedgeSpans in RecastFilter.cpp - * rcFilterWalkableLowHeightSpans in RecastFilter.cpp - * - * Not adding configuration getters until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - * - * TODO: EVAL: It may be better to implement post-processing as external - * algorithms similar to what is done with the open heightfield and - * contour classes. - * - */ - - // Configuration settings. - - private final boolean mClipLedges; - private final int mMinTraversableHeight; - private final int mMaxTraversableStep; - - /** - * A derived value which represent the minimum y-normal permitted for - * a polygon to be considered traversable. - *

See the constructor for details.

- */ - private final float mMinNormalY; - - /** - * The cell size to use for all new fields. - *

IMPORTANT: Only use this value for heightfield object initialization. - * After that, use the value in the heightfield object. (Since the - * heightfield instance may place limitations on the value.)

- */ - private final float mCellSize; - - /** - * The cell height to use for all new fields. - *

IMPORTANT: Only use this value for heightfield object initialization. - * After that, use the value in the heightfield object. (Since the height - * field object may place limitations on the value.)

- */ - private final float mCellHeight; - - /** - * Constructor - * @param cellSize The size of the cells. (The grid that forms the base - * of the field.) - *

This value represents the x and z-axis sampling resolution to use - * when generating voxels.

- * - * @param cellHeight The height increment of the field. - *

This value represents the y-axis sampling resolution to use when - * generating voxels.

- * - * @param minTraversableHeight Represents the minimum floor to ceiling - * height that will still allow a floor area to be considered traversable. - *

Permits detection of overhangs in the geometry which make the - * geometry below become unwalkable.

- *

Constraints: > 0

- * - * @param maxTraversableStep Represents the maximum ledge height that - * is considered to still be traversable. - *

Prevents minor deviations in height from improperly showing as - * obstructions. Permits detection of stair-like structures, curbs, etc.

- *

Constraints: >= 0

- * - * @param maxTraversableSlope The maximum slope that is considered - * traversable. (Degrees) - *

Spans that are at or above this slope have the - * {@link SpanFlags#WALKABLE} flag removed.

- *

Constraints: 0 <= value <= 85

- * - * @param clipLedges Indicates whether ledges should be marked as - * unwalkable. I.e. The {@link SpanFlags#WALKABLE} flag will be removed. - *

A ledge is a normally traversable span that has one or more - * accessible neighbors with a an un-steppable drop from span top to - * span top.

- *

E.g. If an agent using the navmesh were to travel down from the - * ledge span to its neighbor span, it would result in the maximum - * traversable step distance being violated. The agent cannot legally - * "step down" from a ledge to its neighbor.

- */ - public SolidHeightfieldBuilder(float cellSize - , float cellHeight - , int minTraversableHeight - , int maxTraversableStep - , float maxTraversableSlope - , boolean clipLedges) - { - - mMinTraversableHeight = Math.max(1, minTraversableHeight); - mMaxTraversableStep = Math.max(0, maxTraversableStep); - maxTraversableSlope = Math.min(85, Math.max(0, maxTraversableSlope)); - mClipLedges = clipLedges; - mCellSize = cellSize; - mCellHeight = cellHeight; - - /* - * Derive the minimum y-normal. - * - * Base Reference: http://mathworld.wolfram.com/DihedralAngle.html - * - * By ensuring n1 and n2 are both normalized before the calculation, the - * denominator in the reference equations evaluate to 1 and - * can be discarded. So the reference equation is simplified to... - * - * cos theta = n1 dot n2 - * - * Using: - * - * n1 = (0, 1, 0) (Represents a flat surface on the (x,z) plane.) - * n2 = (x, y, z) Normalized. (A surface on an arbitrary plane.) - * - * Simplify and solve for y: - * - * cos theta = 0x + 1y + 0z - * y = cos theta - * - * We know theta. It is the value of maxTraversableSlope after - * conversion to radians. So we know what y-normal is at the walk - * slope angle. If a polygon's y-normal is LESS THAN our calculated - * y-normal, then we know we have exceeded the walk angle. - */ - mMinNormalY = (float)Math.cos(Math.abs( - maxTraversableSlope)/180 * Math.PI); - } - - /** - * Generates a solid heightfield from the provided source geometry. The - * solid heightfield will represent the space obstructed by the source - * geometry. - *

The {@link SpanFlags#WALKABLE} will be applied to spans whose top - * surface is considered traversable. See the class description for - * details.

- * @param vertices Source geometry vertices in the form (x, y, z). - * @param indices Source geometry indices in the form (VertA, VertB, VertC). - * Wrapped: Clockwise. - * @return The generated solid heightfield, or null if the generation fails. - */ - public SolidHeightfield build(float[] vertices, int[] indices) - { - // Perform basic checks. - if (vertices == null - || indices == null - || vertices.length % 3 != 0 - || indices.length % 3 != 0) - return null; - - // Initialize heightfield. - final SolidHeightfield result = - new SolidHeightfield(mCellSize, mCellHeight); - - // Pre-calculate values to save on the cost of division later. - final float inverseCellSize = 1 / result.cellSize(); - final float inverseCellHeight = 1 / result.cellHeight(); - - // Detect and set the bounds of the source geometry. - // Default to the first vertex. - float xmin = vertices[0]; - float ymin = vertices[1]; - float zmin = vertices[2]; - float xmax = vertices[0]; - float ymax = vertices[1]; - float zmax = vertices[2]; - // Loop through all vertices, expanding the bounds - // as appropriate. - for (int i = 3; i < vertices.length; i += 3) - { - xmax = Math.max(vertices[i], xmax); - ymax = Math.max(vertices[i + 1], ymax); - zmax = Math.max(vertices[i + 2], zmax); - - xmin = Math.min(vertices[i], xmin); - ymin = Math.min(vertices[i + 1], ymin); - zmin = Math.min(vertices[i + 2], zmin); - } - // Set the bounds. - result.setBounds(xmin, ymin, zmin, xmax, ymax, zmax); - - // Detect which polygons in the source mesh have a slope - // that low enough to be considered traversable. (Agent can walk up - // or down the slope.) - final int[] polyFlags = markInputMeshWalkableFlags(vertices, indices); - - // For each polygon in the source mesh: Voxelize it and add the - // resulting spans to the solid field. - final int polyCount = indices.length / 3; - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - voxelizeTriangle(iPoly - , vertices - , indices - , polyFlags[iPoly] - , inverseCellSize - , inverseCellHeight - , result); - } - - // Remove the walkable flag from any span that has another span too - // close above it. - markLowHeightSpans(result); - - if (mClipLedges) - // Remove the walkable flag from any span that is determined to - // be a ledge. - markLedgeSpans(result); - - return result; - - } - - /** - * Checks the slope of each polygon against the maximum allowed. Any - * polygon whose slope is below the maximum permitted gets the - * {@link SpanFlags#WALKABLE} flag. - * @param vertices The source geometry vertices in the form (x, y, z). - * @param indices The source geometry indices in the form - * (vertA, vertB, vertC), clockwise wrapped. - * @return An array of flags in the form - * (polyFlag0, polyFlag1, ..., polyFlagN), stride = 1. - */ - private int[] markInputMeshWalkableFlags(float[] vertices, int[] indices) - { - - // See mMinNormalY in constructor for more information on how this - // works. - - final int[] flags = new int[indices.length / 3]; - - // Working variables. Content changes for every loop - // and has no meaning outside the loop. - float[] diffAB = new float[3]; - float[] diffAC = new float[3]; - float[] crossDiff = new float[3]; - - // Loop through all polygons. - int polyCount = indices.length / 3; - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - // Get pointers to each polygon vertex. - int pVertA = indices[iPoly*3]*3; - int pVertB = indices[iPoly*3+1]*3; - int pVertC = indices[iPoly*3+2]*3; - - // Determine the y-normal for the polygon. - float normalY = getNormalY( - cross(subtract(pVertB, pVertA, vertices, diffAB) - , subtract(pVertC, pVertA, vertices, diffAC) - , crossDiff)); - - if (normalY > mMinNormalY) - // The slope of this polygon is acceptable. Mark it as - // walkable. - flags[iPoly] = SpanFlags.WALKABLE; - } - - return flags; - } - - /** - * Removes the traversable flag for any spans that represent a ledge. - * A ledge occurs when stepping from the top of one span down to any of its - * neighbor spans exceeds the allowed walk climb distance. (i.e. Can't - * legally "step down" to a neighbor span.) - * @param field The field to operation on. - */ - private void markLedgeSpans(SolidHeightfield field) - { - - /* - * Note: While this is a solid field representing obstructions, much - * of this algorithm deals with the space between obstructions. - * (The gaps.) So you will need to twist your thinking to gaps rather - * than obstructions. - * - * For visualization, see the @see in the class' javadoc. - */ - - // Loop through all spans. - SolidHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - HeightSpan span = iter.next(); - - if ((span.flags() & SpanFlags.WALKABLE) == 0) - // Span is already known to be un-waklable. - // Skip it. - continue; - - final int widthIndex = iter.widthIndex(); - final int depthIndex = iter.depthIndex(); - - // These values represent the gap (floor to ceiling) above the - // current span. - final int currFloor = span.max(); - final int currCeiling = (span.next() != null) ? - span.next().min() : Integer.MAX_VALUE; - - /* - * Represents the minimum distance from the current span's floor - * to a neighbor span's floor. A positive value indicates a step - * up. A negative distance represents a step down. If this - * distance is too far down, then the current span is a ledge - * and isn't traversable. - * - * This algorithm only cares about drops. - * Default to a maximum step up. - */ - int minDistanceToNeighbor = Integer.MAX_VALUE; - - /* - * The lowest possible floor is at -mMaxTraversableStep. No span - * can exist below the zero height index. So stepping from a span - * whose floor is at zero to "empty space" will result in a drop - * to -mMaxTraversableStep. - */ - - /* - * Loop through all neighbor grid cells. - */ - for (int dir = 0; dir < 4; dir++) - { - final int nWidthIndex = widthIndex - + BoundedField.getDirOffsetWidth(dir); - final int nDepthIndex = depthIndex - + BoundedField.getDirOffsetDepth(dir); - - // Get the lowest span in this neighbor column. - HeightSpan nSpan = field.getData(nWidthIndex, nDepthIndex); - - if (nSpan == null) - { - // No neighbor on this side. Treat as the maximum drop. - // (Which is always considered a ledge.) - // TODO: EVAL: Should this be a break rather than a - // continue? (Detected too close to release to risk code - // changes.) - minDistanceToNeighbor = Math.min(minDistanceToNeighbor - , -mMaxTraversableStep - currFloor); - continue; - } - - /* - * First need to take into account the area below the lowest - * span in this neighbor column. - * - * In this special case, the floor of this gap is the lowest - * possible value. The ceiling of this gap is the bottom of - * neighbor span. - */ - // Default to an excessive drop. - int nFloor = -mMaxTraversableStep; - int nCeiling = nSpan.min(); // The bottom of this first span. - - /* - * This check filters out the following: - * - * The distance from the current span's floor this neighbor's - * ceiling is not large enough to permit transit in that - * direction? (Agent will "bump its head" if it moves in this - * direction?) - * - * The neighbor gap is entirely below the floor of the - * current span. - * - * In such cases travel is not allowed to the neghbor gap, so - * it isn't taken into account. - */ - if (Math.min(currCeiling, nCeiling) - currFloor - > mMinTraversableHeight) - // Travel is permitted in this direction. So take this - // neighbor gap into account. - minDistanceToNeighbor = - Math.min(minDistanceToNeighbor, (nFloor - currFloor)); - - /* - * Now process the rest of the gaps in this neighbor column - * normally. E.g. The top of the span is the floor. The - * bottom of the next span is the ceiling. - */ - - for (nSpan = field.getData(nWidthIndex, nDepthIndex) - ; nSpan != null - ; nSpan = nSpan.next()) - { - nFloor = nSpan.max(); - nCeiling = (nSpan.next() != null) ? - nSpan.next().min() : Integer.MAX_VALUE; - /* - * This next check filters out the following: - * - * The distance from the current span's floor this - * neighbor's ceiling is not large enough to permit - * transit in that direction? (Agent will "bump its head" - * if it moves in this direction?) - * - * The neighbor gap is entirely below the floor of the - * current span. - * - * The neighbor gap is entirely above the ceiling of the - * current gap. - * - * In such cases travel is not allowed to the neghbor gap, - * so it isn't taken into account. - */ - if (Math.min(currCeiling, nCeiling) - - Math.max(currFloor, nFloor) - > mMinTraversableHeight) - // Potential travel to this neighbor span. - minDistanceToNeighbor = - Math.min(minDistanceToNeighbor - , (nFloor - currFloor)); - } - - } - - // Remember: A negative distance indicates a drop. - if (minDistanceToNeighbor < -mMaxTraversableStep) - // Can only drop by mMaxTraversableStep, but a neighbor has a - // drop that exceeds this allowed drop. Remove the walkable - // flag. - span.setFlags(span.flags() & ~SpanFlags.WALKABLE); - } - } - - /** - * Remove the traversable flag from spans that have another span too - * close above them. - * @param field The heightfield to operate on. - */ - private void markLowHeightSpans(SolidHeightfield field) - { - // TODO: EVAL: Consider merging this operation with markLedgeSpans. - - // For visualization, see the @see in the class' javadoc. - - // Iterate through all spans in the field. - SolidHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - HeightSpan span = iter.next(); - - if ((span.flags() & SpanFlags.WALKABLE) == 0) - // Span is already known to be un-waklable. - // Skip it. - continue; - - // Find the gap between the current span and the next higher span. - // This represents the open space (floor to ceiling) above the - // current span. - int spanFloor = span.max(); - int spanCeiling = (span.next() != null) ? - span.next().min() : Integer.MAX_VALUE; - - if (spanCeiling - spanFloor <= mMinTraversableHeight) - // Can't stand on this span. Ceiling is too low. - // Remove its walkable flag. - span.setFlags(span.flags() & ~SpanFlags.WALKABLE); - } - } - - /** - * Clamps the value to the specified range. - * @param value The value to clamp. - * @param minimum The minimum allowed value. (Inclusive.) - * @param maximum The maximum allowed value. (Inclusive.) - * @return If minimum <= value <= maximum, will return value. - * If value < minimum, will return minimum. - * If value > maximum, will return maximum. - */ - private static int clamp(int value, int minimum, int maximum) - { - return (value < minimum - ? minimum : (value > maximum ? maximum : value)); - } - - private static int clipPoly(float[] in - , int inputVertCount - , float[] out - , float pnx - , float pnz - , float pd) - { - - // TODO: DOC: Figure out what is going on here. Not familiar with - // algorithm. pnx and pnz are normals. - - float d[] = new float[inputVertCount]; - for (int vertIndex = 0; vertIndex < inputVertCount; ++vertIndex) - d[vertIndex] = (pnx * in[vertIndex * 3]) - + (pnz * in[vertIndex * 3 + 2]) + pd; - - int m = 0; - for (int current = 0, previous = d.length - 1 - ; current < d.length - ; previous=current, ++current) - { - boolean ina = d[previous] >= 0; - boolean inb = d[current] >= 0; - if (ina != inb) - { - float s = d[previous] / (d[previous] - d[current]); - out[m*3+0] = - in[previous*3+0] + (in[current*3+0] - in[previous*3+0])*s; - out[m*3+1] = - in[previous*3+1] + (in[current*3+1] - in[previous*3+1])*s; - out[m*3+2] = - in[previous*3+2] + (in[current*3+2] - in[previous*3+2])*s; - m++; - } - if (inb) - { - out[m*3+0] = in[current*3+0]; - out[m*3+1] = in[current*3+1]; - out[m*3+2] = in[current*3+2]; - m++; - } - } - return m; - } - - /** - * Performs a cross product on the vectors u and v. (u x v) - * @param u The first vector in the form (x, y, z) - * @param v The second vector in the form (x, y, z) - * @param out The array to be loaded with the result. - * @return A reference to the out array loaded with the cross product. - */ - private static float[] cross(float[] u, float[] v, float[] out) - { - // Reference: http://mathworld.wolfram.com/CrossProduct.html - // Reference: http://en.wikipedia.org/wiki/Cross_product - // #Computing_the_cross_product - out[0] = u[1] * v[2] - u[2] * v[1]; - out[1] = -u[0] * v[2] + u[2] * v[0]; - out[2] = u[0] * v[1] - u[1] * v[0]; - return out; - } - - /** - * Normalizes the provided vector and returns the y-value. - * @param v The vector to normalize in the form: (x, y, z) - * @return The y-value of the normalized vector. - */ - private static float getNormalY(float[] v) - { - // This is just the standard normalization algorithm with - // unneeded x and z calculations removed. - - final float epsilon = 0.0001f; - - float length = - (float)Math.sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2])); - if (length <= epsilon) - length = 1; - - float y = v[1] / length; - - if (Math.abs(y) < epsilon) - y = 0; - - return y; - } - - /** - * Performs vector subtraction on the vertices. (VertexA - VertexB) - * @param pVertA The pointer to a valid vertex in the source vertices array. - * @param pVertB The pointer to a valid vertex in the source vertices array. - * @param out An array of size 3. The array is loaded with the result of - * the subtraction and returned. - * @return A reference to the out array loaded with the result of the - * subtraction. - */ - private static float[] subtract(int pVertA - , int pVertB - , float[] vertices - , float[] out) - { - out[0] = vertices[pVertA] - vertices[pVertB]; - out[1] = vertices[pVertA+1] - vertices[pVertB+1]; - out[2] = vertices[pVertA+2] - vertices[pVertB+2]; - return out; - } - - /** - * Voxelizes the chosen polygon and adds the resulting spans to the - * heightfield. - *

The inverse arguments are included for optimization. (No need to - * recalculate the values for every call.)

- *

The heightfield will make the final decision on whether to apply - * the flags provided in the arguments. See the - * {@link SolidHeightfield#addData(int, int, int, int, int) heightfield - * add operation} for details

- * @param polyIndex The polygon to voxelize. - * @param vertices The vertices of the source geometry in the form - * (x, y, z). - * @param indices The indices of the source geometry in the form - * (vertA, vertB, vertC), wrapped clockwise. - * @param polyFlags The flags to apply to all new spans within the - * heightfield. - * @param inverseCellSize Inverse cell size. (1/cellSize) - * @param inverseCellHeight Inverse cell height. (1/cellheight) - * @param inoutField The heightfield to add new spans to. - */ - private static void voxelizeTriangle(int polyIndex - , float[] vertices - , int[] indices - , int polyFlags - , float inverseCellSize - , float inverseCellHeight - , SolidHeightfield inoutField) - { - - /* - * Design notes: - * - * There is significant processing going on here that is not - * required since this is a private operation and the input is tightly - * controlled. For example: We know that the heightfield is sized to - * hold the source geometry, so bounds checks aren't really needed. - * - * But, with the possible exception of object creation, the extra - * cost is not big. So I'm leaving the algorithm as it is just in - * case it is converted to a public operation at a later date. - */ - - // Pointer to the polygon. - final int pPoly = polyIndex*3; - - // Polygon vertices. - final float[] triVerts = { - vertices[indices[pPoly]*3] // VertA - , vertices[indices[pPoly]*3+1] - , vertices[indices[pPoly]*3+2] - , vertices[indices[pPoly+1]*3] // VertB - , vertices[indices[pPoly+1]*3+1] - , vertices[indices[pPoly+1]*3+2] - , vertices[indices[pPoly+2]*3] // VertC - , vertices[indices[pPoly+2]*3+1] - , vertices[indices[pPoly+2]*3+2] - }; - - // Determine the bounding box of the polygon. - - // Initialize bounds to the first triangle vertex. - final float[] triBoundsMin = { triVerts[0], triVerts[1], triVerts[2] }; - final float[] triBoundsMax = { triVerts[0], triVerts[1], triVerts[2] }; - - // Loop through all vertices to determine the actual bounding box. - for (int vertPointer = 3; vertPointer < 9; vertPointer += 3) - { - triBoundsMin[0] = Math.min(triBoundsMin[0], - triVerts[vertPointer]); - triBoundsMin[1] = Math.min(triBoundsMin[1], - triVerts[vertPointer + 1]); - triBoundsMin[2] = Math.min(triBoundsMin[2], - triVerts[vertPointer + 2]); - triBoundsMax[0] = Math.max(triBoundsMax[0], - triVerts[vertPointer]); - triBoundsMax[1] = Math.max(triBoundsMax[1], - triVerts[vertPointer + 1]); - triBoundsMax[2] = Math.max(triBoundsMax[2], - triVerts[vertPointer + 2]); - } - - // If the triangle does not overlap the heightfield, then skip it. - if (!inoutField.overlaps(triBoundsMin, triBoundsMax)) - return; - - /* - * Determine footprint of triangle bounding box on the heightfield's - * grid. - * - * Notes: - * - * The heightfield is an integer based grid with its origin at the - * heightfield's minimum bounds. I.e. Grid coordinate - * (0, 0) => (heightField.minbounds.x, heightField.minbounds.z) - * - * The heightfield width/depth values map to the (x, z) plane of the - * triangle, not the (x, y) plane. - */ - - // First, convert the triangle bounds to field grid coordinates. - int triWidthMin = (int)((triBoundsMin[0] - inoutField.boundsMin()[0]) - * inverseCellSize); - int triDepthMin = (int)((triBoundsMin[2] - inoutField.boundsMin()[2]) - * inverseCellSize); - int triWidthMax = (int)((triBoundsMax[0] - inoutField.boundsMin()[0]) - * inverseCellSize); - int triDepthMax = (int)((triBoundsMax[2] - inoutField.boundsMin()[2]) - * inverseCellSize); - - // Snap the grid coordinates to the grid bounds. - triWidthMin = clamp(triWidthMin, 0, inoutField.width() - 1); - triDepthMin = clamp(triDepthMin, 0, inoutField.depth() - 1); - triWidthMax = clamp(triWidthMax, 0, inoutField.width() - 1); - triDepthMax = clamp(triDepthMax, 0, inoutField.depth() - 1); - - /* - * "in" will contain the final data. - * "out" and "inrow" are used for intermediate data. - * "in" is initially seeded with the triangle vertices. - * The arrays are sized to be 3 * 7. This allows for the storage of - * the maximum vertex count for a triangle clipped into a square (6) - * with an extra triple. - * (Don't know the purpose of the extra triple.) - */ - final float in[] = new float[21]; - final float out[] = new float[21]; - final float inrow[] = new float[21]; - - // The height of the heightfield. - final float fieldHeight = - inoutField.boundsMax()[1] - inoutField.boundsMin()[1]; - - /* - * Loop through all grid locations overlapped by the polygon. - * (xz-plane only). - * - * Clip the triangle into all grid cells it touches. - * - * Any early exit from either of the loops means that the triangle - * does not overlap the grid column, or is outside the height - * bounds of the field. - * - * All detailed clip data is discarded in the end. The only information - * preserved is the height information. - * - * Dev Note: I don't understand the mathematical algorithm used here. - * So I've marked it as magic. But by tracing the process on paper - * I've determined that the algorithm is finding all intersection - * points between the grid column and the triangle face. - * - * For visualization, see the @see in the class' javadoc. - */ - for (int depthIndex = triDepthMin - ; depthIndex <= triDepthMax - ; ++depthIndex) - { - - // Seed with the triangle vertices. - System.arraycopy(triVerts, 0, in, 0, triVerts.length); - - // Do some magic. - // Count of cell intersection vertices found. - int intermediateVertCount = 3; - final float rowWorldZ = inoutField.boundsMin()[2] - + (depthIndex * inoutField.cellSize()); - intermediateVertCount = clipPoly(in - , intermediateVertCount - , out - , 0 - , 1 - , -rowWorldZ); - if (intermediateVertCount < 3) - continue; - intermediateVertCount = clipPoly(out, intermediateVertCount - , inrow - , 0 - , -1 - , rowWorldZ + inoutField.cellSize()); - if (intermediateVertCount < 3) - continue; - - for (int widthIndex = triWidthMin - ; widthIndex <= triWidthMax - ; ++widthIndex) - { - - // Do some more magic. - int vertCount = intermediateVertCount; - final float colWorldX = inoutField.boundsMin()[0] - + (widthIndex * inoutField.cellSize()); - vertCount = clipPoly(inrow, vertCount, out, 1, 0, -colWorldX); - if (vertCount < 3) - continue; - vertCount = clipPoly(out - , vertCount - , in - , -1 - , 0 - , colWorldX + inoutField.cellSize()); - if (vertCount < 3) - continue; - - // If got here, then "in" contains the definition for a poly - // representing the portion - // of the input triangle that overlaps the grid location. - - // Find the height (y-axis) range for this grid location. - float heightMin = in[1]; - float heightMax = in[1]; - for (int i = 1; i < vertCount; ++i) - { - heightMin = Math.min(heightMin, in[i*3+1]); - heightMax = Math.max(heightMax, in[i*3+1]); - } - // Convert to height above the "floor" of the heightfield. - heightMin -= inoutField.boundsMin()[1]; - heightMax -= inoutField.boundsMin()[1]; - if (heightMax < 0.0f || heightMin > fieldHeight) - // The height of the potential span is entirely outside - // the bounds of the heightfield. - continue; - // Clamp to the heightfield bounding box. - if (heightMin < 0.0f) - heightMin = inoutField.boundsMin()[1]; - if (heightMax > fieldHeight) - heightMax = inoutField.boundsMax()[1]; - - // Convert the min/max to height grid index. - int heightIndexMin = clamp( - (int)Math.floor(heightMin * inverseCellHeight) - , 0 - , Short.MAX_VALUE); - int heightIndexMax = clamp( - (int)Math.ceil(heightMax * inverseCellHeight) - , 0 - , Short.MAX_VALUE); - - // Add the span to the heightfield. - inoutField.addData(widthIndex - , depthIndex - , heightIndexMin - , heightIndexMax - , polyFlags); - } - } - - } - -} diff --git a/critterai/.svn/pristine/56/56e20285899e95fc8f5f431130f3314b6cc44159.svn-base b/critterai/.svn/pristine/56/56e20285899e95fc8f5f431130f3314b6cc44159.svn-base deleted file mode 100644 index 0d6dc3f3..00000000 --- a/critterai/.svn/pristine/56/56e20285899e95fc8f5f431130f3314b6cc44159.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nav")] -[assembly: AssemblyDescription("Core pathfinding and obstacle avoidance features.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2011-2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/57/57751eefa09368c8a06318da82965cd2a8a1ac66.svn-base b/critterai/.svn/pristine/57/57751eefa09368c8a06318da82965cd2a8a1ac66.svn-base deleted file mode 100644 index 4d3b9565..00000000 --- a/critterai/.svn/pristine/57/57751eefa09368c8a06318da82965cd2a8a1ac66.svn-base +++ /dev/null @@ -1,61 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {C4B32B85-13F0-42B8-AC89-770BEFEAF022} - Library - Properties - org.critterai - cai-util - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - ..\bin\Release\cai-util.XML - - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - geom\FakeName.cs - - - interop\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/57/57b286834051967078c2e9927a5dc26218d9695e.svn-base b/critterai/.svn/pristine/57/57b286834051967078c2e9927a5dc26218d9695e.svn-base deleted file mode 100644 index c7f1c5cb..00000000 --- a/critterai/.svn/pristine/57/57b286834051967078c2e9927a5dc26218d9695e.svn-base +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(TagSceneQuery))] -public sealed class TagSceneQueryEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - TagSceneQuery targ = (TagSceneQuery)target; - - // Has someone done something naughty? - - if (targ.tags == null) - { - Debug.LogError(targ.name + "Data null reference. Resetting component."); - targ.tags = new List(); - } - - EditorGUILayout.Separator(); - - EditorGUIUtility.LookLikeControls(120); - - targ.IncludeChildren = EditorGUILayout.Toggle("Include Children", targ.IncludeChildren); - - EditorGUIUtility.LookLikeControls(); - - EditorGUILayout.Separator(); - - EditorUtil.OnGUIManageStringList(targ.tags, true); - - EditorGUILayout.Separator(); - - GUILayout.Box( - "Scene Query\n\nComponent search will include game objects with the specified tags." - + " The search can optionally include child game objects." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Scene Query : Tag", false, NMBEditorUtil.SceneGroup)] - static void CreateAsset() - { - TagSceneQuery item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/57/57c2feef2d749f091b7898f4ecf02a7455c3e233.svn-base b/critterai/.svn/pristine/57/57c2feef2d749f091b7898f4ecf02a7455c3e233.svn-base deleted file mode 100644 index b5ec1516..00000000 --- a/critterai/.svn/pristine/57/57c2feef2d749f091b7898f4ecf02a7455c3e233.svn-base +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include "RecastAlloc.h" - -static void *rcAllocDefault(int size, rcAllocHint) -{ - return malloc(size); -} - -static void rcFreeDefault(void *ptr) -{ - free(ptr); -} - -static rcAllocFunc* sRecastAllocFunc = rcAllocDefault; -static rcFreeFunc* sRecastFreeFunc = rcFreeDefault; - -/// @see rcAlloc, rcFree -void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc) -{ - sRecastAllocFunc = allocFunc ? allocFunc : rcAllocDefault; - sRecastFreeFunc = freeFunc ? freeFunc : rcFreeDefault; -} - -/// @see rcAllocSetCustom -void* rcAlloc(int size, rcAllocHint hint) -{ - return sRecastAllocFunc(size, hint); -} - -/// @par -/// -/// @warning This function leaves the value of @p ptr unchanged. So it still -/// points to the same (now invalid) location, and not to null. -/// -/// @see rcAllocSetCustom -void rcFree(void* ptr) -{ - if (ptr) - sRecastFreeFunc(ptr); -} - -/// @class rcIntArray -/// -/// While it is possible to pre-allocate a specific array size during -/// construction or by using the #resize method, certain methods will -/// automatically resize the array as needed. -/// -/// @warning The array memory is not initialized to zero when the size is -/// manually set during construction or when using #resize. - -/// @par -/// -/// Using this method ensures the array is at least large enough to hold -/// the specified number of elements. This can improve performance by -/// avoiding auto-resizing during use. -void rcIntArray::resize(int n) -{ - if (n > m_cap) - { - if (!m_cap) m_cap = n; - while (m_cap < n) m_cap *= 2; - int* newData = (int*)rcAlloc(m_cap*sizeof(int), RC_ALLOC_TEMP); - if (m_size && newData) memcpy(newData, m_data, m_size*sizeof(int)); - rcFree(m_data); - m_data = newData; - } - m_size = n; -} - diff --git a/critterai/.svn/pristine/58/584bc5a2ad7658a07e4beb91cfc348913f3f0443.svn-base b/critterai/.svn/pristine/58/584bc5a2ad7658a07e4beb91cfc348913f3f0443.svn-base deleted file mode 100644 index c0cf726f..00000000 --- a/critterai/.svn/pristine/58/584bc5a2ad7658a07e4beb91cfc348913f3f0443.svn-base +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild -{ - /// - /// Represents the build state for an object. - /// - /// - /// - /// There are three finished states: , , - /// and . - /// - /// - public enum NMGenState - { - /// - /// The builder is initialized and ready to start the build. - /// - Initialized = 0, - - /// - /// The build was aborted due to an error. (Finished state.) - /// - Aborted, - - /// - /// The build was completed and produced a result. (Finished state.) - /// - /// - /// - /// The build produced at least a object - /// with at least one polygon. - /// - /// - /// It is possible to complete, but have no resulting meshes. See . - /// - /// - Complete, - - /// - /// The build completed without producing a result. (Finished state.) - /// - /// - /// - /// While having no result is usually considered a failure when building a single - /// tile mesh, it is not unexpected for tiled meshes. (Some tiles may not contain - /// input geometry, or not enough to result in a usable surface.) - /// - /// - NoResult, - - /// - /// At the step to build the heightfield. - /// - HeightfieldBuild, - - /// - /// At the step to build the compact heightfield. - /// - CompactFieldBuild, - - /// - /// At the step to build the compact heightfield regions. - /// - RegionBuild, - - /// - /// At the step to build the raw and detail contours. - /// - ContourBuild, - - /// - /// At the step to build the polygon mesh. - /// - PolyMeshBuild, - - /// - /// At the step to build the detail mesh. - /// - /// - /// - /// This state will only be reached if the build is set up to produce a detail mesh. - /// - /// - DetailMeshBuild, - } -} diff --git a/critterai/.svn/pristine/58/58c54d126145af27db2b13d9adf290c45ca993d6.svn-base b/critterai/.svn/pristine/58/58c54d126145af27db2b13d9adf290c45ca993d6.svn-base deleted file mode 100644 index f2eb365f..00000000 --- a/critterai/.svn/pristine/58/58c54d126145af27db2b13d9adf290c45ca993d6.svn-base +++ /dev/null @@ -1,57 +0,0 @@ ->> Directory Layout <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -build - - Contains Visual Studio projects and build related source files for active - projects. - -doc - - Documentation project and source files. - -legacy - - Older projects that are no longer being actively worked on. - -src - - Source for active projects. - - The source directory layout is a bit odd. Most C# source is located - under /src/main/Assets/CAI. This layout mimics the layout within - a Unity project. It is structured in this way to support easy source - deployment to non-Windows Unity projects which can't use the pre-compiled - libraries. - ->> .NET Notes <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -No automatic builds or packaging. -Sandcastle for documentation build. - -DOCUMENTATION BUILD NOTES - -The following tools are required to build the API documentation: - -Sandcastle: http://sandcastle.codeplex.com/ -Sandcastle Help File Builder: http://shfb.codeplex.com/ - -Sandcastle Styles Patch - -http://sandcastlestyles.codeplex.com/ - Home Page -http://sandcastlestyles.codeplex.com/releases/view/47767 - Patch Used - ->> Unity Notes <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -Libraries and namespaces containing 'u3d' depend on Unity Pro -(http://unity3d.com/). The free version of unity is not supported. - -The Visual Studio projects were created on Windows 64-bit, so the Unity DLL -reference will be broken on 32-bit Windows. - -For Unity 3.x, the normal location of the DLL for both operating systems is -as follows: - -Windows 32-bit: C:\Program Files\Unity\Editor\Data\Managed -Windows 64-bit: C:\Program Files (x86)\Unity\Editor\Data\Managed\ - - diff --git a/critterai/.svn/pristine/5a/5a21d1cf6a5fe237704e4ada33b5a620366c3f51.svn-base b/critterai/.svn/pristine/5a/5a21d1cf6a5fe237704e4ada33b5a620366c3f51.svn-base deleted file mode 100644 index 8728a17d..00000000 --- a/critterai/.svn/pristine/5a/5a21d1cf6a5fe237704e4ada33b5a620366c3f51.svn-base +++ /dev/null @@ -1,110 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.assertTrue; -import static org.critterai.nmgen.OpenHeightFieldUtil.*; - -import org.junit.Test; - -/** - * Test the detection and resolution of a special case - * where a region wraps an outer corner of a null region - * This can result in self-intersecting polygons during polygon - * generation. - * - * Governing pattern: - * - * a a - * a x - */ -public class NullRegionShortWrapTests -{ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - @Test - public void testNoPreferenceSelection() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(0, 4).setRegionID(2); - field.getData(0, 5).setRegionID(2); - field.getData(1, 3).setRegionID(2); - field.getData(1, 4).setRegionID(2); - field.getData(1, 5).setRegionID(2); - field.getData(2, 4).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(0, 5).regionID() == 2); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(1, 5).regionID() == 2); - - assertTrue((field.getData(1, 3).regionID() == 1 - && field.getData(2, 4).regionID() == 2) - || (field.getData(1, 3).regionID() == 2 - && field.getData(2, 4).regionID() == 1)); - - } - - @Test - public void testNoAlternative() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(3, 4).setRegionID(2); - field.getData(3, 5).setRegionID(NULL_REGION); - field.getData(4, 3).setRegionID(2); - field.getData(4, 4).setRegionID(2); - field.getData(5, 3).setRegionID(2); - field.getData(5, 4).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - // No change expected. - assertTrue(field.getData(3, 4).regionID() == 2); - assertTrue(field.getData(3, 5).regionID() == NULL_REGION); - assertTrue(field.getData(4, 3).regionID() == 2); - assertTrue(field.getData(4, 4).regionID() == 2); - assertTrue(field.getData(5, 3).regionID() == 2); - assertTrue(field.getData(5, 4).regionID() == 2); - - } - - @Test - public void testNoBreakAllowed() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(2, 1).setRegionID(2); - field.getData(3, 1).setRegionID(2); - field.getData(4, 1).setRegionID(2); - field.getData(4, 2).setRegionID(2); - field.getData(4, 3).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - // No change expected. - assertTrue(field.getData(2, 1).regionID() == 2); - assertTrue(field.getData(3, 1).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == 2); - assertTrue(field.getData(4, 2).regionID() == 2); - assertTrue(field.getData(4, 3).regionID() == 2); - } - - -} diff --git a/critterai/.svn/pristine/5a/5a25602480171dc2e2a62188c0193263116e5b07.svn-base b/critterai/.svn/pristine/5a/5a25602480171dc2e2a62188c0193263116e5b07.svn-base deleted file mode 100644 index 2e12048c..00000000 Binary files a/critterai/.svn/pristine/5a/5a25602480171dc2e2a62188c0193263116e5b07.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/5a/5aa8a72145b4be1bfa644eda725ffeaa4eff5c73.svn-base b/critterai/.svn/pristine/5a/5aa8a72145b4be1bfa644eda725ffeaa4eff5c73.svn-base deleted file mode 100644 index c309b17e..00000000 Binary files a/critterai/.svn/pristine/5a/5aa8a72145b4be1bfa644eda725ffeaa4eff5c73.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/5b/5b6dcb3e24933f786388e129cc87874095c8ba26.svn-base b/critterai/.svn/pristine/5b/5b6dcb3e24933f786388e129cc87874095c8ba26.svn-base deleted file mode 100644 index 5e7191c5..00000000 --- a/critterai/.svn/pristine/5b/5b6dcb3e24933f786388e129cc87874095c8ba26.svn-base +++ /dev/null @@ -1,713 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.Vector2.*; -import static org.junit.Assert.*; - -import static org.critterai.math.MathUtil.*; -import org.critterai.math.Vector2; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Vector2} class. - */ -public class Vector2Tests { - - public static final float AX = 1.5f; - public static final float AY = 8.0f; - public static final float BX = -17.112f; - public static final float BY = 77.5f; - - private Vector2 mA1; - private Vector2 mA2; - private Vector2 mB1; - private Vector2 mC1; - - @Before - public void setUp() - throws Exception - { - mA1 = new Vector2(AX, AY); - mA2 = new Vector2(AX, AY); - mB1 = new Vector2(BX, BY); - mC1 = new Vector2(AY, AX); - } - - @Test - public void testConstructorDefault() - { - Vector2 v = new Vector2(); - assertTrue(v.x == 0 && v.y == 0); - } - - @Test - public void testConstructorFloatFloat() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(v.x == AX && v.y == AY); - } - - @Test - public void testDotFloat() - { - float result = mA1.dot(BX, BY); - float expected = (AX * BX) + (AY * BY); - assertTrue(result == expected); - } - - @Test - public void testDotVector2() - { - float result = mA1.dot(mB1); - float expected = (AX * BX) + (AY * BY); - assertTrue(result == expected); - } - - @Test - public void testEqualsFloat() - { - assertTrue(mA1.equals(AX, AY)); - assertFalse(mA1.equals(AY, AX)); - } - - @Test - public void testEqualsObject() - { - assertTrue(mA1.equals((Object)mA2)); - assertFalse(mA1.equals((Object)mB1)); - assertFalse(mA1.equals((Object)mC1)); - } - - @Test - public void testEqualsVector2() - { - assertTrue(mA1.equals(mA2)); - assertFalse(mA1.equals(mB1)); - assertFalse(mA1.equals(mC1)); - } - - @Test - public void testFields() - { - assertTrue(mA1.x == AX); - assertTrue(mB1.x == BX); - assertTrue(mA1.y == AY); - assertTrue(mB1.y == BY); - } - - @Test - public void testGetX() - { - assertTrue(mA1.getX() == AX); - } - - @Test - public void testGetY() - { - assertTrue(mA1.getY() == AY); - } - - @Test - public void testHashCode() - { - assertTrue(mA1.hashCode() == mA2.hashCode()); - assertTrue(mA1.hashCode() != mB1.hashCode()); - assertTrue(mA1.hashCode() != mC1.hashCode()); - } - - @Test - public void testIsZeroLength() - { - assertTrue(new Vector2().isZeroLength()); - assertFalse(mA1.isZeroLength()); - } - - @Test - public void testLengthSq() - { - float len = (AX * AX) + (AY * AY); - assertTrue(mA1.lengthSq() == len); - } - - @Test - public void testMutatorAddFloat() - { - assertTrue(mA1.add(BX, BY) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - } - - @Test - public void testMutatorAddVector2() - { - assertTrue(mA1.add(mB1) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - } - - @Test - public void testMutatorDivide() - { - assertTrue(mA1.divide(5) == mA1); - assertTrue(mA1.x == AX / 5); - assertTrue(mA1.y == AY / 5); - } - - @Test - public void testMutatorMultiply() - { - assertTrue(mA1.multiply(5) == mA1); - assertTrue(mA1.x == AX * 5); - assertTrue(mA1.y == AY * 5); - } - - @Test - public void testMutatorNormalize() - { - float len = (float) Math.sqrt((AX * AX) + (AY * AY)); - float expectedX = AX / len; - float expectedY = AY / len; - - assertTrue(mA1.normalize() == mA1); - assertTrue(mA1.x == expectedX); - assertTrue(mA1.y == expectedY); - } - - @Test - public void testMutatorReverse() - { - assertTrue(mA1.reverse() == mA1); - assertTrue(mA1.x == -AX); - assertTrue(mA1.y == -AY); - } - - @Test - public void testMutatorRotate() - { - // Only a simple test. Rotate 90 degrees counter clockwise. - Vector2 u = new Vector2(1, 0); - assertTrue(u.rotate((float)(Math.PI / 2)) == u); - assertTrue(u.x > -0.001 - && u.x < 0.001 - && u.y > 0.999 - && u.y < 1.001); - } - - @Test - public void testMutatorScaleTo() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.scaleTo(15.0f) == mA1); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - mA1 = new Vector2(AX, AY).scaleTo(0); - assertTrue(mA1.x == 0 && mA1.y == 0); - } - - @Test - public void testMutatorSubtractFloat() - { - assertTrue(mA1.subtract(BX, BY) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - } - - @Test - public void testMutatorSubtractVector() - { - assertTrue(mA1.subtract(mB1) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - } - - @Test - public void testMutatorTruncateLength() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.truncateLength(15.0f) == mA1); - assertTrue(mA1.x == AX && mA1.y == AY); - - mA1 = new Vector2(AX, AY).truncateLength(5); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - mA1 = new Vector2(AX, AY).truncateLength(0); - assertTrue(mA1.x == 0 && mA1.y == 0); - } - - @Test - public void testMutatorXValue() - { - mA1.setX(BX); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == AY); - } - - @Test - public void testMutatorYValue() - { - mA1.setY(BY); - assertTrue(mA1.x == AX); - assertTrue(mA1.y == BY); - } - - @Test - public void testSetValueFloat() - { - assertTrue(mA1 == mA1.set(BX, BY)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - } - - @Test - public void testSetValueVector2() - { - assertTrue(mA1 == mA1.set(mB1)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - } - - @Test - public void testSloppyEqualsFloat() - { - assertTrue(mA1.sloppyEquals(AX, AY, 0.0f)); - - mA1 = new Vector2(AX + 0.019f, AY); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - - mA1 = new Vector2(AX - 0.019f, AY); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - - mA1 = new Vector2(AX, AY + 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - - mA1 = new Vector2(AX, AY - 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - } - - @Test - public void testSloppyEqualsVector2() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(v.sloppyEquals(mA1, 0.0f)); - - v = new Vector2(AX + 0.019f, AY); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector2(AX - 0.019f, AY); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector2(AX, AY + 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector2(AX, AY - 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - } - - @Test - public void testStaticAddValueFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(AX, AY, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - } - - @Test - public void testStaticAddValueVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - } - - @Test - public void testStaticDivideFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = divide(AX, AY, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - } - - @Test - public void testStaticDivideVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = divide(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - } - - @Test - public void testStaticDotFloat() - { - float expected = (AX * BX) + (AY * BY); - assertTrue(dot(AX, AY, BX, BY) == expected); - } - - @Test - public void testStaticGetDirectionABArray() - { - float sos = (float)Math.sqrt(0.5f); // 0.707 - float[] v = new float[2]; - float[] u = getDirectionAB(1, 1, 3, 3, v, 0); - assertTrue(u == v); - assertTrue(sloppyEquals(u[0], sos, 0.0001f) - && sloppyEquals(u[1], sos, 0.0001f)); - - v = new float[4]; // << - u = getDirectionAB(3, 3, 1, 1, v, 1); - assertTrue(u == v); - assertTrue(sloppyEquals(u[2], -sos, 0.0001f) - && sloppyEquals(u[3], -sos, 0.0001f)); - - u = getDirectionAB(1, 1, -1, 3, v, 0); - assertTrue(sloppyEquals(u[0], -sos, 0.0001f) - && sloppyEquals(u[1], sos, 0.0001f)); - - u = getDirectionAB(1, 1, 3, -1, v, 0); - assertTrue(sloppyEquals(u[0], sos, 0.0001f) - && sloppyEquals(u[1], -sos, 0.0001f)); - - } - - @Test - public void testStaticGetDirectionABVector() - { - float sos = (float)Math.sqrt(0.5f); // 0.707 - Vector2 v = new Vector2(); - Vector2 u = getDirectionAB(1, 1, 3, 3, v); - assertTrue(u == v); - assertTrue(sloppyEquals(u.x, sos, 0.0001f) - && sloppyEquals(u.y, sos, 0.0001f)); - - u = getDirectionAB(3, 3, 1, 1, v); - assertTrue(sloppyEquals(u.x, -sos, 0.0001f) - && sloppyEquals(u.y, -sos, 0.0001f)); - - u = getDirectionAB(1, 1, -1, 3, v); - assertTrue(sloppyEquals(u.x, -sos, 0.0001f) - && sloppyEquals(u.y, sos, 0.0001f)); - } - - - @Test - public void testStaticGetDistanceSqFloat() - { - float result = getDistanceSq(AX, AY, BX, BY); - float deltaX = BX - AX; - float deltaY = BY - AY; - float expected = (deltaX * deltaX) + (deltaY * deltaY); - assertTrue(result == expected); - } - - @Test - public void testStaticGetDistanceSqVector() - { - float result = getDistanceSq(mA1, mB1); - float deltaX = BX - AX; - float deltaY = BY - AY; - float expected = (deltaX * deltaX) + (deltaY * deltaY); - assertTrue(result == expected); - } - - @Test - public void testStaticGetLengthSq() - { - float len = (AX * AX) + (AY * AY); - assertTrue(getLengthSq(AX, AY) == len); - } - - @Test - public void testStaticMultiplyFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = multiply(AX, AY, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - } - - @Test - public void testStaticMultiplyVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = multiply(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - } - - @Test - public void testStaticNormalizeFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = normalize(AX, AY, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY)); - float x = AX / len; - float y = AY / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y); - } - - @Test - public void testStaticNormalizeVector() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = normalize(mA1, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY)); - float x = AX / len; - float y = AY / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y); - } - - @Test - public void testStaticRotateFloat() - { - // Only a simple test. Rotate 90 degrees counter clockwise. - Vector2 v = new Vector2(AX, AY); - Vector2 u = rotate(1, 0, (float)(Math.PI / 2), v); - assertTrue(u.x > -0.001 - && u.x < 0.001 - && u.y > 0.999 - && u.y < 1.001); - } - - @Test - public void testStaticRotateVector2() - { - // Only a simple test. Rotate 90 degrees counter clockwise. - Vector2 v = new Vector2(AX, AY); - Vector2 u = new Vector2(1, 0); - u = rotate(u, (float)(Math.PI / 2), v); - assertTrue(u == v); - assertTrue(u.x > -0.001 - && u.x < 0.001 - && u.y > 0.999 - && u.y < 1.001); - } - - @Test - public void testStaticScaleToFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = scaleTo(AX, AY, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(AX, AY, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticScaleToVector2() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = scaleTo(mA1, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticSloppyEqualsFloat() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - - v = new Vector2(AX + 0.019f, AY); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - - v = new Vector2(AX - 0.019f, AY); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - - v = new Vector2(AX, AY + 0.019f); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - - v = new Vector2(AX, AY - 0.019f); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - } - - @Test - public void testStaticSloppyEqualsVector2() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(sloppyEquals(mA1, v, 0.0f)); - - v = new Vector2(AX + 0.019f, AY); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector2(AX - 0.019f, AY); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector2(AX, AY + 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector2(AX, AY - 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - } - - @Test - public void testStaticSubtractFloats() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = subtract(AX, AY, BX, BY, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - } - - @Test - public void testStaticSubtractVectors() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = subtract(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - } - - @Test - public void testStaticTruncateLengthFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = truncateLength(AX, AY, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY); - - u = truncateLength(AX, AY, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(AX, AY, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticTruncateLengthVector2() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = truncateLength(mA1, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY); - - u = truncateLength(mA1, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticVectorAddFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(AX, AY, BX, BY, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - } - - @Test - public void testStaticVectorAddVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - } - -} diff --git a/critterai/.svn/pristine/5b/5b893f271a10fcfc56ce20615e0e40a3207b349c.svn-base b/critterai/.svn/pristine/5b/5b893f271a10fcfc56ce20615e0e40a3207b349c.svn-base deleted file mode 100644 index 5f124ce6..00000000 --- a/critterai/.svn/pristine/5b/5b893f271a10fcfc56ce20615e0e40a3207b349c.svn-base +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai; - -/// -/// Provides data used to assign an area during an NMGen build. -/// -public abstract class NMGenAreaMarker - : NMGenComponent, IPriorityItem -{ - [SerializeField] - private byte mArea = MaxArea; - - [SerializeField] - private int mPriority = 100; - - /// - /// The priority of the marker. - /// - public int Priority - { - get { return mPriority; } - set { mPriority = Mathf.Max(ushort.MinValue, Mathf.Min(ushort.MaxValue, value)); } - } - - /// - /// The area to assign. - /// - public byte Area - { - get { return mArea; } - set { mArea = ClampArea(value); } - } - - /// - /// The area to assign. (Integer version.) - /// - public int AreaInt - { - get { return mArea; } - set { mArea = ClampArea(value); } - } -} diff --git a/critterai/.svn/pristine/5b/5b97f466332235202c687bf128b78f2f093f041d.svn-base b/critterai/.svn/pristine/5b/5b97f466332235202c687bf128b78f2f093f041d.svn-base deleted file mode 100644 index e814b62a..00000000 --- a/critterai/.svn/pristine/5b/5b97f466332235202c687bf128b78f2f093f041d.svn-base +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURALLOCATOR_H -#define DETOURALLOCATOR_H - -/// Provides hint values to the memory allocator on how long the -/// memory is expected to be used. -enum dtAllocHint -{ - DT_ALLOC_PERM, ///< Memory persist after a function call. - DT_ALLOC_TEMP ///< Memory used temporarily within a function. -}; - -/// A memory allocation function. -// @param[in] size The size, in bytes of memory, to allocate. -// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use. -// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. -/// @see dtAllocSetCustom -typedef void* (dtAllocFunc)(int size, dtAllocHint hint); - -/// A memory deallocation function. -/// @param[in] ptr A pointer to a memory block previously allocated using #dtAllocFunc. -/// @see dtAllocSetCustom -typedef void (dtFreeFunc)(void* ptr); - -/// Sets the base custom allocation functions to be used by Detour. -/// @param[in] allocFunc The memory allocation function to be used by #dtAlloc -/// @param[in] freeFunc The memory de-allocation function to be used by #dtFree -void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc); - -/// Allocates a memory block. -/// @param[in] size The size, in bytes of memory, to allocate. -/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use. -/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. -/// @see dtFree -void* dtAlloc(int size, dtAllocHint hint); - -/// Deallocates a memory block. -/// @param[in] ptr A pointer to a memory block previously allocated using #dtAlloc. -/// @see dtAlloc -void dtFree(void* ptr); - -#endif diff --git a/critterai/.svn/pristine/5b/5bb9bac3e6b485d2a14a7d314de5474c7f7ee130.svn-base b/critterai/.svn/pristine/5b/5bb9bac3e6b485d2a14a7d314de5474c7f7ee130.svn-base deleted file mode 100644 index 130157a6..00000000 --- a/critterai/.svn/pristine/5b/5bb9bac3e6b485d2a14a7d314de5474c7f7ee130.svn-base +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" -#include "RecastAlloc.h" - -struct nmgSpan -{ - unsigned int smin : 13; - unsigned int smax : 13; - unsigned int area : 6; -}; - -struct nmgChunkyNode -{ - float xmin; - float zmin; - float xmax; - float zmax; - int i; - int count; -}; - -extern "C" -{ - EXPORT_API rcHeightfield* nmhfAllocField(const int width - , const int height - , const float* bmin - , const float* bmax - , const float cs - , const float ch) - { - if (!bmin || !bmax) - return 0; - - rcHeightfield* hf = rcAllocHeightfield(); - if (!hf) - return 0; - - if (rcCreateHeightfield(0 - , *hf - , width - , height - , bmin - , bmax - , cs - , ch)) - { - return hf; - } - - rcFreeHeightField(hf); - return 0; - } - - EXPORT_API void nmhfFreeField(rcHeightfield* hf) - { - rcFreeHeightField(hf); - } - - EXPORT_API bool nmhfRasterizeTriangle(nmgBuildContext* ctx - , const float* v - , const unsigned char area - , rcHeightfield* hf - , const int flagMergeThr) - { - if (!ctx || !v || !hf) - return false; - - rcRasterizeTriangle(ctx - , &v[0], &v[3], &v[6] - , area - , *hf - , flagMergeThr); - - return true; - } - - EXPORT_API bool nmhfRasterizeNodes(nmgBuildContext* ctx - , const float* verts - , const int* tris - , const unsigned char* areas - , const nmgChunkyNode* nodes - , const int nc - , rcHeightfield* hf - , const int flagMergeThr) - { - if (!ctx || !verts || !tris || !areas || !nodes || !hf) - return false; - - // Find the maximum number of triangles in a node. - int maxTris = 0; - for (int iNode = 0; iNode < nc; ++iNode) - { - maxTris = rcMax(nodes[iNode].count, maxTris); - } - - int* ltris = (int*)rcAlloc(sizeof(int) * maxTris * 3, RC_ALLOC_TEMP); - - unsigned char* lareas = - (unsigned char*)rcAlloc(sizeof(unsigned char) * maxTris, RC_ALLOC_TEMP); - - if (!ltris || !lareas) - return false; - - // Rasterize each node separately. - for (int iNode = 0; iNode < nc; ++iNode) - { - // Load node triangles into the working arrays. - for (int iTri = 0; iTri < nodes[iNode].count; ++iTri) - { - const int* tbase = &tris[(nodes[iNode].i + iTri) * 3]; - - ltris[iTri * 3 + 0] = tbase[0]; - ltris[iTri * 3 + 1] = tbase[1]; - ltris[iTri * 3 + 2] = tbase[2]; - - lareas[iTri] = areas[nodes[iNode].i + iTri]; - } - - // Rasterize the node. - rcRasterizeTriangles(ctx - , verts - , 0 // Not actually used. - , ltris - , lareas - , nodes[iNode].count - , *hf - , flagMergeThr); - } - - rcFree(ltris); - rcFree(lareas); - - return true; - } - - EXPORT_API bool nmhfRasterizeTriMesh(nmgBuildContext* ctx - , const float* verts - , const int nv - , const int* tris - , const unsigned char* areas - , const int nt - , rcHeightfield* hf - , const int flagMergeThr) - { - if (!ctx || !verts || !tris || !areas || !hf) - return false; - - rcRasterizeTriangles(ctx - , verts - , nv - , tris - , areas - , nt - , *hf - , flagMergeThr); - - return true; - } - - EXPORT_API bool nmhfRasterizeTriMeshShort(nmgBuildContext* ctx - , const float* verts - , const int nv - , const unsigned short* tris - , const unsigned char* areas - , const int nt - , rcHeightfield* hf - , const int flagMergeThr) - { - if (!ctx || !verts || !tris || !areas || !hf) - return false; - - rcRasterizeTriangles(ctx - , verts - , nv - , tris - , areas - , nt - , *hf - , flagMergeThr); - - return true; - } - - EXPORT_API bool nmhfRasterizeTriangles(nmgBuildContext* ctx - , const float* verts - , const unsigned char* areas - , const int nt - , rcHeightfield* hf - , const int flagMergeThr) - { - if (!ctx || !verts || !areas || !hf) - return false; - - rcRasterizeTriangles(ctx - , verts - , areas - , nt - , *hf - , flagMergeThr); - - return true; - } - - EXPORT_API bool nmhfFilterLowHangingWalkableObstacles(nmgBuildContext* ctx - , const int walkableClimb - , rcHeightfield* hf) - { - if (!ctx || !hf) - return false; - - rcFilterLowHangingWalkableObstacles(ctx, walkableClimb, *hf); - - return true; - } - - EXPORT_API bool nmhfFilterLedgeSpans(nmgBuildContext* ctx - , const int walkableHeight - , const int walkableClimb - , rcHeightfield* hf) - { - if (!ctx || !hf) - return false; - - rcFilterLedgeSpans(ctx, walkableHeight, walkableClimb, *hf); - - return true; - } - - EXPORT_API bool nmhfFilterWalkableLowHeightSpans(nmgBuildContext* ctx - , int walkableHeight - , rcHeightfield* hf) - { - if (!ctx || !hf) - return false; - - rcFilterWalkableLowHeightSpans(ctx, walkableHeight, *hf); - - return true; - } - - EXPORT_API int nmhfGetHeightFieldSpanCount(rcHeightfield* hf) - { - if (!hf) - return 0; - - return rcGetHeightFieldSpanCount(0, *hf); - } - - EXPORT_API int nmhfGetMaxSpansInColumn(rcHeightfield* hf) - { - if (!hf) - return 0; - - const int w = hf->width; - const int h = hf->height; - int maxCount = 0; - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - int spanCount = 0; - for (rcSpan* s = hf->spans[x + y*w]; s; s = s->next) - { - if (s->area != RC_NULL_AREA) - spanCount++; - } - maxCount = rcMax(spanCount, maxCount); - } - } - return maxCount; - } - - EXPORT_API int nmhfGetSpans(rcHeightfield* hf - , const int iw - , const int ih - , nmgSpan* spans - , int spanSize) - { - if (!hf || !spans - || iw < 0 || iw > hf->width - || ih < 0 || ih > hf->height) - { - return -1; - } - - int spanCount = 0; - - const int w = hf->width; - for (rcSpan* s = hf->spans[iw + ih*w]; s; s = s->next) - { - if (s->area != RC_NULL_AREA) - { - if (spanCount < spanSize) - { - spans[spanCount].area = s->area; - spans[spanCount].smax = s->smax; - spans[spanCount].smin = s->smin; - spanCount++; - } - else - // Buffer can't fit anymore. - return -1; - } - } - - return spanCount; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/5c/5c6b4f0e047c9209b8b0a728a0f9f516da82cb10.svn-base b/critterai/.svn/pristine/5c/5c6b4f0e047c9209b8b0a728a0f9f516da82cb10.svn-base deleted file mode 100644 index 8cf0a3a9..00000000 --- a/critterai/.svn/pristine/5c/5c6b4f0e047c9209b8b0a728a0f9f516da82cb10.svn-base +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Information related to an input build. (Editor Only) - /// - /// - /// - /// This information is used for GUI presentation and debug purposes. - /// - /// - public struct InputBuildInfo - { - /// - /// The number of components loaded by the loader processors. - /// - public int compCountPre; - - /// - /// The number of components that survived the filter processors. - /// - public int compCountPost; - - /// - /// The number of loader processors applied. - /// - public int loaderCount; - - /// - /// The number of filter processors applied. - /// - public int filterCount; - - /// - /// The number of area modifier processors applied. - /// - public int areaModifierCount; - - /// - /// The number of compiler processors applied. - /// - public int compilerCount; - - /// - /// The number of post-processors applied. - /// - public int postCount; - } -} diff --git a/critterai/.svn/pristine/5d/5db2a9fb584c4825c410a9c5d6d35f6be238b710.svn-base b/critterai/.svn/pristine/5d/5db2a9fb584c4825c410a9c5d6d35f6be238b710.svn-base deleted file mode 100644 index c21313aa..00000000 --- a/critterai/.svn/pristine/5d/5db2a9fb584c4825c410a9c5d6d35f6be238b710.svn-base +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - The NMGen ease-of-use extensions for Unity provide GUI-level access to almost all of the NMGen features. You can build navigation meshes - with a single click. Or you can build, tweek, and rebuild selected zones of navigations meshes using advanced GUI features. - - - - All NMGen assets and support code are 'editor only'. So they have zero impact on scene size and are not included in the Unity project build. - (No data or code bloat.) The only impact on the scene will be if you need to create custom scene for things like off-mesh connections - and area markers. - - - - The Unity NMGen build process is pretty much the same as the standard build process describe by - . - The Unity extensions take care of gathering scene components and compiling them into input data, and provide ways to adjust the build via GUI - editors rather than requiring you to code things. - - - - -
- - The Main NMGen Build Assets - - - - - As noted above, the NMGen build process and all associated assets are implemented as project assets, not scene components. The only time you will need - NMGen specific components in a scene is if you need to manually annotate something special that you want to include in the build. - (E.g. Off-mesh connections.) The below diagram shows the main assets and how they are related from an input/output perspective. - - - - - - - - The central asset is the T:NavmeshBuild asset. It defines the build configuration and holds all intermediate - build data created during the build. - - - - The build uses a scene query asset to determine which scene components will be included in the build. Any ScritableObject that - implements the T:org.critterai.nmbuild.u3d.editor.ISceneQuery interface can be used. For example, - if you want the build to gather scene components based on tags, then you'll use the T:TagSceneQuery asset. - - - - Input processors do the heavy lifting such as triangulating MeshFilter and Terrain components, adding INMGenProcessor objects to the build, etc. - Any ScriptableObject that implements the T:org.critterai.nmbuild.u3d.editor.IInputBuildProcessor interface can be used. - - - - The bake target is the asset that will get the result of the build. (The navigation mesh.) Any ScritableObject that - implements the T:org.critterai.nav.u3d.INavmeshData interface can be used. The normal - target will be a T:CAIBakedNavmesh asset. Note that this is a navigation asset, not an NMGen asset, - so it can be distributed as part of the project compile and be referenced by scene components. - - - - -
- -
- - The NavmeshBuild Asset - - - - - At the core of the Unity NMGen build process is the T:NavmeshBuild asset. It is created using one of the - CritterAI->Create NMGenAsset->Navmesh Build menu items, usually the Standard option. Once added to the project you'll be presented with - the following inspector. - - - - - - - - The upper section of the inspector contains the primary build controls and build target assignment. Since it is possible to reassign the target - you can use a single configuration to build any number of navigation meshes. Just reassign the target, open the target's input scene, and build. - - - - The center section contains the NMGen configuration. It is defaults to values suitable for generic human-sized agents. - - - - The lower section contains the input configuration. The scene query is optional. If none is provided then the search will be global. E.g. - All MeshFilters in the scene. There has to be at least one input processor for the build to produce anything. - - - - -
- - - - - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/5e/5e07a63c6af16a2cf37862b6c57f84cb21dbb01a.svn-base b/critterai/.svn/pristine/5e/5e07a63c6af16a2cf37862b6c57f84cb21dbb01a.svn-base deleted file mode 100644 index 8e5d6cba..00000000 Binary files a/critterai/.svn/pristine/5e/5e07a63c6af16a2cf37862b6c57f84cb21dbb01a.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/5e/5e6a46ae1435a396c072d0d1f5ec01d0b06b4d32.svn-base b/critterai/.svn/pristine/5e/5e6a46ae1435a396c072d0d1f5ec01d0b06b4d32.svn-base deleted file mode 100644 index e6028a1a..00000000 --- a/critterai/.svn/pristine/5e/5e6a46ae1435a396c072d0d1f5ec01d0b06b4d32.svn-base +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/5e/5ef6678410a0dd79a85ec4de6c15594359d1027d.svn-base b/critterai/.svn/pristine/5e/5ef6678410a0dd79a85ec4de6c15594359d1027d.svn-base deleted file mode 100644 index ade1f41d..00000000 --- a/critterai/.svn/pristine/5e/5ef6678410a0dd79a85ec4de6c15594359d1027d.svn-base +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.nmgen; -using UnityEngine; - -/// -/// Applies a default area to all components in an input build. (Editor Only) -/// -/// -/// -/// Normally all components in an input build get a default area of . -/// This processor allows a different default to be assigned. -/// -/// -[System.Serializable] -public sealed class DefaultAreaDef - : ScriptableObject, IInputBuildProcessor -{ - [SerializeField] - private byte mDefaultArea = NMGen.MaxArea; - - /// - /// The default area to assign. - /// - public byte DefaultArea - { - get { return mDefaultArea; } - set { mDefaultArea = NMGen.ClampArea(value); } - } - - /// - /// The priority of the processor. - /// - public int Priority { get { return NMBuild.MinPriority - 1; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// Duplicates not allowed. (Always false.) - /// - public bool DuplicatesAllowed { get { return false; } } - - /// - /// Processes the context. - /// - /// - /// - /// Applied during the state. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (state == InputBuildState.ApplyAreaModifiers) - { - context.info.areaModifierCount++; - - List areas = context.areas; - - for (int i = 0; i < areas.Count; i++) - { - areas[i] = mDefaultArea; - } - - string msg = string.Format("{0}: Applied default area to all components: {1}" - , name, mDefaultArea); - - context.Log(msg, this); - } - - return true; - } -} diff --git a/critterai/.svn/pristine/5f/5f263d86459475490be9214733cf43fb895eab21.svn-base b/critterai/.svn/pristine/5f/5f263d86459475490be9214733cf43fb895eab21.svn-base deleted file mode 100644 index 579fcb47..00000000 --- a/critterai/.svn/pristine/5f/5f263d86459475490be9214733cf43fb895eab21.svn-base +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.nmbuild; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(MeshInputFilter))] -public sealed class MeshInputFilterEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - MeshInputFilter targ = (MeshInputFilter)target; - - EditorGUILayout.Separator(); - - // Clamp before sending to property. - targ.Priority = EditorGUILayout.IntField("Priority", targ.Priority); - - targ.matchType = (MatchType) - EditorGUILayout.EnumPopup("Match Type", targ.matchType); - - EditorGUILayout.Separator(); - - EditorUtil.OnGUIManageObjectList("Meshes", targ.meshes, false); - - EditorGUILayout.Separator(); - - string msg = "Input Build Processor\n\nFilters out " + typeof(MeshFilter).Name - + " components that reference the specified " + typeof(Mesh).Name + " objects.\n\n"; - - switch (targ.matchType) - { - case MatchType.Strict: - - msg += "Will match only on strict mesh equality."; - break; - - case MatchType.NameBeginsWith: - - msg += "Will match any mesh that starts with the mesh names. Example: If the" - + " source mesh name is 'Column', then 'ColumnWooden' and 'Column Iron' will" - + " match."; - break; - - case MatchType.AnyInstance: - - msg += "Will match any instance, based on name. The check is lazy. Example:" - + " If the source mesh name is 'SwampMesh', then both 'SwampMesh Instance' and " - + " 'SwampMesh NotReallyAnInstance' will match."; - break; - } - - GUILayout.Box(msg, EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Component Filter : Mesh", false, NMBEditorUtil.FilterGroup)] - static void CreateAsset() - { - MeshInputFilter item = - EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/60/602b82a784a4007dd9f7311d7a79378d8741c4e4.svn-base b/critterai/.svn/pristine/60/602b82a784a4007dd9f7311d7a79378d8741c4e4.svn-base deleted file mode 100644 index 7929cf31..00000000 Binary files a/critterai/.svn/pristine/60/602b82a784a4007dd9f7311d7a79378d8741c4e4.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/60/604bef6cd29d0a5dc970f8d95e4b344cf3fe3c98.svn-base b/critterai/.svn/pristine/60/604bef6cd29d0a5dc970f8d95e4b344cf3fe3c98.svn-base deleted file mode 100644 index df2c3f1b..00000000 --- a/critterai/.svn/pristine/60/604bef6cd29d0a5dc970f8d95e4b344cf3fe3c98.svn-base +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.u3d.editor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class CoreFailureControl - : BuildControl - { - private static GUIStyle mBoxStyle = null; - - public CoreFailureControl() { } - - public override bool Enter(ControlContext context, DebugViewContext debug) - { - if (base.Enter(context, debug)) - { - // Unforgiving. - Context.Build.ResetBuild(); - return true; - } - - return false; - } - - public override void Exit() - { - if (Context.Build != null) - // Still unforgiving. - Context.Build.ResetBuild(); - - base.Exit(); - } - - protected override void OnGUIMain() - { - NavmeshBuild build = Context.Build; - - if (mBoxStyle == null) - { - mBoxStyle = new GUIStyle(EditorUtil.ErrorStyle); - mBoxStyle.alignment = TextAnchor.MiddleCenter; - } - - GUI.Box(Context.MainArea - , (build ? build.name : "Unknown build") + " is not ready to build!\n" - + "Issue(s) must be corrected before a build can be started." - , mBoxStyle); - } - - protected override void OnGUIButtons() - { - ControlUtil.BeginButtonArea(Context.ButtonArea); - ControlUtil.EndButtonArea(); - } - } -} diff --git a/critterai/.svn/pristine/60/6054bc0b78eefa194e8a522ca7374f9e0ce2adb4.svn-base b/critterai/.svn/pristine/60/6054bc0b78eefa194e8a522ca7374f9e0ce2adb4.svn-base deleted file mode 100644 index c06d7208..00000000 Binary files a/critterai/.svn/pristine/60/6054bc0b78eefa194e8a522ca7374f9e0ce2adb4.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/60/60b94e4ba23a4eec220e8aa8c70d0d04b1e04a2f.svn-base b/critterai/.svn/pristine/60/60b94e4ba23a4eec220e8aa8c70d0d04b1e04a2f.svn-base deleted file mode 100644 index 13aad2af..00000000 --- a/critterai/.svn/pristine/60/60b94e4ba23a4eec220e8aa8c70d0d04b1e04a2f.svn-base +++ /dev/null @@ -1,1428 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#define _USE_MATH_DEFINES -#include -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" - -struct rcEdge -{ - unsigned short vert[2]; - unsigned short polyEdge[2]; - unsigned short poly[2]; -}; - -static bool buildMeshAdjacency(unsigned short* polys, const int npolys, - const int nverts, const int vertsPerPoly) -{ - // Based on code by Eric Lengyel from: - // http://www.terathon.com/code/edges.php - - int maxEdgeCount = npolys*vertsPerPoly; - unsigned short* firstEdge = (unsigned short*)rcAlloc(sizeof(unsigned short)*(nverts + maxEdgeCount), RC_ALLOC_TEMP); - if (!firstEdge) - return false; - unsigned short* nextEdge = firstEdge + nverts; - int edgeCount = 0; - - rcEdge* edges = (rcEdge*)rcAlloc(sizeof(rcEdge)*maxEdgeCount, RC_ALLOC_TEMP); - if (!edges) - { - rcFree(firstEdge); - return false; - } - - for (int i = 0; i < nverts; i++) - firstEdge[i] = RC_MESH_NULL_IDX; - - for (int i = 0; i < npolys; ++i) - { - unsigned short* t = &polys[i*vertsPerPoly*2]; - for (int j = 0; j < vertsPerPoly; ++j) - { - if (t[j] == RC_MESH_NULL_IDX) break; - unsigned short v0 = t[j]; - unsigned short v1 = (j+1 >= vertsPerPoly || t[j+1] == RC_MESH_NULL_IDX) ? t[0] : t[j+1]; - if (v0 < v1) - { - rcEdge& edge = edges[edgeCount]; - edge.vert[0] = v0; - edge.vert[1] = v1; - edge.poly[0] = (unsigned short)i; - edge.polyEdge[0] = (unsigned short)j; - edge.poly[1] = (unsigned short)i; - edge.polyEdge[1] = 0; - // Insert edge - nextEdge[edgeCount] = firstEdge[v0]; - firstEdge[v0] = (unsigned short)edgeCount; - edgeCount++; - } - } - } - - for (int i = 0; i < npolys; ++i) - { - unsigned short* t = &polys[i*vertsPerPoly*2]; - for (int j = 0; j < vertsPerPoly; ++j) - { - if (t[j] == RC_MESH_NULL_IDX) break; - unsigned short v0 = t[j]; - unsigned short v1 = (j+1 >= vertsPerPoly || t[j+1] == RC_MESH_NULL_IDX) ? t[0] : t[j+1]; - if (v0 > v1) - { - for (unsigned short e = firstEdge[v1]; e != RC_MESH_NULL_IDX; e = nextEdge[e]) - { - rcEdge& edge = edges[e]; - if (edge.vert[1] == v0 && edge.poly[0] == edge.poly[1]) - { - edge.poly[1] = (unsigned short)i; - edge.polyEdge[1] = (unsigned short)j; - break; - } - } - } - } - } - - // Store adjacency - for (int i = 0; i < edgeCount; ++i) - { - const rcEdge& e = edges[i]; - if (e.poly[0] != e.poly[1]) - { - unsigned short* p0 = &polys[e.poly[0]*vertsPerPoly*2]; - unsigned short* p1 = &polys[e.poly[1]*vertsPerPoly*2]; - p0[vertsPerPoly + e.polyEdge[0]] = e.poly[1]; - p1[vertsPerPoly + e.polyEdge[1]] = e.poly[0]; - } - } - - rcFree(firstEdge); - rcFree(edges); - - return true; -} - - -static const int VERTEX_BUCKET_COUNT = (1<<12); - -inline int computeVertexHash(int x, int y, int z) -{ - const unsigned int h1 = 0x8da6b343; // Large multiplicative constants; - const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes - const unsigned int h3 = 0xcb1ab31f; - unsigned int n = h1 * x + h2 * y + h3 * z; - return (int)(n & (VERTEX_BUCKET_COUNT-1)); -} - -static unsigned short addVertex(unsigned short x, unsigned short y, unsigned short z, - unsigned short* verts, int* firstVert, int* nextVert, int& nv) -{ - int bucket = computeVertexHash(x, 0, z); - int i = firstVert[bucket]; - - while (i != -1) - { - const unsigned short* v = &verts[i*3]; - if (v[0] == x && (rcAbs(v[1] - y) <= 2) && v[2] == z) - return (unsigned short)i; - i = nextVert[i]; // next - } - - // Could not find, create new. - i = nv; nv++; - unsigned short* v = &verts[i*3]; - v[0] = x; - v[1] = y; - v[2] = z; - nextVert[i] = firstVert[bucket]; - firstVert[bucket] = i; - - return (unsigned short)i; -} - -inline int prev(int i, int n) { return i-1 >= 0 ? i-1 : n-1; } -inline int next(int i, int n) { return i+1 < n ? i+1 : 0; } - -inline int area2(const int* a, const int* b, const int* c) -{ - return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]); -} - -// Exclusive or: true iff exactly one argument is true. -// The arguments are negated to ensure that they are 0/1 -// values. Then the bitwise Xor operator may apply. -// (This idea is due to Michael Baldwin.) -inline bool xorb(bool x, bool y) -{ - return !x ^ !y; -} - -// Returns true iff c is strictly to the left of the directed -// line through a to b. -inline bool left(const int* a, const int* b, const int* c) -{ - return area2(a, b, c) < 0; -} - -inline bool leftOn(const int* a, const int* b, const int* c) -{ - return area2(a, b, c) <= 0; -} - -inline bool collinear(const int* a, const int* b, const int* c) -{ - return area2(a, b, c) == 0; -} - -// Returns true iff ab properly intersects cd: they share -// a point interior to both segments. The properness of the -// intersection is ensured by using strict leftness. -static bool intersectProp(const int* a, const int* b, const int* c, const int* d) -{ - // Eliminate improper cases. - if (collinear(a,b,c) || collinear(a,b,d) || - collinear(c,d,a) || collinear(c,d,b)) - return false; - - return xorb(left(a,b,c), left(a,b,d)) && xorb(left(c,d,a), left(c,d,b)); -} - -// Returns T iff (a,b,c) are collinear and point c lies -// on the closed segement ab. -static bool between(const int* a, const int* b, const int* c) -{ - if (!collinear(a, b, c)) - return false; - // If ab not vertical, check betweenness on x; else on y. - if (a[0] != b[0]) - return ((a[0] <= c[0]) && (c[0] <= b[0])) || ((a[0] >= c[0]) && (c[0] >= b[0])); - else - return ((a[2] <= c[2]) && (c[2] <= b[2])) || ((a[2] >= c[2]) && (c[2] >= b[2])); -} - -// Returns true iff segments ab and cd intersect, properly or improperly. -static bool intersect(const int* a, const int* b, const int* c, const int* d) -{ - if (intersectProp(a, b, c, d)) - return true; - else if (between(a, b, c) || between(a, b, d) || - between(c, d, a) || between(c, d, b)) - return true; - else - return false; -} - -static bool vequal(const int* a, const int* b) -{ - return a[0] == b[0] && a[2] == b[2]; -} - -// Returns T iff (v_i, v_j) is a proper internal *or* external -// diagonal of P, *ignoring edges incident to v_i and v_j*. -static bool diagonalie(int i, int j, int n, const int* verts, int* indices) -{ - const int* d0 = &verts[(indices[i] & 0x0fffffff) * 4]; - const int* d1 = &verts[(indices[j] & 0x0fffffff) * 4]; - - // For each edge (k,k+1) of P - for (int k = 0; k < n; k++) - { - int k1 = next(k, n); - // Skip edges incident to i or j - if (!((k == i) || (k1 == i) || (k == j) || (k1 == j))) - { - const int* p0 = &verts[(indices[k] & 0x0fffffff) * 4]; - const int* p1 = &verts[(indices[k1] & 0x0fffffff) * 4]; - - if (vequal(d0, p0) || vequal(d1, p0) || vequal(d0, p1) || vequal(d1, p1)) - continue; - - if (intersect(d0, d1, p0, p1)) - return false; - } - } - return true; -} - -// Returns true iff the diagonal (i,j) is strictly internal to the -// polygon P in the neighborhood of the i endpoint. -static bool inCone(int i, int j, int n, const int* verts, int* indices) -{ - const int* pi = &verts[(indices[i] & 0x0fffffff) * 4]; - const int* pj = &verts[(indices[j] & 0x0fffffff) * 4]; - const int* pi1 = &verts[(indices[next(i, n)] & 0x0fffffff) * 4]; - const int* pin1 = &verts[(indices[prev(i, n)] & 0x0fffffff) * 4]; - - // If P[i] is a convex vertex [ i+1 left or on (i-1,i) ]. - if (leftOn(pin1, pi, pi1)) - return left(pi, pj, pin1) && left(pj, pi, pi1); - // Assume (i-1,i,i+1) not collinear. - // else P[i] is reflex. - return !(leftOn(pi, pj, pi1) && leftOn(pj, pi, pin1)); -} - -// Returns T iff (v_i, v_j) is a proper internal -// diagonal of P. -static bool diagonal(int i, int j, int n, const int* verts, int* indices) -{ - return inCone(i, j, n, verts, indices) && diagonalie(i, j, n, verts, indices); -} - -static int triangulate(int n, const int* verts, int* indices, int* tris) -{ - int ntris = 0; - int* dst = tris; - - // The last bit of the index is used to indicate if the vertex can be removed. - for (int i = 0; i < n; i++) - { - int i1 = next(i, n); - int i2 = next(i1, n); - if (diagonal(i, i2, n, verts, indices)) - indices[i1] |= 0x80000000; - } - - while (n > 3) - { - int minLen = -1; - int mini = -1; - for (int i = 0; i < n; i++) - { - int i1 = next(i, n); - if (indices[i1] & 0x80000000) - { - const int* p0 = &verts[(indices[i] & 0x0fffffff) * 4]; - const int* p2 = &verts[(indices[next(i1, n)] & 0x0fffffff) * 4]; - - int dx = p2[0] - p0[0]; - int dy = p2[2] - p0[2]; - int len = dx*dx + dy*dy; - - if (minLen < 0 || len < minLen) - { - minLen = len; - mini = i; - } - } - } - - if (mini == -1) - { - // Should not happen. -/* printf("mini == -1 ntris=%d n=%d\n", ntris, n); - for (int i = 0; i < n; i++) - { - printf("%d ", indices[i] & 0x0fffffff); - } - printf("\n");*/ - return -ntris; - } - - int i = mini; - int i1 = next(i, n); - int i2 = next(i1, n); - - *dst++ = indices[i] & 0x0fffffff; - *dst++ = indices[i1] & 0x0fffffff; - *dst++ = indices[i2] & 0x0fffffff; - ntris++; - - // Removes P[i1] by copying P[i+1]...P[n-1] left one index. - n--; - for (int k = i1; k < n; k++) - indices[k] = indices[k+1]; - - if (i1 >= n) i1 = 0; - i = prev(i1,n); - // Update diagonal flags. - if (diagonal(prev(i, n), i1, n, verts, indices)) - indices[i] |= 0x80000000; - else - indices[i] &= 0x0fffffff; - - if (diagonal(i, next(i1, n), n, verts, indices)) - indices[i1] |= 0x80000000; - else - indices[i1] &= 0x0fffffff; - } - - // Append the remaining triangle. - *dst++ = indices[0] & 0x0fffffff; - *dst++ = indices[1] & 0x0fffffff; - *dst++ = indices[2] & 0x0fffffff; - ntris++; - - return ntris; -} - -static int countPolyVerts(const unsigned short* p, const int nvp) -{ - for (int i = 0; i < nvp; ++i) - if (p[i] == RC_MESH_NULL_IDX) - return i; - return nvp; -} - -inline bool uleft(const unsigned short* a, const unsigned short* b, const unsigned short* c) -{ - return ((int)b[0] - (int)a[0]) * ((int)c[2] - (int)a[2]) - - ((int)c[0] - (int)a[0]) * ((int)b[2] - (int)a[2]) < 0; -} - -static int getPolyMergeValue(unsigned short* pa, unsigned short* pb, - const unsigned short* verts, int& ea, int& eb, - const int nvp) -{ - const int na = countPolyVerts(pa, nvp); - const int nb = countPolyVerts(pb, nvp); - - // If the merged polygon would be too big, do not merge. - if (na+nb-2 > nvp) - return -1; - - // Check if the polygons share an edge. - ea = -1; - eb = -1; - - for (int i = 0; i < na; ++i) - { - unsigned short va0 = pa[i]; - unsigned short va1 = pa[(i+1) % na]; - if (va0 > va1) - rcSwap(va0, va1); - for (int j = 0; j < nb; ++j) - { - unsigned short vb0 = pb[j]; - unsigned short vb1 = pb[(j+1) % nb]; - if (vb0 > vb1) - rcSwap(vb0, vb1); - if (va0 == vb0 && va1 == vb1) - { - ea = i; - eb = j; - break; - } - } - } - - // No common edge, cannot merge. - if (ea == -1 || eb == -1) - return -1; - - // Check to see if the merged polygon would be convex. - unsigned short va, vb, vc; - - va = pa[(ea+na-1) % na]; - vb = pa[ea]; - vc = pb[(eb+2) % nb]; - if (!uleft(&verts[va*3], &verts[vb*3], &verts[vc*3])) - return -1; - - va = pb[(eb+nb-1) % nb]; - vb = pb[eb]; - vc = pa[(ea+2) % na]; - if (!uleft(&verts[va*3], &verts[vb*3], &verts[vc*3])) - return -1; - - va = pa[ea]; - vb = pa[(ea+1)%na]; - - int dx = (int)verts[va*3+0] - (int)verts[vb*3+0]; - int dy = (int)verts[va*3+2] - (int)verts[vb*3+2]; - - return dx*dx + dy*dy; -} - -static void mergePolys(unsigned short* pa, unsigned short* pb, int ea, int eb, - unsigned short* tmp, const int nvp) -{ - const int na = countPolyVerts(pa, nvp); - const int nb = countPolyVerts(pb, nvp); - - // Merge polygons. - memset(tmp, 0xff, sizeof(unsigned short)*nvp); - int n = 0; - // Add pa - for (int i = 0; i < na-1; ++i) - tmp[n++] = pa[(ea+1+i) % na]; - // Add pb - for (int i = 0; i < nb-1; ++i) - tmp[n++] = pb[(eb+1+i) % nb]; - - memcpy(pa, tmp, sizeof(unsigned short)*nvp); -} - - -static void pushFront(int v, int* arr, int& an) -{ - an++; - for (int i = an-1; i > 0; --i) arr[i] = arr[i-1]; - arr[0] = v; -} - -static void pushBack(int v, int* arr, int& an) -{ - arr[an] = v; - an++; -} - -static bool canRemoveVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short rem) -{ - const int nvp = mesh.nvp; - - // Count number of polygons to remove. - int numRemovedVerts = 0; - int numTouchedVerts = 0; - int numRemainingEdges = 0; - for (int i = 0; i < mesh.npolys; ++i) - { - unsigned short* p = &mesh.polys[i*nvp*2]; - const int nv = countPolyVerts(p, nvp); - int numRemoved = 0; - int numVerts = 0; - for (int j = 0; j < nv; ++j) - { - if (p[j] == rem) - { - numTouchedVerts++; - numRemoved++; - } - numVerts++; - } - if (numRemoved) - { - numRemovedVerts += numRemoved; - numRemainingEdges += numVerts-(numRemoved+1); - } - } - - // There would be too few edges remaining to create a polygon. - // This can happen for example when a tip of a triangle is marked - // as deletion, but there are no other polys that share the vertex. - // In this case, the vertex should not be removed. - if (numRemainingEdges <= 2) - return false; - - // Find edges which share the removed vertex. - const int maxEdges = numTouchedVerts*2; - int nedges = 0; - rcScopedDelete edges = (int*)rcAlloc(sizeof(int)*maxEdges*3, RC_ALLOC_TEMP); - if (!edges) - { - ctx->log(RC_LOG_WARNING, "canRemoveVertex: Out of memory 'edges' (%d).", maxEdges*3); - return false; - } - - for (int i = 0; i < mesh.npolys; ++i) - { - unsigned short* p = &mesh.polys[i*nvp*2]; - const int nv = countPolyVerts(p, nvp); - - // Collect edges which touches the removed vertex. - for (int j = 0, k = nv-1; j < nv; k = j++) - { - if (p[j] == rem || p[k] == rem) - { - // Arrange edge so that a=rem. - int a = p[j], b = p[k]; - if (b == rem) - rcSwap(a,b); - - // Check if the edge exists - bool exists = false; - for (int m = 0; m < nedges; ++m) - { - int* e = &edges[m*3]; - if (e[1] == b) - { - // Exists, increment vertex share count. - e[2]++; - exists = true; - } - } - // Add new edge. - if (!exists) - { - int* e = &edges[nedges*3]; - e[0] = a; - e[1] = b; - e[2] = 1; - nedges++; - } - } - } - } - - // There should be no more than 2 open edges. - // This catches the case that two non-adjacent polygons - // share the removed vertex. In that case, do not remove the vertex. - int numOpenEdges = 0; - for (int i = 0; i < nedges; ++i) - { - if (edges[i*3+2] < 2) - numOpenEdges++; - } - if (numOpenEdges > 2) - return false; - - return true; -} - -static bool removeVertex(rcContext* ctx, rcPolyMesh& mesh, const unsigned short rem, const int maxTris) -{ - const int nvp = mesh.nvp; - - // Count number of polygons to remove. - int numRemovedVerts = 0; - for (int i = 0; i < mesh.npolys; ++i) - { - unsigned short* p = &mesh.polys[i*nvp*2]; - const int nv = countPolyVerts(p, nvp); - for (int j = 0; j < nv; ++j) - { - if (p[j] == rem) - numRemovedVerts++; - } - } - - int nedges = 0; - rcScopedDelete edges = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp*4, RC_ALLOC_TEMP); - if (!edges) - { - ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'edges' (%d).", numRemovedVerts*nvp*4); - return false; - } - - int nhole = 0; - rcScopedDelete hole = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); - if (!hole) - { - ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hole' (%d).", numRemovedVerts*nvp); - return false; - } - - int nhreg = 0; - rcScopedDelete hreg = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); - if (!hreg) - { - ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'hreg' (%d).", numRemovedVerts*nvp); - return false; - } - - int nharea = 0; - rcScopedDelete harea = (int*)rcAlloc(sizeof(int)*numRemovedVerts*nvp, RC_ALLOC_TEMP); - if (!harea) - { - ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'harea' (%d).", numRemovedVerts*nvp); - return false; - } - - for (int i = 0; i < mesh.npolys; ++i) - { - unsigned short* p = &mesh.polys[i*nvp*2]; - const int nv = countPolyVerts(p, nvp); - bool hasRem = false; - for (int j = 0; j < nv; ++j) - if (p[j] == rem) hasRem = true; - if (hasRem) - { - // Collect edges which does not touch the removed vertex. - for (int j = 0, k = nv-1; j < nv; k = j++) - { - if (p[j] != rem && p[k] != rem) - { - int* e = &edges[nedges*4]; - e[0] = p[k]; - e[1] = p[j]; - e[2] = mesh.regs[i]; - e[3] = mesh.areas[i]; - nedges++; - } - } - // Remove the polygon. - unsigned short* p2 = &mesh.polys[(mesh.npolys-1)*nvp*2]; - memcpy(p,p2,sizeof(unsigned short)*nvp); - memset(p+nvp,0xff,sizeof(unsigned short)*nvp); - mesh.regs[i] = mesh.regs[mesh.npolys-1]; - mesh.areas[i] = mesh.areas[mesh.npolys-1]; - mesh.npolys--; - --i; - } - } - - // Remove vertex. - for (int i = (int)rem; i < mesh.nverts; ++i) - { - mesh.verts[i*3+0] = mesh.verts[(i+1)*3+0]; - mesh.verts[i*3+1] = mesh.verts[(i+1)*3+1]; - mesh.verts[i*3+2] = mesh.verts[(i+1)*3+2]; - } - mesh.nverts--; - - // Adjust indices to match the removed vertex layout. - for (int i = 0; i < mesh.npolys; ++i) - { - unsigned short* p = &mesh.polys[i*nvp*2]; - const int nv = countPolyVerts(p, nvp); - for (int j = 0; j < nv; ++j) - if (p[j] > rem) p[j]--; - } - for (int i = 0; i < nedges; ++i) - { - if (edges[i*4+0] > rem) edges[i*4+0]--; - if (edges[i*4+1] > rem) edges[i*4+1]--; - } - - if (nedges == 0) - return true; - - // Start with one vertex, keep appending connected - // segments to the start and end of the hole. - pushBack(edges[0], hole, nhole); - pushBack(edges[2], hreg, nhreg); - pushBack(edges[3], harea, nharea); - - while (nedges) - { - bool match = false; - - for (int i = 0; i < nedges; ++i) - { - const int ea = edges[i*4+0]; - const int eb = edges[i*4+1]; - const int r = edges[i*4+2]; - const int a = edges[i*4+3]; - bool add = false; - if (hole[0] == eb) - { - // The segment matches the beginning of the hole boundary. - pushFront(ea, hole, nhole); - pushFront(r, hreg, nhreg); - pushFront(a, harea, nharea); - add = true; - } - else if (hole[nhole-1] == ea) - { - // The segment matches the end of the hole boundary. - pushBack(eb, hole, nhole); - pushBack(r, hreg, nhreg); - pushBack(a, harea, nharea); - add = true; - } - if (add) - { - // The edge segment was added, remove it. - edges[i*4+0] = edges[(nedges-1)*4+0]; - edges[i*4+1] = edges[(nedges-1)*4+1]; - edges[i*4+2] = edges[(nedges-1)*4+2]; - edges[i*4+3] = edges[(nedges-1)*4+3]; - --nedges; - match = true; - --i; - } - } - - if (!match) - break; - } - - rcScopedDelete tris = (int*)rcAlloc(sizeof(int)*nhole*3, RC_ALLOC_TEMP); - if (!tris) - { - ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tris' (%d).", nhole*3); - return false; - } - - rcScopedDelete tverts = (int*)rcAlloc(sizeof(int)*nhole*4, RC_ALLOC_TEMP); - if (!tverts) - { - ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'tverts' (%d).", nhole*4); - return false; - } - - rcScopedDelete thole = (int*)rcAlloc(sizeof(int)*nhole, RC_ALLOC_TEMP); - if (!tverts) - { - ctx->log(RC_LOG_WARNING, "removeVertex: Out of memory 'thole' (%d).", nhole); - return false; - } - - // Generate temp vertex array for triangulation. - for (int i = 0; i < nhole; ++i) - { - const int pi = hole[i]; - tverts[i*4+0] = mesh.verts[pi*3+0]; - tverts[i*4+1] = mesh.verts[pi*3+1]; - tverts[i*4+2] = mesh.verts[pi*3+2]; - tverts[i*4+3] = 0; - thole[i] = i; - } - - // Triangulate the hole. - int ntris = triangulate(nhole, &tverts[0], &thole[0], tris); - if (ntris < 0) - { - ntris = -ntris; - ctx->log(RC_LOG_WARNING, "removeVertex: triangulate() returned bad results."); - } - - // Merge the hole triangles back to polygons. - rcScopedDelete polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*(ntris+1)*nvp, RC_ALLOC_TEMP); - if (!polys) - { - ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'polys' (%d).", (ntris+1)*nvp); - return false; - } - rcScopedDelete pregs = (unsigned short*)rcAlloc(sizeof(unsigned short)*ntris, RC_ALLOC_TEMP); - if (!pregs) - { - ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pregs' (%d).", ntris); - return false; - } - rcScopedDelete pareas = (unsigned char*)rcAlloc(sizeof(unsigned char)*ntris, RC_ALLOC_TEMP); - if (!pregs) - { - ctx->log(RC_LOG_ERROR, "removeVertex: Out of memory 'pareas' (%d).", ntris); - return false; - } - - unsigned short* tmpPoly = &polys[ntris*nvp]; - - // Build initial polygons. - int npolys = 0; - memset(polys, 0xff, ntris*nvp*sizeof(unsigned short)); - for (int j = 0; j < ntris; ++j) - { - int* t = &tris[j*3]; - if (t[0] != t[1] && t[0] != t[2] && t[1] != t[2]) - { - polys[npolys*nvp+0] = (unsigned short)hole[t[0]]; - polys[npolys*nvp+1] = (unsigned short)hole[t[1]]; - polys[npolys*nvp+2] = (unsigned short)hole[t[2]]; - pregs[npolys] = (unsigned short)hreg[t[0]]; - pareas[npolys] = (unsigned char)harea[t[0]]; - npolys++; - } - } - if (!npolys) - return true; - - // Merge polygons. - if (nvp > 3) - { - for (;;) - { - // Find best polygons to merge. - int bestMergeVal = 0; - int bestPa = 0, bestPb = 0, bestEa = 0, bestEb = 0; - - for (int j = 0; j < npolys-1; ++j) - { - unsigned short* pj = &polys[j*nvp]; - for (int k = j+1; k < npolys; ++k) - { - unsigned short* pk = &polys[k*nvp]; - int ea, eb; - int v = getPolyMergeValue(pj, pk, mesh.verts, ea, eb, nvp); - if (v > bestMergeVal) - { - bestMergeVal = v; - bestPa = j; - bestPb = k; - bestEa = ea; - bestEb = eb; - } - } - } - - if (bestMergeVal > 0) - { - // Found best, merge. - unsigned short* pa = &polys[bestPa*nvp]; - unsigned short* pb = &polys[bestPb*nvp]; - mergePolys(pa, pb, bestEa, bestEb, tmpPoly, nvp); - memcpy(pb, &polys[(npolys-1)*nvp], sizeof(unsigned short)*nvp); - pregs[bestPb] = pregs[npolys-1]; - pareas[bestPb] = pareas[npolys-1]; - npolys--; - } - else - { - // Could not merge any polygons, stop. - break; - } - } - } - - // Store polygons. - for (int i = 0; i < npolys; ++i) - { - if (mesh.npolys >= maxTris) break; - unsigned short* p = &mesh.polys[mesh.npolys*nvp*2]; - memset(p,0xff,sizeof(unsigned short)*nvp*2); - for (int j = 0; j < nvp; ++j) - p[j] = polys[i*nvp+j]; - mesh.regs[mesh.npolys] = pregs[i]; - mesh.areas[mesh.npolys] = pareas[i]; - mesh.npolys++; - if (mesh.npolys > maxTris) - { - ctx->log(RC_LOG_ERROR, "removeVertex: Too many polygons %d (max:%d).", mesh.npolys, maxTris); - return false; - } - } - - return true; -} - -/// @par -/// -/// @note If the mesh data is to be used to construct a Detour navigation mesh, then the upper -/// limit must be retricted to <= #DT_VERTS_PER_POLYGON. -/// -/// @see rcAllocPolyMesh, rcContourSet, rcPolyMesh, rcConfig -bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_BUILD_POLYMESH); - - rcVcopy(mesh.bmin, cset.bmin); - rcVcopy(mesh.bmax, cset.bmax); - mesh.cs = cset.cs; - mesh.ch = cset.ch; - mesh.borderSize = cset.borderSize; - - int maxVertices = 0; - int maxTris = 0; - int maxVertsPerCont = 0; - for (int i = 0; i < cset.nconts; ++i) - { - // Skip null contours. - if (cset.conts[i].nverts < 3) continue; - maxVertices += cset.conts[i].nverts; - maxTris += cset.conts[i].nverts - 2; - maxVertsPerCont = rcMax(maxVertsPerCont, cset.conts[i].nverts); - } - - if (maxVertices >= 0xfffe) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Too many vertices %d.", maxVertices); - return false; - } - - rcScopedDelete vflags = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxVertices, RC_ALLOC_TEMP); - if (!vflags) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'vflags' (%d).", maxVertices); - return false; - } - memset(vflags, 0, maxVertices); - - mesh.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxVertices*3, RC_ALLOC_PERM); - if (!mesh.verts) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.verts' (%d).", maxVertices); - return false; - } - mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris*nvp*2, RC_ALLOC_PERM); - if (!mesh.polys) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.polys' (%d).", maxTris*nvp*2); - return false; - } - mesh.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxTris, RC_ALLOC_PERM); - if (!mesh.regs) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.regs' (%d).", maxTris); - return false; - } - mesh.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxTris, RC_ALLOC_PERM); - if (!mesh.areas) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.areas' (%d).", maxTris); - return false; - } - - mesh.nverts = 0; - mesh.npolys = 0; - mesh.nvp = nvp; - mesh.maxpolys = maxTris; - - memset(mesh.verts, 0, sizeof(unsigned short)*maxVertices*3); - memset(mesh.polys, 0xff, sizeof(unsigned short)*maxTris*nvp*2); - memset(mesh.regs, 0, sizeof(unsigned short)*maxTris); - memset(mesh.areas, 0, sizeof(unsigned char)*maxTris); - - rcScopedDelete nextVert = (int*)rcAlloc(sizeof(int)*maxVertices, RC_ALLOC_TEMP); - if (!nextVert) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'nextVert' (%d).", maxVertices); - return false; - } - memset(nextVert, 0, sizeof(int)*maxVertices); - - rcScopedDelete firstVert = (int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP); - if (!firstVert) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); - return false; - } - for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i) - firstVert[i] = -1; - - rcScopedDelete indices = (int*)rcAlloc(sizeof(int)*maxVertsPerCont, RC_ALLOC_TEMP); - if (!indices) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'indices' (%d).", maxVertsPerCont); - return false; - } - rcScopedDelete tris = (int*)rcAlloc(sizeof(int)*maxVertsPerCont*3, RC_ALLOC_TEMP); - if (!tris) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'tris' (%d).", maxVertsPerCont*3); - return false; - } - rcScopedDelete polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*(maxVertsPerCont+1)*nvp, RC_ALLOC_TEMP); - if (!polys) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'polys' (%d).", maxVertsPerCont*nvp); - return false; - } - unsigned short* tmpPoly = &polys[maxVertsPerCont*nvp]; - - for (int i = 0; i < cset.nconts; ++i) - { - rcContour& cont = cset.conts[i]; - - // Skip null contours. - if (cont.nverts < 3) - continue; - - // Triangulate contour - for (int j = 0; j < cont.nverts; ++j) - indices[j] = j; - - int ntris = triangulate(cont.nverts, cont.verts, &indices[0], &tris[0]); - if (ntris <= 0) - { - // Bad triangulation, should not happen. -/* printf("\tconst float bmin[3] = {%ff,%ff,%ff};\n", cset.bmin[0], cset.bmin[1], cset.bmin[2]); - printf("\tconst float cs = %ff;\n", cset.cs); - printf("\tconst float ch = %ff;\n", cset.ch); - printf("\tconst int verts[] = {\n"); - for (int k = 0; k < cont.nverts; ++k) - { - const int* v = &cont.verts[k*4]; - printf("\t\t%d,%d,%d,%d,\n", v[0], v[1], v[2], v[3]); - } - printf("\t};\n\tconst int nverts = sizeof(verts)/(sizeof(int)*4);\n");*/ - ctx->log(RC_LOG_WARNING, "rcBuildPolyMesh: Bad triangulation Contour %d.", i); - ntris = -ntris; - } - - // Add and merge vertices. - for (int j = 0; j < cont.nverts; ++j) - { - const int* v = &cont.verts[j*4]; - indices[j] = addVertex((unsigned short)v[0], (unsigned short)v[1], (unsigned short)v[2], - mesh.verts, firstVert, nextVert, mesh.nverts); - if (v[3] & RC_BORDER_VERTEX) - { - // This vertex should be removed. - vflags[indices[j]] = 1; - } - } - - // Build initial polygons. - int npolys = 0; - memset(polys, 0xff, maxVertsPerCont*nvp*sizeof(unsigned short)); - for (int j = 0; j < ntris; ++j) - { - int* t = &tris[j*3]; - if (t[0] != t[1] && t[0] != t[2] && t[1] != t[2]) - { - polys[npolys*nvp+0] = (unsigned short)indices[t[0]]; - polys[npolys*nvp+1] = (unsigned short)indices[t[1]]; - polys[npolys*nvp+2] = (unsigned short)indices[t[2]]; - npolys++; - } - } - if (!npolys) - continue; - - // Merge polygons. - if (nvp > 3) - { - for(;;) - { - // Find best polygons to merge. - int bestMergeVal = 0; - int bestPa = 0, bestPb = 0, bestEa = 0, bestEb = 0; - - for (int j = 0; j < npolys-1; ++j) - { - unsigned short* pj = &polys[j*nvp]; - for (int k = j+1; k < npolys; ++k) - { - unsigned short* pk = &polys[k*nvp]; - int ea, eb; - int v = getPolyMergeValue(pj, pk, mesh.verts, ea, eb, nvp); - if (v > bestMergeVal) - { - bestMergeVal = v; - bestPa = j; - bestPb = k; - bestEa = ea; - bestEb = eb; - } - } - } - - if (bestMergeVal > 0) - { - // Found best, merge. - unsigned short* pa = &polys[bestPa*nvp]; - unsigned short* pb = &polys[bestPb*nvp]; - mergePolys(pa, pb, bestEa, bestEb, tmpPoly, nvp); - memcpy(pb, &polys[(npolys-1)*nvp], sizeof(unsigned short)*nvp); - npolys--; - } - else - { - // Could not merge any polygons, stop. - break; - } - } - } - - // Store polygons. - for (int j = 0; j < npolys; ++j) - { - unsigned short* p = &mesh.polys[mesh.npolys*nvp*2]; - unsigned short* q = &polys[j*nvp]; - for (int k = 0; k < nvp; ++k) - p[k] = q[k]; - mesh.regs[mesh.npolys] = cont.reg; - mesh.areas[mesh.npolys] = cont.area; - mesh.npolys++; - if (mesh.npolys > maxTris) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Too many polygons %d (max:%d).", mesh.npolys, maxTris); - return false; - } - } - } - - - // Remove edge vertices. - for (int i = 0; i < mesh.nverts; ++i) - { - if (vflags[i]) - { - if (!canRemoveVertex(ctx, mesh, (unsigned short)i)) - continue; - if (!removeVertex(ctx, mesh, (unsigned short)i, maxTris)) - { - // Failed to remove vertex - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Failed to remove edge vertex %d.", i); - return false; - } - // Remove vertex - // Note: mesh.nverts is already decremented inside removeVertex()! - // Fixup vertex flags - for (int j = i; j < mesh.nverts; ++j) - vflags[j] = vflags[j+1]; - --i; - } - } - - // Calculate adjacency. - if (!buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, nvp)) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Adjacency failed."); - return false; - } - - // Find portal edges - if (mesh.borderSize > 0) - { - const int w = cset.width; - const int h = cset.height; - for (int i = 0; i < mesh.npolys; ++i) - { - unsigned short* p = &mesh.polys[i*2*nvp]; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == RC_MESH_NULL_IDX) break; - // Skip connected edges. - if (p[nvp+j] != RC_MESH_NULL_IDX) - continue; - int nj = j+1; - if (nj >= nvp || p[nj] == RC_MESH_NULL_IDX) nj = 0; - const unsigned short* va = &mesh.verts[p[j]*3]; - const unsigned short* vb = &mesh.verts[p[nj]*3]; - - if ((int)va[0] == 0 && (int)vb[0] == 0) - p[nvp+j] = 0x8000 | 0; - else if ((int)va[2] == h && (int)vb[2] == h) - p[nvp+j] = 0x8000 | 1; - else if ((int)va[0] == w && (int)vb[0] == w) - p[nvp+j] = 0x8000 | 2; - else if ((int)va[2] == 0 && (int)vb[2] == 0) - p[nvp+j] = 0x8000 | 3; - } - } - } - - // Just allocate the mesh flags array. The user is resposible to fill it. - mesh.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*mesh.npolys, RC_ALLOC_PERM); - if (!mesh.flags) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: Out of memory 'mesh.flags' (%d).", mesh.npolys); - return false; - } - memset(mesh.flags, 0, sizeof(unsigned short) * mesh.npolys); - - if (mesh.nverts > 0xffff) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff); - } - if (mesh.npolys > 0xffff) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMesh: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff); - } - - ctx->stopTimer(RC_TIMER_BUILD_POLYMESH); - - return true; -} - -/// @see rcAllocPolyMesh, rcPolyMesh -bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh) -{ - rcAssert(ctx); - - if (!nmeshes || !meshes) - return true; - - ctx->startTimer(RC_TIMER_MERGE_POLYMESH); - - mesh.nvp = meshes[0]->nvp; - mesh.cs = meshes[0]->cs; - mesh.ch = meshes[0]->ch; - rcVcopy(mesh.bmin, meshes[0]->bmin); - rcVcopy(mesh.bmax, meshes[0]->bmax); - - int maxVerts = 0; - int maxPolys = 0; - int maxVertsPerMesh = 0; - for (int i = 0; i < nmeshes; ++i) - { - rcVmin(mesh.bmin, meshes[i]->bmin); - rcVmax(mesh.bmax, meshes[i]->bmax); - maxVertsPerMesh = rcMax(maxVertsPerMesh, meshes[i]->nverts); - maxVerts += meshes[i]->nverts; - maxPolys += meshes[i]->npolys; - } - - mesh.nverts = 0; - mesh.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxVerts*3, RC_ALLOC_PERM); - if (!mesh.verts) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.verts' (%d).", maxVerts*3); - return false; - } - - mesh.npolys = 0; - mesh.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxPolys*2*mesh.nvp, RC_ALLOC_PERM); - if (!mesh.polys) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.polys' (%d).", maxPolys*2*mesh.nvp); - return false; - } - memset(mesh.polys, 0xff, sizeof(unsigned short)*maxPolys*2*mesh.nvp); - - mesh.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxPolys, RC_ALLOC_PERM); - if (!mesh.regs) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.regs' (%d).", maxPolys); - return false; - } - memset(mesh.regs, 0, sizeof(unsigned short)*maxPolys); - - mesh.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxPolys, RC_ALLOC_PERM); - if (!mesh.areas) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.areas' (%d).", maxPolys); - return false; - } - memset(mesh.areas, 0, sizeof(unsigned char)*maxPolys); - - mesh.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxPolys, RC_ALLOC_PERM); - if (!mesh.flags) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'mesh.flags' (%d).", maxPolys); - return false; - } - memset(mesh.flags, 0, sizeof(unsigned short)*maxPolys); - - rcScopedDelete nextVert = (int*)rcAlloc(sizeof(int)*maxVerts, RC_ALLOC_TEMP); - if (!nextVert) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'nextVert' (%d).", maxVerts); - return false; - } - memset(nextVert, 0, sizeof(int)*maxVerts); - - rcScopedDelete firstVert = (int*)rcAlloc(sizeof(int)*VERTEX_BUCKET_COUNT, RC_ALLOC_TEMP); - if (!firstVert) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'firstVert' (%d).", VERTEX_BUCKET_COUNT); - return false; - } - for (int i = 0; i < VERTEX_BUCKET_COUNT; ++i) - firstVert[i] = -1; - - rcScopedDelete vremap = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxVertsPerMesh, RC_ALLOC_PERM); - if (!vremap) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Out of memory 'vremap' (%d).", maxVertsPerMesh); - return false; - } - memset(vremap, 0, sizeof(unsigned short)*maxVertsPerMesh); - - for (int i = 0; i < nmeshes; ++i) - { - const rcPolyMesh* pmesh = meshes[i]; - - const unsigned short ox = (unsigned short)floorf((pmesh->bmin[0]-mesh.bmin[0])/mesh.cs+0.5f); - const unsigned short oz = (unsigned short)floorf((pmesh->bmin[2]-mesh.bmin[2])/mesh.cs+0.5f); - - for (int j = 0; j < pmesh->nverts; ++j) - { - unsigned short* v = &pmesh->verts[j*3]; - vremap[j] = addVertex(v[0]+ox, v[1], v[2]+oz, - mesh.verts, firstVert, nextVert, mesh.nverts); - } - - for (int j = 0; j < pmesh->npolys; ++j) - { - unsigned short* tgt = &mesh.polys[mesh.npolys*2*mesh.nvp]; - unsigned short* src = &pmesh->polys[j*2*mesh.nvp]; - mesh.regs[mesh.npolys] = pmesh->regs[j]; - mesh.areas[mesh.npolys] = pmesh->areas[j]; - mesh.flags[mesh.npolys] = pmesh->flags[j]; - mesh.npolys++; - for (int k = 0; k < mesh.nvp; ++k) - { - if (src[k] == RC_MESH_NULL_IDX) break; - tgt[k] = vremap[src[k]]; - } - } - } - - // Calculate adjacency. - if (!buildMeshAdjacency(mesh.polys, mesh.npolys, mesh.nverts, mesh.nvp)) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: Adjacency failed."); - return false; - } - - if (mesh.nverts > 0xffff) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many vertices %d (max %d). Data can be corrupted.", mesh.nverts, 0xffff); - } - if (mesh.npolys > 0xffff) - { - ctx->log(RC_LOG_ERROR, "rcMergePolyMeshes: The resulting mesh has too many polygons %d (max %d). Data can be corrupted.", mesh.npolys, 0xffff); - } - - ctx->stopTimer(RC_TIMER_MERGE_POLYMESH); - - return true; -} - -bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst) -{ - rcAssert(ctx); - - // Destination must be empty. - rcAssert(dst.verts == 0); - rcAssert(dst.polys == 0); - rcAssert(dst.regs == 0); - rcAssert(dst.areas == 0); - rcAssert(dst.flags == 0); - - dst.nverts = src.nverts; - dst.npolys = src.npolys; - dst.maxpolys = src.npolys; - dst.nvp = src.nvp; - rcVcopy(dst.bmin, src.bmin); - rcVcopy(dst.bmax, src.bmax); - dst.cs = src.cs; - dst.ch = src.ch; - dst.borderSize = src.borderSize; - - dst.verts = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.nverts*3, RC_ALLOC_PERM); - if (!dst.verts) - { - ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.verts' (%d).", src.nverts*3); - return false; - } - memcpy(dst.verts, src.verts, sizeof(unsigned short)*src.nverts*3); - - dst.polys = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys*2*src.nvp, RC_ALLOC_PERM); - if (!dst.polys) - { - ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.polys' (%d).", src.npolys*2*src.nvp); - return false; - } - memcpy(dst.polys, src.polys, sizeof(unsigned short)*src.npolys*2*src.nvp); - - dst.regs = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM); - if (!dst.regs) - { - ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.regs' (%d).", src.npolys); - return false; - } - memcpy(dst.regs, src.regs, sizeof(unsigned short)*src.npolys); - - dst.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*src.npolys, RC_ALLOC_PERM); - if (!dst.areas) - { - ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.areas' (%d).", src.npolys); - return false; - } - memcpy(dst.areas, src.areas, sizeof(unsigned char)*src.npolys); - - dst.flags = (unsigned short*)rcAlloc(sizeof(unsigned short)*src.npolys, RC_ALLOC_PERM); - if (!dst.flags) - { - ctx->log(RC_LOG_ERROR, "rcCopyPolyMesh: Out of memory 'dst.flags' (%d).", src.npolys); - return false; - } - memcpy(dst.flags, src.flags, sizeof(unsigned char)*src.npolys); - - return true; -} diff --git a/critterai/.svn/pristine/60/60d1285fe92b0f36296b1f252b8dc31b0a965ade.svn-base b/critterai/.svn/pristine/60/60d1285fe92b0f36296b1f252b8dc31b0a965ade.svn-base deleted file mode 100644 index ec82d960..00000000 --- a/critterai/.svn/pristine/60/60d1285fe92b0f36296b1f252b8dc31b0a965ade.svn-base +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// A ScriptableObject processor used to build input for a - /// build. (Editor Only) - /// - /// - /// - /// Processors are called during each step of the input build, in ascending priority. - /// - /// - /// This interface is only valid when implemented by a ScriptableObject. - /// - /// - public interface IInputBuildProcessor - : IPriorityItem - { - /// - /// The name of the processor. - /// - string Name { get; } // Don't get rid of this. It is convenient. - - /// - /// Processes the context. - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - bool ProcessInput(InputBuildContext context, InputBuildState state); - - /// - /// True if the multiple processors of the same type can be included in a build. - /// - /// - /// - /// If this property is false, then the input builder will discard duplicate processors of the - /// same type. Which duplicate is discarded is undefined. - /// - /// This restiction only effects type comparison. The input builder never accepts duplicate - /// objects. - /// - bool DuplicatesAllowed { get; } - } -} diff --git a/critterai/.svn/pristine/60/60d4a6918e6136dabf73392e498f4e82292989d8.svn-base b/critterai/.svn/pristine/60/60d4a6918e6136dabf73392e498f4e82292989d8.svn-base deleted file mode 100644 index 5cd3e5e7..00000000 --- a/critterai/.svn/pristine/60/60d4a6918e6136dabf73392e498f4e82292989d8.svn-base +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; -using org.critterai.nav; -using System.Collections.Generic; -using Math = System.Math; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Provides utility methods related to the NMGen build process. - /// - public static class NMBuild - { - /// - /// The default flag applied to polygons during the build process if the - /// is set. - /// - public const ushort DefaultFlag = 0x01; - - /// - /// The minimum permitted priority for non-system (custom) elements. - /// - public const int MinPriority = ushort.MinValue; - - /// - /// The maximum permitted priority for non-system (custom) elements. - /// - public const int MaxPriority = ushort.MaxValue; - - /// - /// The standard default priority for priority elements. - /// - public const int DefaultPriority = 100; - - /// - /// Clamps the value to the allowed non-system (custom) priority range. - /// - /// The value to clamp. - /// - /// The clamped value. - /// ( <= clampedValue <= - /// - public static int ClampPriority(int value) - { - return Math.Max(MinPriority, Math.Min(MaxPriority, value)); - } - - /// - /// Creates a standard object from the provided - /// parameters. - /// - /// - /// - /// Errors will be logged to the build context. - /// - /// - /// The x-index of the tile. - /// The z-index of the tile. - /// The polygon mesh data. - /// The detail mesh data. (Optional) - /// The off-mesh connections. (Null allowed.) - /// True if bounding volumes should be generated. - /// The build context. - /// The tile build data, or null on error. - public static NavmeshTileBuildData GetBuildData(BuildContext context - , int tx, int tz - , PolyMeshData polyMesh, PolyMeshDetailData detailMesh - , ConnectionSet connections - , bool bvTreeEnabled) - { - if (context == null) - // Silent. - return null; - - Vector3[] verts = null; - float[] radii = null; - byte[] dirs = null; - byte[] areas = null; - ushort[] flags = null; - uint[] userIds = null; - - Vector3 bmin = polyMesh.boundsMin; - Vector3 bmax = polyMesh.boundsMax; - - int connCount = (connections == null) - ? 0 - : connections.GetConnections(bmin.x, bmin.z, bmax.x, bmax.z - , out verts, out radii, out dirs, out areas, out flags, out userIds); - - NavmeshTileBuildData result = new NavmeshTileBuildData( - polyMesh.vertCount - , polyMesh.polyCount - , polyMesh.maxVertsPerPoly - , (detailMesh == null ? 0 : detailMesh.vertCount) - , (detailMesh == null ? 0 : detailMesh.triCount) - , connCount); - - if (!result.LoadBase(tx, tz, 0, 0 - , polyMesh.boundsMin - , polyMesh.boundsMax - , polyMesh.xzCellSize - , polyMesh.yCellSize - , polyMesh.walkableHeight - , polyMesh.walkableRadius - , polyMesh.walkableStep - , bvTreeEnabled)) - { - context.LogError("Base data load failed. Bad configuration data or internal error." - , null); - return null; - } - - if (!result.LoadPolys(polyMesh.verts - , polyMesh.vertCount - , polyMesh.polys - , polyMesh.flags - , polyMesh.areas - , polyMesh.polyCount)) - { - context.LogError("Polygon load failed. Bad mesh data or internal error.", null); - return null; - } - - if (detailMesh != null) - { - if (!result.LoadDetail(detailMesh.verts - , detailMesh.vertCount - , detailMesh.tris - , detailMesh.triCount - , detailMesh.meshes - , detailMesh.meshCount)) - { - context.LogError("Detail load failed. Bad mesh data or internal error.", null); - return null; - } - } - - if (connCount > 0) - { - if (!result.LoadConns(verts, radii, dirs, areas, flags, userIds, connCount)) - { - context.LogError("Off-mesh connection load failed. Bad data or internal error." - , null); - return null; - } - } - - return result; - } - } -} diff --git a/critterai/.svn/pristine/61/6105272b54a2efd2bfbdb73a44b4cbd62cfd7da3.svn-base b/critterai/.svn/pristine/61/6105272b54a2efd2bfbdb73a44b4cbd62cfd7da3.svn-base deleted file mode 100644 index 0f6db370..00000000 --- a/critterai/.svn/pristine/61/6105272b54a2efd2bfbdb73a44b4cbd62cfd7da3.svn-base +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Filters out all MeshFilter components that reference a mesh in the list. (Editor Only) -/// -[System.Serializable] -public sealed class MeshInputFilter - : ScriptableObject, IInputBuildProcessor -{ - /// - /// The list of meshes to filter out. - /// - public List meshes = new List(); - - /// - /// The type of match to use when filtering. - /// - public MatchType matchType; - - [SerializeField] - private int mPriority = NMBuild.DefaultPriority; - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// The priority of the processor. - /// - public int Priority - { - get { return mPriority; } - set { mPriority = NMBuild.ClampPriority(value); } - } - - /// - /// Multiple processors of this type are allowed. (Always true.) - /// - public bool DuplicatesAllowed { get { return true; } } - - /// - /// Processes the context. - /// - /// - /// - /// Applied during the state. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (state != InputBuildState.FilterComponents) - return true; - - if (meshes == null) - { - context.LogError(name + " Mesh exclusion list is null. (Invalid processor state.)" - , this); - return false; - } - - if (meshes.Count == 0) - { - context.Log(name + ": Filter is inactive. No meshes configured to filter.", this); - return true; - } - - List targetFilters = context.components; - - int removed = 0; - for (int iTarget = targetFilters.Count - 1; iTarget >= 0; iTarget--) - { - if (!(targetFilters[iTarget] is MeshFilter)) - continue; - - MeshFilter filter = (MeshFilter)targetFilters[iTarget]; - - if (!filter) - continue; - - MatchPredicate p = new MatchPredicate(filter.sharedMesh, matchType, true); - - int iSource = meshes.FindIndex(p.Matches); - - if (iSource != -1) - { - targetFilters.RemoveAt(iTarget); - removed++; - } - } - - if (removed > 0) - context.Log(string.Format("{0}: Filtered out {1} components.", name, removed), this); - else - context.Log(name + ": No components filtered.", this); - - return true; - } -} diff --git a/critterai/.svn/pristine/61/615f0eab418d7f30facbe07919faf7c9c436c8ec.svn-base b/critterai/.svn/pristine/61/615f0eab418d7f30facbe07919faf7c9c436c8ec.svn-base deleted file mode 100644 index e19a1395..00000000 --- a/critterai/.svn/pristine/61/615f0eab418d7f30facbe07919faf7c9c436c8ec.svn-base +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using Math = System.Math; - -/// -/// A scene component used during an NMGen build. -/// -public abstract class NMGenComponent - : MonoBehaviour -{ - /// - /// The maximum allowed area. - /// - public const byte MaxArea = 63; - - /// - /// True if debug mode is enabled for all components. - /// - public static bool debugEnabled = false; - - /// - /// True if debug mode is enabled for the current component. - /// - [System.NonSerialized] - public bool debugEnabledLocal = false; - - /// - /// Clamps the value to a valid area. - /// - /// The value to clamp. - /// The clamped value. - public static byte ClampArea(byte value) - { - return Math.Min(MaxArea, value); - } - - /// - /// Clamps the value to a valid area. (Integer version.) - /// - /// The value to clamp. - /// The clamped value. - public static byte ClampArea(int value) - { - return (byte)Math.Min(MaxArea, Math.Max(0, value)); - } -} diff --git a/critterai/.svn/pristine/62/6290b5a93c62d1589da21a59e472ca34ff15c9ea.svn-base b/critterai/.svn/pristine/62/6290b5a93c62d1589da21a59e472ca34ff15c9ea.svn-base deleted file mode 100644 index 81d3e391..00000000 --- a/critterai/.svn/pristine/62/6290b5a93c62d1589da21a59e472ca34ff15c9ea.svn-base +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef CAI_NMG_EX_H -#define CAI_NMG_EX_H - -#include "Recast.h" - -#if _MSC_VER // TRUE for Microsoft compiler. -#define EXPORT_API __declspec(dllexport) // Required for VC++ -#else -#define EXPORT_API // Otherwise don't define. -#endif - -static const float NMG_EPSILON = 0.00001f; -static const float NMG_TOLERANCE = 0.0001f; - -// The memory was allocated externally and cannot -// be freed by this library. -static const unsigned char NMG_ALLOC_TYPE_EXTERN = 0; - -// The memory was allocated locally and can be freed locally. -static const unsigned char NMG_ALLOC_TYPE_LOCAL = 1; - -// The memory was allocated locally, but it is managed by an -// owner object. It should only be freed by that object. -static const unsigned char NMG_ALLOC_TYPE_MANAGED_LOCAL = 2; - -class nmgBuildContext - : public rcContext -{ -public: - static const int MAX_MESSAGES = 1024; - static const int MESSAGE_POOL_SIZE = 65536; - - nmgBuildContext(); - virtual ~nmgBuildContext(); - - int getMessageCount() const; - const char* getMessage(const int i) const; - - int getMessagePoolLength() const; - const char* getMessagePool() const; - - bool getLogEnabled() const { return m_logEnabled; } - -protected: - virtual void doResetLog(); - virtual void doLog(const rcLogCategory category - , const char* msg - , const int len); - -private: - const char* mMessages[MAX_MESSAGES]; - int mMessageCount; - - char mTextPool[MESSAGE_POOL_SIZE]; - int mTextPoolSize; -}; - -template inline bool nmgSloppyEquals(T a, T b) -{ - return !(b < a - NMG_TOLERANCE || b > a + NMG_TOLERANCE); -}; - -#endif \ No newline at end of file diff --git a/critterai/.svn/pristine/62/62a15f8b941855147ec629299da649fba2ac551d.svn-base b/critterai/.svn/pristine/62/62a15f8b941855147ec629299da649fba2ac551d.svn-base deleted file mode 100644 index 9b89349e..00000000 --- a/critterai/.svn/pristine/62/62a15f8b941855147ec629299da649fba2ac551d.svn-base +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nav; -using org.critterai.nav.u3d; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.nmgen; -using UnityEngine; - -/// -/// A navigation mesh build. (Editor Only) -/// -/// -/// -/// This class is only meant for use with Unity editors. Its public interface is very limited. -/// -/// -[System.Serializable] -public sealed class NavmeshBuild - : ScriptableObject -{ - /* - * Design notes: - * - * Unity REEEALLY hates null serialized fields for non-unity objects. - * I've tried all sorts of workarounds for the fields that are supposed to - * be null when not in use. But Unity keeps un-nulling the fields at unexpected - * times. In most cases I just don't allow fields to be unset. For the build - * data, it has a 'valid' check build into it. - * - * It is important to the design that the input data only be cleared by - * an uncontroled editor reset or a manual reset of the build. - * The recovery state is detected by the input data going missing while - * there is build data. - * - * ScribableObjects: Can't recast a ScribableObject to an interface and test for null due - * to an oddity. If the ScribableObject is deleted while it is still assigned to a build, then - * (CastedToInterfaceVar == null) will evaluate to false for a long period of time. - * But (!ScribableObjectVar) will evaluate to true. - * - */ - - internal const int MinAllowedTileSize = 12; - - #region Serialized Fields - - // WARNING: Don't make this field read-only. It breaks serialization. - /// - /// Warning: Always check for nulls via (inputProcessors[i]) evaluation. Don't do null check. - /// - [SerializeField] - internal List inputProcessors = new List(); - - [SerializeField] - private NavmeshBuildType mBuildType = NavmeshBuildType.Standard; - - [SerializeField] - private ScriptableObject mSceneQuery; - - [SerializeField] - private ScriptableObject mTarget; - - [SerializeField] - private NMGenConfig mConfig = new NMGenConfig(); - - [SerializeField] - private Vector3 mBoundsMin; - - [SerializeField] - private Vector3 mBoundsMax; - - [SerializeField] - private TileBuildData mBuildData; - - [SerializeField] - private bool mCleanInputGeometry = true; - - [SerializeField] - private bool mIsDirty = false; // Yes, this needs to be serialized. - - #endregion - - #region Non-Serialized Fields - - // This information is lost during a Unity editor reset. - - private InputGeometry mInputGeom; - private InputBuildInfo mInputInfo; - private ProcessorSet mNMGenProcessors; - private ConnectionSet mConnections; // Off-mesh. - private TileSetDefinition mTileSet; - - #endregion - - /// - /// The state of the build. - /// - public NavmeshBuildState BuildState - { - get - { - // The test for the input processors is lazy since it may contain - // nulls due to asset deletions. Choosing performance over accuracy. - if (!mTarget || inputProcessors.Count == 0) - return NavmeshBuildState.Invalid; - - if (mNMGenProcessors == null) - { - if (mBuildData.IsValid) - return NavmeshBuildState.NeedsRecovery; - else - return NavmeshBuildState.Inactive; - } - - if (mBuildData.IsValid) - return NavmeshBuildState.Buildable; - else - return NavmeshBuildState.InputCompiled; - } - } - - internal bool AutoCleanGeometry - { - get { return mCleanInputGeometry; } - set { mCleanInputGeometry = value; } - } - - internal NavmeshBuildType BuildType - { - get { return mBuildType; } - set - { - if (value != mBuildType) - { - ResetBuild(); - - mBuildType = value; - - if (mBuildType == NavmeshBuildType.Advanced) - BuildSelector.Instance.Add(this); - else - BuildSelector.Instance.Remove(this); - - mIsDirty = true; - } - } - } - - internal bool IsDirty - { - get { return mIsDirty || mBuildData.IsDirty; } - set - { - mIsDirty = value; - mBuildData.IsDirty = value; - } - } - - internal bool HasInputData - { - get { return (mNMGenProcessors != null); } - } - - internal IInputBuildProcessor[] GetInputProcessors() - { - // May contain nulls due to asset deletions. So clean things up. - for (int i = inputProcessors.Count - 1; i >= 0; i--) - { - if (!inputProcessors[i]) - { - inputProcessors.RemoveAt(i); - mIsDirty = true; - } - } - - IInputBuildProcessor[] result = new IInputBuildProcessor[inputProcessors.Count]; - - // Assumption: The editor is properly controlling additions to the list. - for (int i = 0; i < result.Length; i++) - { - result[i] = (IInputBuildProcessor)inputProcessors[i]; - } - - return result; - } - - internal InputGeometry InputGeom { get { return mInputGeom; } } - - internal ProcessorSet NMGenProcessors { get { return mNMGenProcessors; } } - - internal ConnectionSet Connections { get { return mConnections; } } - - internal InputBuildInfo InputInfo { get { return mInputInfo; } } - - internal bool TargetHasNavmesh - { - get { return (mTarget) ? BuildTarget.HasNavmesh : false; } - } - - internal ISceneQuery SceneQuery - { - - get - { - // See design notes for reason for this test. - return mSceneQuery ? (ISceneQuery)mSceneQuery : null; - } - set - { - mSceneQuery = mSceneQuery ? mSceneQuery : null; // Clean - if (value == null || value is ScriptableObject) - { - - ScriptableObject so = (ScriptableObject)value; - so = so ? so : null; - if (mSceneQuery != so) - { - mSceneQuery = so; - mIsDirty = true; - } - } - } - } - - internal INavmeshData BuildTarget - { - - get - { - // See design notes for reason for this test. - return mTarget ? (INavmeshData)mTarget : null; - } - set - { - mTarget = mTarget ? mTarget : null; // Clean; - if (value is ScriptableObject || value == null) - { - ScriptableObject so = (ScriptableObject)value; - so = so ? so : null; - if (mTarget != so) - { - mTarget = so; - mIsDirty = true; - } - } - } - } - - internal NMGenConfig Config { get { return mConfig; } } - - internal bool HasBuildData { get { return mBuildData.IsValid; } } - - internal TileBuildData BuildData - { - get { return (mBuildData.IsValid ? mBuildData : null); } - } - - internal TileSetDefinition TileSetDefinition { get { return mTileSet; } } - - internal bool ContainsProcessor() where T : IInputBuildProcessor - { - foreach (IInputBuildProcessor processor in inputProcessors) - { - if (processor is T) - return true; - } - return false; - } - - /// - /// Resets the build to the state, clearing all - /// build data. - /// - public void ResetBuild() - { - mBuildData = new TileBuildData(); - mTileSet = null; - - mInputGeom = null; - mInputInfo = new InputBuildInfo(); - mNMGenProcessors = null; - mConnections = null; - - mBoundsMin = Vector3.zero; - mBoundsMax = Vector3.zero; - - mIsDirty = true; - } - - internal bool SetConfigFromTarget(BuildContext context) - { - if (mBuildData.IsValid) - // Can't do it while in buildable state. - return false; - - if (!CanLoadFromTarget(context, false)) - return false; - - Navmesh navmesh = BuildTarget.GetNavmesh(); - - if (navmesh == null) - { - context.LogError("Build target does not have an existing navigation mesh. (It lied.)" - , this); - return false; - } - - SetConfigFromTargetIntern(navmesh); - - return true; - } - - private void SetConfigFromTargetIntern(Navmesh navmesh) - { - NavmeshBuildInfo targetConfig = BuildTarget.BuildInfo; - NMGenParams currConfig = mConfig.GetConfig(); - - // Note: Must ensure exact match with original configuration. - // So this process is using the fields and trusting the - // original configuration to have valid values. - - currConfig.tileSize = targetConfig.tileSize; - currConfig.walkableHeight = targetConfig.walkableHeight; - currConfig.walkableRadius = targetConfig.walkableRadius; - currConfig.walkableStep = targetConfig.walkableStep; - currConfig.xzCellSize = targetConfig.xzCellSize; - currConfig.yCellSize = targetConfig.yCellSize; - currConfig.borderSize = targetConfig.borderSize; - - mBoundsMin = navmesh.GetConfig().origin; - - int maxTiles = navmesh.GetMaxTiles(); - - // Make sure the maximum bounds fits the target mesh. - // Note: Will not shrink the existing max bounds. - for (int i = 0; i < maxTiles; i++) - { - NavmeshTile tile = navmesh.GetTile(i); - - if (tile == null) - continue; - - NavmeshTileHeader tileHeader = tile.GetHeader(); - - if (tileHeader.polyCount == 0) - continue; - - mBoundsMax = Vector3.Max(mBoundsMax, tileHeader.boundsMax); - } - - mConfig.SetConfig(currConfig); - - mIsDirty = true; - } - - internal bool SetInputData(BuildContext context - , InputGeometry geometry - , InputBuildInfo info - , INMGenProcessor[] processors - , ConnectionSet connections - , bool threadSafeOnly) - { - // Remember: Never allow this method to clear the input geometry. - // Note: Don't set class fields until it is safe. - - if (geometry == null) - { - context.LogError("Set input data: Invalid parameters.", this); - return false; - } - - // Generate the processor set. - - processors = org.critterai.ArrayUtil.Compress(processors); - - List lprocessors = new List(); - if (processors != null) - lprocessors.AddRange(processors); - - NMGenBuildFlag bflags = mConfig.BuildFlags; - bool threadCheckFail = false; - - // This section makes sure we don't get duplicate processors. - // It also checks for thread-safety. - foreach (INMGenProcessor p in lprocessors) - { - if (p is FilterLedgeSpans) - bflags &= ~NMGenBuildFlag.LedgeSpansNotWalkable; - - if (p is FilterLowHeightSpans) - bflags &= ~NMGenBuildFlag.LowHeightSpansNotWalkable; - - if (p is LowObstaclesWalkable) - bflags &= ~NMGenBuildFlag.LowObstaclesWalkable; - - if (threadSafeOnly && !p.IsThreadSafe) - { - context.LogError(p.Name + " processor is not thread-safe.", this); - threadCheckFail = true; - } - } - - if (threadCheckFail) - { - context.LogError("One or more processors is not thread-safe.", this); - return false; - } - - lprocessors.AddRange(ProcessorSet.GetStandard(bflags)); - - ProcessorSet pset = ProcessorSet.Create(lprocessors.ToArray()); - - if (pset == null) - { - context.LogError("Set input data: No NMGen processors available.", this); - return false; - } - - // If necessary, re-create the tile set definition. - - Vector3 bmin; - Vector3 bmax; - - DeriveBounds(geometry.BoundsMin, geometry.BoundsMax, out bmin, out bmax); - - if (mBuildData.IsTiled) - { - - mTileSet = TileSetDefinition.Create(bmin, bmax, mConfig.GetConfig(), geometry); - - if (mTileSet == null) - { - context.LogError("Set input data: Create tile build definition: Unexpected error." - + " Invalid input data or configuration." - , this); - return false; - } - } - - // Everything is OK. Set the rest of the fields. - - mNMGenProcessors = pset; - mBoundsMin = bmin; - mBoundsMax = bmax; - mInputGeom = geometry; - mInputInfo = info; - mConnections = (connections == null ? ConnectionSet.CreateEmpty() : connections); - - mIsDirty = true; - - return true; - } - - private void DeriveBounds(Vector3 bminIn, Vector3 bmaxIn, out Vector3 bmin, out Vector3 bmax) - { - if (mBuildData.IsValid && mBuildData.IsTiled) - { - // Note: Can't change the origin of existing tile data. - bmin = mBoundsMin; - - // Extend the maximum bounds if needed. - bmax = Vector3.Max(mBoundsMax, bmaxIn); - } - else - { - bmin = bminIn; - bmax = bmaxIn; - } - } - - internal bool CanLoadFromTarget(BuildContext context, bool fullCheck) - { - INavmeshData target = BuildTarget; - - if (target == null || !target.HasNavmesh) - { - if (context != null) - context.LogError("Build target does not have an existing navigation mesh.", this); - return false; - } - - NavmeshBuildInfo targetConfig = target.BuildInfo; - - // Note: The tile size is checked since the original builder - // may have supported a tile size not supported by the the standard build. - if (targetConfig == null - || targetConfig.tileSize >= 0 && targetConfig.tileSize < MinAllowedTileSize) - { - if (context != null) - context.LogError("Unavailable or unsupported build target configuration.", this); - return false; - } - - if (!fullCheck) - return true; - - Navmesh nm = target.GetNavmesh(); - - if (nm == null) - { - if (context != null) - { - context.LogError( - "Build target does not have an existing navigation mesh. (It lied.)", this); - } - return false; - } - - NavmeshParams nmConfig = nm.GetConfig(); - - if (nmConfig.maxTiles < 2) - { - if (context != null) - context.LogError("Target navigation mesh is not tiled.", this); - return false; - } - - int tileCount = 0; - for (int i = 0; i < nmConfig.maxTiles; i++) - { - NavmeshTile tile = nm.GetTile(i); - - if (tile == null) - continue; - - NavmeshTileHeader header = tile.GetHeader(); - - if (header.polyCount == 0) - continue; - - tileCount++; - - if (header.layer > 0) - { - if (context != null) - { - context.LogError( - "Target navigation mesh contains layered tiles. (Not supported.)", this); - } - return false; - } - } - - if (tileCount < 2) - { - if (context != null) - { - context.LogError( - "Target navigation mesh is either not tiled or has no tiles loaded.", this); - } - return false; - } - - return true; - } - - internal void DiscardBuildData() - { - mBuildData.Resize(0, 0); - mTileSet = null; - - // Note: The user may have recompiled the input geometry during the build, resulting in a - // significant change in the bounds. So need to derive new bounds in order. - // (This effectively released the bounds lock.) - DeriveBounds(mInputGeom.BoundsMin, mInputGeom.BoundsMax, out mBoundsMin, out mBoundsMax); - - } - - internal bool InitializeBuild(BuildContext context, bool fromTarget) - { - Navmesh navmesh = null; - - if (fromTarget) - { - if (!CanLoadFromTarget(context, true)) - return false; - - navmesh = BuildTarget.GetNavmesh(); - - SetConfigFromTargetIntern(navmesh); - } - - mIsDirty = true; - - // Note: If loading from the target, the tile size was already validated. - // So it won't trigger this adjustment. - if (mConfig.TileSize != 0 - && mConfig.TileSize < MinAllowedTileSize) - { - string msg = string.Format("Tile size too small. Reverting tile size from" - + " {0} to 0 (non-tiled). Minimum tile size is {1}" - , mConfig.TileSize, MinAllowedTileSize); - - context.LogWarning(msg, this); - - mConfig.TileSize = 0; - } - - if (mConfig.TileSize == 0) - mBuildData.Resize(1, 1); - else - { - // Need to check to see if the the build is truly tiled. - - int w; - int d = 0; - - if (navmesh == null) - { - NMGen.DeriveSizeOfTileGrid(mBoundsMin, mBoundsMax - , mConfig.XZCellSize, mConfig.TileSize - , out w, out d); - } - else - // Existing navmesh will always be tiled. - w = 2; - - if (w > 1 || d > 1) - { - mTileSet = TileSetDefinition.Create(mBoundsMin, mBoundsMax - , mConfig.GetConfig() - , mInputGeom); - - if (mTileSet == null) - { - context.LogError("Create tile build definition: Unexpected error." - + " Invalid input data or configuration." - , this); - - return false; - } - - mBuildData.Resize(mTileSet.Width, mTileSet.Depth); - } - else - // Not really tiled. - mBuildData.Resize(1, 1); - } - - if (navmesh != null) - { - // Need to load the tiles from existing navmesh. - - NavmeshTileExtract[] tiles; - NavmeshParams meshConfig; - - NavStatus status = Navmesh.ExtractTileData(navmesh.GetSerializedMesh() - , out tiles - , out meshConfig); - - if ((status & NavStatus.Failure) != 0) - { - context.LogError("Could not extract the tile data from the target's" - + " navigation mesh. (Can't initialize from build target.)" - , this); - return false; - } - - foreach (NavmeshTileExtract tile in tiles) - { - int polyCount = tile.header.polyCount; - - if (polyCount == 0) - continue; - - int tx = tile.header.tileX; - int tz = tile.header.tileZ; - - if (tx >= mBuildData.Width || tz >= mBuildData.Depth) - { - // Shouldn't happen. Probably indicates in internal error - // of some type. - - string msg = string.Format("The existing navigation mesh" - + " contains a tile outside the expected range. Ignoring" - + " the tile. (Tile: [{0},{1}])" - , tx, tz); - - context.LogWarning(msg, this); - - continue; - } - - mBuildData.SetAsBaked(tx, tz, tile.data, polyCount); - } - } - - // Note: Dirty state was set earlier in the code. - - return true; - } - - void OnEnable() - { - if (mBuildData == null || !mBuildData.IsValid) - // Don't trust Unity de-serialization of null objects. - mBuildData = new TileBuildData(); - - CleanBuild(); - - if (mBuildType == NavmeshBuildType.Advanced) - BuildSelector.Instance.Add(this); - } - - void OnDisable() - { - BuildSelector.Instance.Remove(this); - } - - internal void CleanBuild() - { - // OnDebugRender = null; - - if (BuildState == NavmeshBuildState.Invalid) - { - // Possible naughty user. Silent reset. - ResetBuild(); - - } - else if (mBuildData.IsValid) - { - if (mBuildData.BakeableCount() == 0) - // Nothing to bake. Just do a silent reset. - ResetBuild(); - } - } -} diff --git a/critterai/.svn/pristine/63/6310fde05cab563bebd29c6cc6a7ba3029e23a94.svn-base b/critterai/.svn/pristine/63/6310fde05cab563bebd29c6cc6a7ba3029e23a94.svn-base deleted file mode 100644 index 55abf430..00000000 --- a/critterai/.svn/pristine/63/6310fde05cab563bebd29c6cc6a7ba3029e23a94.svn-base +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Represents the solid (wall) polygon segments in the vicinity of a reference point. - /// - /// - /// - /// Instances of this class are required by . - /// - /// - /// This class is used as an interop buffer. Behavior is undefined if the size of the array - /// fields are changed after construction. - /// - /// - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class LocalBoundaryData - { - /* - * Design note: - * - * Implemented as a class to permit use as a buffer. - * - */ - - /// - /// The maximum allowed segments. - /// - /// Used to size the buffer. - public const int MaxSegments = 8; - - /// - /// The reference point for which the boundary data was compiled. - /// - public Vector3 center; - - /// - /// The solid navigation mesh polygon segments in the vicinity of . - /// [(vertA, vertB) * ] - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxSegments * 2)] - public Vector3[] segments = new Vector3[MaxSegments * 2]; - - /// - /// The number of segments in the field. - /// - public int segmentCount = 0; - - /// - /// Creates an instance with properly sized buffers. - /// - public LocalBoundaryData() { } - } -} diff --git a/critterai/.svn/pristine/63/636ae3cf640b1f4a0720370d28b1cfe46ee1ffba.svn-base b/critterai/.svn/pristine/63/636ae3cf640b1f4a0720370d28b1cfe46ee1ffba.svn-base deleted file mode 100644 index 598758f5..00000000 --- a/critterai/.svn/pristine/63/636ae3cf640b1f4a0720370d28b1cfe46ee1ffba.svn-base +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmgen; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Assigns areas to components based on the component's tag. (Editor Only) -/// -/// -/// -/// Will not override the assignment of . -/// -/// -[System.Serializable] -public sealed class TagAreaDef - : ScriptableObject, IInputBuildProcessor -{ - /// - /// True if components whose parents have one of the tags should be assigned the area. - /// - public bool recursive; - - /// - /// Tags to associate with areas. - /// - public List tags; - - /// - /// The area associated with each tag. - /// - public List areas; - - [SerializeField] - private int mPriority = NMBuild.DefaultPriority; - - /// - /// The priority of the processor. - /// - public int Priority { get { return mPriority; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// Sets the priority. - /// - /// The new priority. - public void SetPriority(int value) - { - mPriority = NMBuild.ClampPriority(value); - } - - /// - /// Duplicates allowed. (Always true.) - /// - public bool DuplicatesAllowed { get { return true; } } - - /// - /// Processes the context. - /// - /// - /// - /// Applied during the state. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (state != InputBuildState.ApplyAreaModifiers) - return true; - - context.info.areaModifierCount++; - - if (tags == null || areas == null || tags.Count != areas.Count) - { - context.Log("Mesh/Area size error. (Invalid processor state.)", this); - return false; - } - - if (tags.Count == 0) - { - context.Log("No action taken. No tags defined.", this); - return true; - } - - List targetItems = context.components; - List targetAreas = context.areas; - - int applied = 0; - for (int iTarget = 0; iTarget < targetItems.Count; iTarget++) - { - Component targetItem = targetItems[iTarget]; - - if (targetItem == null || targetAreas[iTarget] == NMGen.NullArea) - // Don't override null area. - continue; - - int iSource = tags.IndexOf(targetItem.tag); - - if (iSource != -1) - { - targetAreas[iTarget] = areas[iSource]; - applied++; - continue; - } - - if (recursive) - { - // Need to see if the tag is on any parent. - Transform parent = targetItem.transform.parent; - - while (parent != null) - { - iSource = tags.IndexOf(parent.tag); - - if (iSource != -1) - { - // One of the tags is on this item. - targetAreas[iTarget] = areas[iSource]; - applied++; - break; - } - parent = parent.parent; - } - } - } - - context.Log(string.Format("{1}: Applied area(s) to {0} components", applied, name), this); - - return true; - } -} diff --git a/critterai/.svn/pristine/64/64b205523c22a5d21199821af7912a86b825b8f8.svn-base b/critterai/.svn/pristine/64/64b205523c22a5d21199821af7912a86b825b8f8.svn-base deleted file mode 100644 index 7762f1e3..00000000 --- a/critterai/.svn/pristine/64/64b205523c22a5d21199821af7912a86b825b8f8.svn-base +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - The crowd manager is the big beast of the navigation components. It not only handles a lot of the path management for you, but also - local steering and dynamic avoidance between navigation clients. I.e. It can keep your agents from running into each other. - - - - Core Class: CrowdManager - - - - The NavmeshQuery and PathCorridor classes provide perfectly good, easy to use path planning features. But in - the end they only give you points that your navigation client should be moving toward. When it comes to deciding things like client velocity - and steering to avoid other clients, that is up to you to implement. Unless, of course, you decide to use the crowd manager. - - - - Basically, you add an navigation client (agent) to the crowd manager, providing various configuration settings such as - maximum speed and acceleration. You also provide a local target to more toward. The crowd manager then provides, with every update, the new - agent position and velocity for the frame. The movement will be constrained to the navigation mesh, and steering will be applied to ensure - agents managed by the crowd manager do not collide with each other. - - - - This is very powerful feature set. But it comes with limitations. - - - - The biggest limitation is that you must give control of the agent's position and velocity completely over to the crowd manager. You can - update things like maximum speed and acceleration. But in order for the crowd manager to do its thing, it can't allow you to constantly be - giving it overrides to position and velocity. So you give up direct control of the agent's movement. It belongs to the crowd manager. - - - - The second biggest limitation revolves around the fact that the crowd manager deals with local planning. The agent's target should never - be more than 256 polygons aways from its current position. If it is, you risk your agent failing to reach its target. So you may - still need to do long distance planning and provide the crowd manager with intermediate targets. - - - - Other significant limitations: - - - - All agents using the crowd manager use the same NavmeshQueryFilter. - Crowd management is relatively expensive. The maximum agents under crowd management at any one time is - around 20. - - - - The CAINavExplorerDownload includes a Crowd Manager Demo that lets you see the manager in action. - - - - - - - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshQueryFilter - T:org.critterai.nav.CrowdManager - T:org.critterai.nav.CrowdAgent - T:org.critterai.nav.CrowdAgentParams - T:org.critterai.nav.CrowdAvoidanceParams - - - - - - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/65/65188da301468276310c3604df105deba095adde.svn-base b/critterai/.svn/pristine/65/65188da301468276310c3604df105deba095adde.svn-base deleted file mode 100644 index a837694c..00000000 Binary files a/critterai/.svn/pristine/65/65188da301468276310c3604df105deba095adde.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/67/67536fbfa836c3aa95d27bed492890bdb2ace00e.svn-base b/critterai/.svn/pristine/67/67536fbfa836c3aa95d27bed492890bdb2ace00e.svn-base deleted file mode 100644 index 5f84d5e6..00000000 --- a/critterai/.svn/pristine/67/67536fbfa836c3aa95d27bed492890bdb2ace00e.svn-base +++ /dev/null @@ -1,925 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.Vector3.*; - -import static org.junit.Assert.*; - -import org.critterai.math.Vector3; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Vector3} class. - */ -public class Vector3Tests { - - public static final float AX = 1.5f; - public static final float AY = 8.0f; - public static final float AZ = -3.2f; - public static final float BX = -17.112f; - public static final float BY = 77.5f; - public static final float BZ = 22.42f; - - private Vector3 mA1; - private Vector3 mB1; - - float[] mVectors; - - @Before - public void setUp() - throws Exception - { - mA1 = new Vector3(AX, AY, AZ); - mB1 = new Vector3(BX, BY, BZ); - mVectors = new float[6]; - mVectors[0] = AX; - mVectors[1] = AY; - mVectors[2] = AZ; - mVectors[3] = BX; - mVectors[4] = BY; - mVectors[5] = BZ; - } - - @Test - public void testConstructorArray() - { - Vector3 v = new Vector3(mVectors, 1); - assertTrue(v.x == BX); - assertTrue(v.y == BY); - assertTrue(v.z == BZ); - } - - @Test - public void testConstructorDefault() - { - Vector3 v = new Vector3(); - assertTrue(v.x == 0 && v.y == 0 && v.z == 0); - } - - @Test - public void testConstructorFloatFloatFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(v.x == AX && v.y == AY && v.z == AZ); - } - - @Test - public void testDotFloat() - { - float result = mA1.dot(BX, BY, BZ); - float expected = (AX * BX) + (AY * BY) + (AZ * BZ); - assertTrue(result == expected); - } - - @Test - public void testDotVector3() - { - float result = mA1.dot(mB1); - float expected = (AX * BX) + (AY * BY) + (AZ * BZ); - assertTrue(result == expected); - } - - @Test - public void testEqualsFloat() - { - assertTrue(mA1.equals(AX, AY, AZ)); - assertFalse(mA1.equals(AY, AX, AZ)); - assertFalse(mA1.equals(AZ, AX, AY)); - assertFalse(mA1.equals(AX, AZ, AY)); - } - - @Test - public void testEqualsObject() - { - assertTrue(mA1.equals((Object)new Vector3(AX, AY, AZ))); - assertFalse(mA1.equals((Object)mB1)); - assertFalse(mA1.equals((Object)new Vector3(AY, AX, AZ))); - assertFalse(mA1.equals((Object)new Vector3(AZ, AX, AY))); - assertFalse(mA1.equals((Object)new Vector3(AX, AZ, AY))); - } - - @Test - public void testEqualsVector3() - { - assertTrue(mA1.equals(new Vector3(AX, AY, AZ))); - assertFalse(mA1.equals(mB1)); - assertFalse(mA1.equals(new Vector3(AY, AX, AZ))); - assertFalse(mA1.equals(new Vector3(AZ, AX, AY))); - assertFalse(mA1.equals(new Vector3(AX, AZ, AY))); - } - - @Test - public void testFields() - { - assertTrue(mA1.x == AX); - assertTrue(mB1.x == BX); - assertTrue(mA1.y == AY); - assertTrue(mB1.y == BY); - assertTrue(mA1.z == AZ); - assertTrue(mB1.z == BZ); - } - - @Test - public void testFlatten() - { - float[] v = flatten(mVectors, 0, mB1, mA1); - assertTrue(v == mVectors); - assertTrue(v[0] == BX); - assertTrue(v[1] == BY); - assertTrue(v[2] == BZ); - assertTrue(v[3] == AX); - assertTrue(v[4] == AY); - assertTrue(v[5] == AZ); - v = flatten(mVectors, 1, mB1); - assertTrue(v[0] == BX); - assertTrue(v[1] == BY); - assertTrue(v[2] == BZ); - assertTrue(v[3] == BX); - assertTrue(v[4] == BY); - assertTrue(v[5] == BZ); - } - - @Test - public void testGet() - { - float[] va = mA1.get(mVectors, 1); - assertTrue(va == mVectors); - assertTrue(mVectors[0] == AX); - assertTrue(mVectors[1] == AY); - assertTrue(mVectors[2] == AZ); - assertTrue(mVectors[3] == AX); - assertTrue(mVectors[4] == AY); - assertTrue(mVectors[5] == AZ); - mB1.get(mVectors, 0); - assertTrue(mVectors[0] == BX); - assertTrue(mVectors[1] == BY); - assertTrue(mVectors[2] == BZ); - assertTrue(mVectors[3] == AX); - assertTrue(mVectors[4] == AY); - assertTrue(mVectors[5] == AZ); - } - - @Test - public void testGetX() - { - assertTrue(mA1.getX() == AX); - } - - @Test - public void testGetY() - { - assertTrue(mA1.getY() == AY); - } - - @Test - public void testGetZ() - { - assertTrue(mA1.getZ() == AZ); - } - - @Test - public void testHashCode() - { - assertTrue(mA1.hashCode() == new Vector3(AX, AY, AZ).hashCode()); - assertTrue(mA1.hashCode() != mB1.hashCode()); - assertTrue(mA1.hashCode() != new Vector3(AY, AX, AZ).hashCode()); - assertTrue(mA1.hashCode() != new Vector3(AZ, AX, AY).hashCode()); - assertTrue(mA1.hashCode() != new Vector3(AX, AZ, AY).hashCode()); - } - - @Test - public void testIsZeroLength() - { - assertTrue(new Vector3().isZeroLength()); - assertFalse(mA1.isZeroLength()); - } - - @Test - public void testLengthSq() - { - float len = (AX * AX) + (AY * AY) + (AZ * AZ); - assertTrue(mA1.lengthSq() == len); - } - - @Test - public void testMutatorAddFloat() - { - assertTrue(mA1.add(BX, BY, BZ) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - assertTrue(mA1.z == AZ + BZ); - } - - @Test - public void testMutatorAddVector3() - { - assertTrue(mA1.add(mB1) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - assertTrue(mA1.z == AZ + BZ); - } - - @Test - public void testMutatorDivide() - { - assertTrue(mA1.divide(5) == mA1); - assertTrue(mA1.x == AX / 5); - assertTrue(mA1.y == AY / 5); - assertTrue(mA1.z == AZ / 5); - } - - @Test - public void testMutatorMultiply() - { - assertTrue(mA1.multiply(5) == mA1); - assertTrue(mA1.x == AX * 5); - assertTrue(mA1.y == AY * 5); - assertTrue(mA1.z == AZ * 5); - } - - @Test - public void testMutatorNormalize() - { - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float expectedX = AX / len; - float expectedY = AY / len; - float expectedZ = AZ / len; - - assertTrue(mA1.normalize() == mA1); - assertTrue(mA1.x == expectedX); - assertTrue(mA1.y == expectedY); - assertTrue(mA1.z == expectedZ); - } - - @Test - public void testMutatorScaleTo() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.scaleTo(15.0f) == mA1); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - mA1 = new Vector3(AX, AY, AZ).scaleTo(0); - assertTrue(mA1.x == 0 && mA1.y == 0); - } - - @Test - public void testMutatorSubtractFloat() - { - assertTrue(mA1.subtract(BX, BY, BZ) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - assertTrue(mA1.z == AZ - BZ); - } - - @Test - public void testMutatorSubtractVector() - { - assertTrue(mA1.subtract(mB1) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - assertTrue(mA1.z == AZ - BZ); - } - - @Test - public void testMutatorTruncateLength() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.truncateLength(15.0f) == mA1); - assertTrue(mA1.x == AX && mA1.y == AY && mA1.z == mA1.z); - - mA1 = new Vector3(AX, AY, AZ).truncateLength(5); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - mA1 = new Vector3(AX, AY, AZ).truncateLength(0); - assertTrue(mA1.x == 0 && mA1.y == 0 && mA1.z == 0); - } - - @Test - public void testMutatorXValue() - { - mA1.setX(BX); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == AY); - assertTrue(mA1.z == AZ); - } - - @Test - public void testMutatorYValue() - { - mA1.setY(BY); - assertTrue(mA1.x == AX); - assertTrue(mA1.y == BY); - assertTrue(mA1.z == AZ); - } - - @Test - public void testMutatorZValue() - { - mA1.setZ(BZ); - assertTrue(mA1.x == AX); - assertTrue(mA1.y == AY); - assertTrue(mA1.z == BZ); - } - - @Test - public void testSetValueFloat() - { - assertTrue(mA1 == mA1.set(BX, BY, BZ)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - assertTrue(mA1.z == BZ); - - } - - @Test - public void testSetValueVector3() - { - assertTrue (mA1 == mA1.set(mB1)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - assertTrue(mA1.z == BZ); - } - - @Test - public void testSloppyEqualsFloat() - { - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - - mA1 = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - } - - @Test - public void testSloppyEqualsVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(v.sloppyEquals(mA1, 0.0f)); - - v = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - } - - @Test - public void testStaticAddFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(AX, AY, AZ, BX, BY, BZ, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - assertTrue(u.z == AZ + BZ); - } - - @Test - public void testStaticAddValueFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(AX, AY, AZ, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - assertTrue(u.z == AZ + BX); - } - - @Test - public void testStaticAddValueVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - assertTrue(u.z == AZ + BX); - } - - @Test - public void testStaticAddVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - assertTrue(u.z == AZ + BZ); - } - - - @Test - public void testStaticCrossArrayArray() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - float[] v = cross(mVectors, 0, mVectors, 1, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticCrossFloat() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - Vector3 v = Vector3.cross(AX, AY, AZ, BX, BY, BZ, mA1); - assertTrue(v == mA1); - assertTrue(v.x == expectedX); - assertTrue(v.y == expectedY); - assertTrue(v.z == expectedZ); - } - - @Test - public void testStaticCrossFloatArray() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - float[] v = cross(AX, AY, AZ, BX, BY, BZ, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticCrossVector3() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - Vector3 v = cross(mA1, mB1, mA1); - assertTrue(v == mA1); - assertTrue(v.x == expectedX); - assertTrue(v.y == expectedY); - assertTrue(v.z == expectedZ); - } - - @Test - public void testStaticDivideFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = divide(AX, AY, AZ, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - assertTrue(u.z == AZ / BX); - } - - @Test - public void testStaticDivideVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = divide(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - } - - @Test - public void testStaticDotFloat() - { - float expected = (AX * BX) + (AY * BY) + (AZ * BZ); - assertTrue(dot(AX, AY, AZ, BX, BY, BZ) == expected); - } - - @Test - public void testStaticGetDistanceSqFloat() - { - float result = getDistanceSq(AX, AY, AZ, BX, BY, BZ); - float deltaX = BX - AX; - float deltaY = BY - AY; - float deltaZ = BZ - AZ; - float expected = (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ); - assertTrue(result == expected); - } - - @Test - public void testStaticGetDistanceSqVector() - { - float result = getDistanceSq(mA1, mB1); - float deltaX = BX - AX; - float deltaY = BY - AY; - float deltaZ = BZ - AZ; - float expected = (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ); - assertTrue(result == expected); - } - - @Test - public void testStaticGetLengthSq() - { - float len = (AX * AX) + (AY * AY) + (AZ * AZ); - assertTrue(getLengthSq(AX, AY, AZ) == len); - } - - @Test - public void testStaticMultiplyFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = multiply(AX, AY, AZ, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - assertTrue(u.z == AZ * BX); - } - - @Test - public void testStaticMultiplyVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = multiply(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - assertTrue(u.z == AZ * BX); - } - - @Test - public void testStaticNormalizeArrayArray() - { - float[] v = normalize(mVectors, 1, mVectors, 1); - float len = (float) Math.sqrt((BX * BX) + (BY * BY) + (BZ * BZ)); - float expectedX = BX / len; - float expectedY = BY / len; - float expectedZ = BZ / len; - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticNormalizeFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = normalize(AX, AY, AZ, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float x = AX / len; - float y = AY / len; - float z = AZ / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y && u.z == z); - } - - @Test - public void testStaticNormalizeFloatArrray() - { - float[] v = normalize(AX, AY, AZ, mVectors, 1); - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float expectedX = AX / len; - float expectedY = AY / len; - float expectedZ = AZ / len; - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticNormalizeVector() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = normalize(mA1, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float x = AX / len; - float y = AY / len; - float z = AZ / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y && u.z == z); - } - - @Test - public void testStaticScaleToFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = scaleTo(AX, AY, AZ, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(AX, AY, AZ, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - - - - - - - - - - - - - - - - - @Test - public void testStaticScaleToVector3() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = scaleTo(mA1, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - - @Test - public void testStaticSloppyEqualsFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - - v = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - } - - @Test - public void testStaticSloppyEqualsVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(sloppyEquals(mA1, v, 0.0f)); - - v = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - } - - @Test - public void testStaticSubtractArrayArray() - { - float[] v = subtract(mVectors, 1, mVectors, 1, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == 0); - assertTrue(v[4] == 0); - assertTrue(v[5] == 0); - } - - @Test - public void testStaticSubtractFloatArray() - { - float[] v = subtract(AX, AY, AZ, BX, BY, BZ, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == AX - BX); - assertTrue(v[4] == AY - BY); - assertTrue(v[5] == AZ - BZ); - } - - @Test - public void testStaticSubtractFloats() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = subtract(AX, AY, AZ, BX, BY, BZ, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - assertTrue(u.z == AZ - BZ); - } - - @Test - public void testStaticSubtractVectors() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = subtract(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - assertTrue(u.z == AZ - BZ); - } - - @Test - public void testStaticTranslateTowardFloat() - { - final float factor = 0.62f; - final float x = AX + (BX - AX) * factor; - final float y = AY + (BY - AY) * factor; - final float z = AZ + (BZ - AZ) * factor; - Vector3 v = new Vector3(); - Vector3 u = translateToward(AX, AY, AZ, BX, BY, BZ, factor, v); - assertTrue(u == v); - assertTrue(u.x == x); - assertTrue(u.y == y); - assertTrue(u.z == z); - } - - @Test - public void testStaticTruncateLengthFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = truncateLength(AX, AY, AZ, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY && u.z == AZ); - - u = truncateLength(AX, AY, AZ, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(AX, AY, AZ, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - - @Test - public void testStaticTruncateLengthVector3() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = truncateLength(mA1, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY && u.z == AZ); - - u = truncateLength(mA1, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - -} diff --git a/critterai/.svn/pristine/68/682cc32d12ba441835df599cbe69c2e50e862c66.svn-base b/critterai/.svn/pristine/68/682cc32d12ba441835df599cbe69c2e50e862c66.svn-base deleted file mode 100644 index 92eb4341..00000000 --- a/critterai/.svn/pristine/68/682cc32d12ba441835df599cbe69c2e50e862c66.svn-base +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - CAINav provides various extensions that make life easier in Unity. This section covers topcis - that will help you get going. - - - - The NMGen extensions provide designer friendly features that can be used by non-coders to create complex navigation meshes. - There are various extension points that allow coders to easily extend the build process even further. - - - - -
- - Getting CAINav Up and Running - - - - - To get started you first need to get the CAINav package into your project: - - - - - - - Download - http://code.google.com/p/critterai/downloads/list - _blank - and extract the contents of the CAINav distribution. - - - - Locate the Unity Pro package: cai-nav-pro-x.x.x.unitypackage. (Where x.x.x is the version number.) - - - - Import the package into your project. (Assets->Import Package... from the menu bar.) - - - - - The package will add the following files to your project: - - - - The core plug-in libraries to the project's plugin - folder. - - The core libraries to the CAI folder. These give you script level - access to the core CAINav features. - - The Unity extension libraries to the CAI and - CAI/Editor folders. These provide all the Unity extensions. - - - - - The package also adds a CritterAI menu from which many of the features can be accessed. - - - - -
- - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/68/68387ec60cf5ceebfdd9f2169a862d1f296db71d.svn-base b/critterai/.svn/pristine/68/68387ec60cf5ceebfdd9f2169a862d1f296db71d.svn-base deleted file mode 100644 index a77b80dd..00000000 --- a/critterai/.svn/pristine/68/68387ec60cf5ceebfdd9f2169a862d1f296db71d.svn-base +++ /dev/null @@ -1,1451 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include -#include -#include "DetourNavMesh.h" -#include "DetourNode.h" -#include "DetourCommon.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include - - -inline bool overlapSlabs(const float* amin, const float* amax, - const float* bmin, const float* bmax, - const float px, const float py) -{ - // Check for horizontal overlap. - // The segment is shrunken a little so that slabs which touch - // at end points are not connected. - const float minx = dtMax(amin[0]+px,bmin[0]+px); - const float maxx = dtMin(amax[0]-px,bmax[0]-px); - if (minx > maxx) - return false; - - // Check vertical overlap. - const float ad = (amax[1]-amin[1]) / (amax[0]-amin[0]); - const float ak = amin[1] - ad*amin[0]; - const float bd = (bmax[1]-bmin[1]) / (bmax[0]-bmin[0]); - const float bk = bmin[1] - bd*bmin[0]; - const float aminy = ad*minx + ak; - const float amaxy = ad*maxx + ak; - const float bminy = bd*minx + bk; - const float bmaxy = bd*maxx + bk; - const float dmin = bminy - aminy; - const float dmax = bmaxy - amaxy; - - // Crossing segments always overlap. - if (dmin*dmax < 0) - return true; - - // Check for overlap at endpoints. - const float thr = dtSqr(py*2); - if (dmin*dmin <= thr || dmax*dmax <= thr) - return true; - - return false; -} - -static float getSlabCoord(const float* va, const int side) -{ - if (side == 0 || side == 4) - return va[0]; - else if (side == 2 || side == 6) - return va[2]; - return 0; -} - -static void calcSlabEndPoints(const float* va, const float* vb, float* bmin, float* bmax, const int side) -{ - if (side == 0 || side == 4) - { - if (va[2] < vb[2]) - { - bmin[0] = va[2]; - bmin[1] = va[1]; - bmax[0] = vb[2]; - bmax[1] = vb[1]; - } - else - { - bmin[0] = vb[2]; - bmin[1] = vb[1]; - bmax[0] = va[2]; - bmax[1] = va[1]; - } - } - else if (side == 2 || side == 6) - { - if (va[0] < vb[0]) - { - bmin[0] = va[0]; - bmin[1] = va[1]; - bmax[0] = vb[0]; - bmax[1] = vb[1]; - } - else - { - bmin[0] = vb[0]; - bmin[1] = vb[1]; - bmax[0] = va[0]; - bmax[1] = va[1]; - } - } -} - -inline int computeTileHash(int x, int y, const int mask) -{ - const unsigned int h1 = 0x8da6b343; // Large multiplicative constants; - const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes - unsigned int n = h1 * x + h2 * y; - return (int)(n & mask); -} - -inline unsigned int allocLink(dtMeshTile* tile) -{ - if (tile->linksFreeList == DT_NULL_LINK) - return DT_NULL_LINK; - unsigned int link = tile->linksFreeList; - tile->linksFreeList = tile->links[link].next; - return link; -} - -inline void freeLink(dtMeshTile* tile, unsigned int link) -{ - tile->links[link].next = tile->linksFreeList; - tile->linksFreeList = link; -} - - -dtNavMesh* dtAllocNavMesh() -{ - void* mem = dtAlloc(sizeof(dtNavMesh), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtNavMesh; -} - -/// @par -/// -/// This function will only free the memory for tiles with the #DT_TILE_FREE_DATA -/// flag set. -void dtFreeNavMesh(dtNavMesh* navmesh) -{ - if (!navmesh) return; - navmesh->~dtNavMesh(); - dtFree(navmesh); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -/** -@class dtNavMesh - -The navigation mesh consists of one or more tiles defining three primary types of structural data: - -A polygon mesh which defines most of the navigation graph. (See rcPolyMesh for its structure.) -A detail mesh used for determining surface height on the polygon mesh. (See rcPolyMeshDetail for its structure.) -Off-mesh connections, which define custom point-to-point edges within the navigation graph. - -The general build process is as follows: - --# Create rcPolyMesh and rcPolyMeshDetail data using the Recast build pipeline. --# Optionally, create off-mesh connection data. --# Combine the source data into a dtNavMeshCreateParams structure. --# Create a tile data array using dtCreateNavMeshData(). --# Allocate at dtNavMesh object and initialize it. (For single tile navigation meshes, - the tile data is loaded during this step.) --# For multi-tile navigation meshes, load the tile data using dtNavMesh::addTile(). - -Notes: - -- This class is usually used in conjunction with the dtNavMeshQuery class for pathfinding. -- Technically, all navigation meshes are tiled. A 'solo' mesh is simply a navigation mesh initialized - to have only a single tile. -- This class does not implement any asynchronous methods. So the ::dtStatus result of all methods will - always contain either a success or failure flag. - -@see dtNavMeshQuery, dtCreateNavMeshData, dtNavMeshCreateParams, #dtAllocNavMesh, #dtFreeNavMesh -*/ - -dtNavMesh::dtNavMesh() : - m_tileWidth(0), - m_tileHeight(0), - m_maxTiles(0), - m_tileLutSize(0), - m_tileLutMask(0), - m_posLookup(0), - m_nextFree(0), - m_tiles(0), - m_saltBits(0), - m_tileBits(0), - m_polyBits(0) -{ - memset(&m_params, 0, sizeof(dtNavMeshParams)); - m_orig[0] = 0; - m_orig[1] = 0; - m_orig[2] = 0; -} - -dtNavMesh::~dtNavMesh() -{ - for (int i = 0; i < m_maxTiles; ++i) - { - if (m_tiles[i].flags & DT_TILE_FREE_DATA) - { - dtFree(m_tiles[i].data); - m_tiles[i].data = 0; - m_tiles[i].dataSize = 0; - } - } - dtFree(m_posLookup); - dtFree(m_tiles); -} - -dtStatus dtNavMesh::init(const dtNavMeshParams* params) -{ - memcpy(&m_params, params, sizeof(dtNavMeshParams)); - dtVcopy(m_orig, params->orig); - m_tileWidth = params->tileWidth; - m_tileHeight = params->tileHeight; - - // Init tiles - m_maxTiles = params->maxTiles; - m_tileLutSize = dtNextPow2(params->maxTiles/4); - if (!m_tileLutSize) m_tileLutSize = 1; - m_tileLutMask = m_tileLutSize-1; - - m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM); - if (!m_tiles) - return DT_FAILURE | DT_OUT_OF_MEMORY; - m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM); - if (!m_posLookup) - return DT_FAILURE | DT_OUT_OF_MEMORY; - memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles); - memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize); - m_nextFree = 0; - for (int i = m_maxTiles-1; i >= 0; --i) - { - m_tiles[i].salt = 1; - m_tiles[i].next = m_nextFree; - m_nextFree = &m_tiles[i]; - } - - // Init ID generator values. - m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles)); - m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); - // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow. - m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits); - if (m_saltBits < 10) - return DT_FAILURE | DT_INVALID_PARAM; - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flags) -{ - // Make sure the data is in right format. - dtMeshHeader* header = (dtMeshHeader*)data; - if (header->magic != DT_NAVMESH_MAGIC) - return DT_FAILURE | DT_WRONG_MAGIC; - if (header->version != DT_NAVMESH_VERSION) - return DT_FAILURE | DT_WRONG_VERSION; - - dtNavMeshParams params; - dtVcopy(params.orig, header->bmin); - params.tileWidth = header->bmax[0] - header->bmin[0]; - params.tileHeight = header->bmax[2] - header->bmin[2]; - params.maxTiles = 1; - params.maxPolys = header->polyCount; - - dtStatus status = init(¶ms); - if (dtStatusFailed(status)) - return status; - - return addTile(data, dataSize, flags, 0, 0); -} - -/// @par -/// -/// @note The parameters are created automatically when the single tile -/// initialization is performed. -const dtNavMeshParams* dtNavMesh::getParams() const -{ - return &m_params; -} - -////////////////////////////////////////////////////////////////////////////////////////// -int dtNavMesh::findConnectingPolys(const float* va, const float* vb, - const dtMeshTile* tile, int side, - dtPolyRef* con, float* conarea, int maxcon) const -{ - if (!tile) return 0; - - float amin[2], amax[2]; - calcSlabEndPoints(va,vb, amin,amax, side); - const float apos = getSlabCoord(va, side); - - // Remove links pointing to 'side' and compact the links array. - float bmin[2], bmax[2]; - unsigned short m = DT_EXT_LINK | (unsigned short)side; - int n = 0; - - dtPolyRef base = getPolyRefBase(tile); - - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - const int nv = poly->vertCount; - for (int j = 0; j < nv; ++j) - { - // Skip edges which do not point to the right side. - if (poly->neis[j] != m) continue; - - const float* vc = &tile->verts[poly->verts[j]*3]; - const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3]; - const float bpos = getSlabCoord(vc, side); - - // Segments are not close enough. - if (dtAbs(apos-bpos) > 0.01f) - continue; - - // Check if the segments touch. - calcSlabEndPoints(vc,vd, bmin,bmax, side); - - if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue; - - // Add return value. - if (n < maxcon) - { - conarea[n*2+0] = dtMax(amin[0], bmin[0]); - conarea[n*2+1] = dtMin(amax[0], bmax[0]); - con[n] = base | (dtPolyRef)i; - n++; - } - break; - } - } - return n; -} - -void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target) -{ - if (!tile || !target) return; - - const unsigned int targetNum = decodePolyIdTile(getTileRef(target)); - - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - unsigned int j = poly->firstLink; - unsigned int pj = DT_NULL_LINK; - while (j != DT_NULL_LINK) - { - if (tile->links[j].side != 0xff && - decodePolyIdTile(tile->links[j].ref) == targetNum) - { - // Revove link. - unsigned int nj = tile->links[j].next; - if (pj == DT_NULL_LINK) - poly->firstLink = nj; - else - tile->links[pj].next = nj; - freeLink(tile, j); - j = nj; - } - else - { - // Advance - pj = j; - j = tile->links[j].next; - } - } - } -} - -void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side) -{ - if (!tile) return; - - // Connect border links. - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - - // Create new links. -// unsigned short m = DT_EXT_LINK | (unsigned short)side; - - const int nv = poly->vertCount; - for (int j = 0; j < nv; ++j) - { - // Skip non-portal edges. - if ((poly->neis[j] & DT_EXT_LINK) == 0) - continue; - - const int dir = (int)(poly->neis[j] & 0xff); - if (side != -1 && dir != side) - continue; - - // Create new links - const float* va = &tile->verts[poly->verts[j]*3]; - const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3]; - dtPolyRef nei[4]; - float neia[4*2]; - int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(dir), nei,neia,4); - for (int k = 0; k < nnei; ++k) - { - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - dtLink* link = &tile->links[idx]; - link->ref = nei[k]; - link->edge = (unsigned char)j; - link->side = (unsigned char)dir; - - link->next = poly->firstLink; - poly->firstLink = idx; - - // Compress portal limits to a byte value. - if (dir == 0 || dir == 4) - { - float tmin = (neia[k*2+0]-va[2]) / (vb[2]-va[2]); - float tmax = (neia[k*2+1]-va[2]) / (vb[2]-va[2]); - if (tmin > tmax) - dtSwap(tmin,tmax); - link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f); - link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f); - } - else if (dir == 2 || dir == 6) - { - float tmin = (neia[k*2+0]-va[0]) / (vb[0]-va[0]); - float tmax = (neia[k*2+1]-va[0]) / (vb[0]-va[0]); - if (tmin > tmax) - dtSwap(tmin,tmax); - link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f); - link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f); - } - } - } - } - } -} - -void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side) -{ - if (!tile) return; - - // Connect off-mesh links. - // We are interested on links which land from target tile to this tile. - const unsigned char oppositeSide = (unsigned char)dtOppositeTile(side); - - for (int i = 0; i < target->header->offMeshConCount; ++i) - { - dtOffMeshConnection* targetCon = &target->offMeshCons[i]; - if (targetCon->side != oppositeSide) - continue; - - dtPoly* targetPoly = &target->polys[targetCon->poly]; - - const float ext[3] = { targetCon->rad, target->header->walkableClimb, targetCon->rad }; - - // Find polygon to connect to. - const float* p = &targetCon->pos[3]; - float nearestPt[3]; - dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); - if (!ref) continue; - // findNearestPoly may return too optimistic results, further check to make sure. - if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(targetCon->rad)) - continue; - // Make sure the location is on current mesh. - float* v = &target->verts[targetPoly->verts[1]*3]; - dtVcopy(v, nearestPt); - - // Link off-mesh connection to target poly. - unsigned int idx = allocLink(target); - if (idx != DT_NULL_LINK) - { - dtLink* link = &target->links[idx]; - link->ref = ref; - link->edge = (unsigned char)1; - link->side = oppositeSide; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = targetPoly->firstLink; - targetPoly->firstLink = idx; - } - - // Link target poly to off-mesh connection. - if (targetCon->flags & DT_OFFMESH_CON_BIDIR) - { - unsigned int tidx = allocLink(tile); - if (tidx != DT_NULL_LINK) - { - const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); - dtPoly* landPoly = &tile->polys[landPolyIdx]; - dtLink* link = &tile->links[tidx]; - link->ref = getPolyRefBase(target) | (dtPolyRef)(targetCon->poly); - link->edge = 0xff; - link->side = (unsigned char)side; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = landPoly->firstLink; - landPoly->firstLink = tidx; - } - } - } - -} - -void dtNavMesh::connectIntLinks(dtMeshTile* tile) -{ - if (!tile) return; - - dtPolyRef base = getPolyRefBase(tile); - - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - poly->firstLink = DT_NULL_LINK; - - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Build edge links backwards so that the links will be - // in the linked list from lowest index to highest. - for (int j = poly->vertCount-1; j >= 0; --j) - { - // Skip hard and non-internal edges. - if (poly->neis[j] == 0 || (poly->neis[j] & DT_EXT_LINK)) continue; - - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - dtLink* link = &tile->links[idx]; - link->ref = base | (dtPolyRef)(poly->neis[j]-1); - link->edge = (unsigned char)j; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = poly->firstLink; - poly->firstLink = idx; - } - } - } -} - -void dtNavMesh::connectIntOffMeshLinks(dtMeshTile* tile) -{ - if (!tile) return; - - dtPolyRef base = getPolyRefBase(tile); - - // Find Off-mesh connection end points. - for (int i = 0; i < tile->header->offMeshConCount; ++i) - { - dtOffMeshConnection* con = &tile->offMeshCons[i]; - dtPoly* poly = &tile->polys[con->poly]; - - const float ext[3] = { con->rad, tile->header->walkableClimb, con->rad }; - - for (int j = 0; j < 2; ++j) - { - unsigned char side = j == 0 ? 0xff : con->side; - - if (side == 0xff) - { - // Find polygon to connect to. - const float* p = &con->pos[j*3]; - float nearestPt[3]; - dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); - if (!ref) continue; - // findNearestPoly may return too optimistic results, further check to make sure. - if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad)) - continue; - // Make sure the location is on current mesh. - float* v = &tile->verts[poly->verts[j]*3]; - dtVcopy(v, nearestPt); - - // Link off-mesh connection to target poly. - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - dtLink* link = &tile->links[idx]; - link->ref = ref; - link->edge = (unsigned char)j; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = poly->firstLink; - poly->firstLink = idx; - } - - // Start end-point is always connect back to off-mesh connection, - // Destination end-point only if it is bidirectional link. - if (j == 0 || (j == 1 && (con->flags & DT_OFFMESH_CON_BIDIR))) - { - // Link target poly to off-mesh connection. - unsigned int tidx = allocLink(tile); - if (tidx != DT_NULL_LINK) - { - const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); - dtPoly* landPoly = &tile->polys[landPolyIdx]; - dtLink* link = &tile->links[tidx]; - link->ref = base | (dtPolyRef)(con->poly); - link->edge = 0xff; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = landPoly->firstLink; - landPoly->firstLink = tidx; - } - } - - } - } - } -} - -void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, - const float* pos, float* closest) const -{ - const dtPoly* poly = &tile->polys[ip]; - - float closestDistSqr = FLT_MAX; - const dtPolyDetail* pd = &tile->detailMeshes[ip]; - - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - float pt[3]; - dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]); - float d = dtVdistSqr(pos, pt); - if (d < closestDistSqr) - { - dtVcopy(closest, pt); - closestDistSqr = d; - } - } -} - -dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile, - const float* center, const float* extents, - float* nearestPt) const -{ - float bmin[3], bmax[3]; - dtVsub(bmin, center, extents); - dtVadd(bmax, center, extents); - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = queryPolygonsInTile(tile, bmin, bmax, polys, 128); - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) - { - dtPolyRef ref = polys[i]; - float closestPtPoly[3]; - closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly); - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) - { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; - } - } - - return nearest; -} - -int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, - dtPolyRef* polys, const int maxPolys) const -{ - if (tile->bvTree) - { - const dtBVNode* node = &tile->bvTree[0]; - const dtBVNode* end = &tile->bvTree[tile->header->bvNodeCount]; - const float* tbmin = tile->header->bmin; - const float* tbmax = tile->header->bmax; - const float qfac = tile->header->bvQuantFactor; - - // Calculate quantized box - unsigned short bmin[3], bmax[3]; - // dtClamp query box to world box. - float minx = dtClamp(qmin[0], tbmin[0], tbmax[0]) - tbmin[0]; - float miny = dtClamp(qmin[1], tbmin[1], tbmax[1]) - tbmin[1]; - float minz = dtClamp(qmin[2], tbmin[2], tbmax[2]) - tbmin[2]; - float maxx = dtClamp(qmax[0], tbmin[0], tbmax[0]) - tbmin[0]; - float maxy = dtClamp(qmax[1], tbmin[1], tbmax[1]) - tbmin[1]; - float maxz = dtClamp(qmax[2], tbmin[2], tbmax[2]) - tbmin[2]; - // Quantize - bmin[0] = (unsigned short)(qfac * minx) & 0xfffe; - bmin[1] = (unsigned short)(qfac * miny) & 0xfffe; - bmin[2] = (unsigned short)(qfac * minz) & 0xfffe; - bmax[0] = (unsigned short)(qfac * maxx + 1) | 1; - bmax[1] = (unsigned short)(qfac * maxy + 1) | 1; - bmax[2] = (unsigned short)(qfac * maxz + 1) | 1; - - // Traverse tree - dtPolyRef base = getPolyRefBase(tile); - int n = 0; - while (node < end) - { - const bool overlap = dtOverlapQuantBounds(bmin, bmax, node->bmin, node->bmax); - const bool isLeafNode = node->i >= 0; - - if (isLeafNode && overlap) - { - if (n < maxPolys) - polys[n++] = base | (dtPolyRef)node->i; - } - - if (overlap || isLeafNode) - node++; - else - { - const int escapeIndex = -node->i; - node += escapeIndex; - } - } - - return n; - } - else - { - float bmin[3], bmax[3]; - int n = 0; - dtPolyRef base = getPolyRefBase(tile); - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - // Calc polygon bounds. - const float* v = &tile->verts[p->verts[0]*3]; - dtVcopy(bmin, v); - dtVcopy(bmax, v); - for (int j = 1; j < p->vertCount; ++j) - { - v = &tile->verts[p->verts[j]*3]; - dtVmin(bmin, v); - dtVmax(bmax, v); - } - if (dtOverlapBounds(qmin,qmax, bmin,bmax)) - { - if (n < maxPolys) - polys[n++] = base | (dtPolyRef)i; - } - } - return n; - } -} - -/// @par -/// -/// The add operation will fail if the data is in the wrong format, the allocated tile -/// space is full, or there is a tile already at the specified reference. -/// -/// The lastRef parameter is used to restore a tile with the same tile -/// reference it had previously used. In this case the #dtPolyRef's for the -/// tile will be restored to the same values they were before the tile was -/// removed. -/// -/// @see dtCreateNavMeshData, #removeTile -dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, - dtTileRef lastRef, dtTileRef* result) -{ - // Make sure the data is in right format. - dtMeshHeader* header = (dtMeshHeader*)data; - if (header->magic != DT_NAVMESH_MAGIC) - return DT_FAILURE | DT_WRONG_MAGIC; - if (header->version != DT_NAVMESH_VERSION) - return DT_FAILURE | DT_WRONG_VERSION; - - // Make sure the location is free. - if (getTileAt(header->x, header->y, header->layer)) - return DT_FAILURE; - - // Allocate a tile. - dtMeshTile* tile = 0; - if (!lastRef) - { - if (m_nextFree) - { - tile = m_nextFree; - m_nextFree = tile->next; - tile->next = 0; - } - } - else - { - // Try to relocate the tile to specific index with same salt. - int tileIndex = (int)decodePolyIdTile((dtPolyRef)lastRef); - if (tileIndex >= m_maxTiles) - return DT_FAILURE | DT_OUT_OF_MEMORY; - // Try to find the specific tile id from the free list. - dtMeshTile* target = &m_tiles[tileIndex]; - dtMeshTile* prev = 0; - tile = m_nextFree; - while (tile && tile != target) - { - prev = tile; - tile = tile->next; - } - // Could not find the correct location. - if (tile != target) - return DT_FAILURE | DT_OUT_OF_MEMORY; - // Remove from freelist - if (!prev) - m_nextFree = tile->next; - else - prev->next = tile->next; - - // Restore salt. - tile->salt = decodePolyIdSalt((dtPolyRef)lastRef); - } - - // Make sure we could allocate a tile. - if (!tile) - return DT_FAILURE | DT_OUT_OF_MEMORY; - - // Insert tile into the position lut. - int h = computeTileHash(header->x, header->y, m_tileLutMask); - tile->next = m_posLookup[h]; - m_posLookup[h] = tile; - - // Patch header pointers. - const int headerSize = dtAlign4(sizeof(dtMeshHeader)); - const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount); - const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount); - const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount)); - const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount); - const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount); - const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount); - const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount); - const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); - - unsigned char* d = data + headerSize; - tile->verts = (float*)d; d += vertsSize; - tile->polys = (dtPoly*)d; d += polysSize; - tile->links = (dtLink*)d; d += linksSize; - tile->detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - tile->detailVerts = (float*)d; d += detailVertsSize; - tile->detailTris = (unsigned char*)d; d += detailTrisSize; - tile->bvTree = (dtBVNode*)d; d += bvtreeSize; - tile->offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize; - - // If there are no items in the bvtree, reset the tree pointer. - if (!bvtreeSize) - tile->bvTree = 0; - - // Build links freelist - tile->linksFreeList = 0; - tile->links[header->maxLinkCount-1].next = DT_NULL_LINK; - for (int i = 0; i < header->maxLinkCount-1; ++i) - tile->links[i].next = i+1; - - // Init tile. - tile->header = header; - tile->data = data; - tile->dataSize = dataSize; - tile->flags = flags; - - connectIntLinks(tile); - connectIntOffMeshLinks(tile); - - // Create connections with neighbour tiles. - static const int MAX_NEIS = 32; - dtMeshTile* neis[MAX_NEIS]; - int nneis; - - // Connect with layers in current tile. - nneis = getTilesAt(header->x, header->y, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - if (neis[j] == tile) continue; - connectExtLinks(tile, neis[j], -1); - connectExtLinks(neis[j], tile, -1); - connectExtOffMeshLinks(tile, neis[j], -1); - connectExtOffMeshLinks(neis[j], tile, -1); - } - - // Connect with neighbour tiles. - for (int i = 0; i < 8; ++i) - { - nneis = getNeighbourTilesAt(header->x, header->y, i, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - connectExtLinks(tile, neis[j], i); - connectExtLinks(neis[j], tile, dtOppositeTile(i)); - connectExtOffMeshLinks(tile, neis[j], i); - connectExtOffMeshLinks(neis[j], tile, dtOppositeTile(i)); - } - } - - if (result) - *result = getTileRef(tile); - - return DT_SUCCESS; -} - -const dtMeshTile* dtNavMesh::getTileAt(const int x, const int y, const int layer) const -{ - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y && - tile->header->layer == layer) - { - return tile; - } - tile = tile->next; - } - return 0; -} - -int dtNavMesh::getNeighbourTilesAt(const int x, const int y, const int side, dtMeshTile** tiles, const int maxTiles) const -{ - int nx = x, ny = y; - switch (side) - { - case 0: nx++; break; - case 1: nx++; ny++; break; - case 2: ny++; break; - case 3: nx--; ny++; break; - case 4: nx--; break; - case 5: nx--; ny--; break; - case 6: ny--; break; - case 7: nx++; ny--; break; - }; - - return getTilesAt(nx, ny, tiles, maxTiles); -} - -int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile** tiles, const int maxTiles) const -{ - int n = 0; - - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y) - { - if (n < maxTiles) - tiles[n++] = tile; - } - tile = tile->next; - } - - return n; -} - -/// @par -/// -/// This function will not fail if the tiles array is too small to hold the -/// entire result set. It will simply fill the array to capacity. -int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile const** tiles, const int maxTiles) const -{ - int n = 0; - - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y) - { - if (n < maxTiles) - tiles[n++] = tile; - } - tile = tile->next; - } - - return n; -} - - -dtTileRef dtNavMesh::getTileRefAt(const int x, const int y, const int layer) const -{ - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y && - tile->header->layer == layer) - { - return getTileRef(tile); - } - tile = tile->next; - } - return 0; -} - -const dtMeshTile* dtNavMesh::getTileByRef(dtTileRef ref) const -{ - if (!ref) - return 0; - unsigned int tileIndex = decodePolyIdTile((dtPolyRef)ref); - unsigned int tileSalt = decodePolyIdSalt((dtPolyRef)ref); - if ((int)tileIndex >= m_maxTiles) - return 0; - const dtMeshTile* tile = &m_tiles[tileIndex]; - if (tile->salt != tileSalt) - return 0; - return tile; -} - -int dtNavMesh::getMaxTiles() const -{ - return m_maxTiles; -} - -dtMeshTile* dtNavMesh::getTile(int i) -{ - return &m_tiles[i]; -} - -const dtMeshTile* dtNavMesh::getTile(int i) const -{ - return &m_tiles[i]; -} - -void dtNavMesh::calcTileLoc(const float* pos, int* tx, int* ty) const -{ - *tx = (int)floorf((pos[0]-m_orig[0]) / m_tileWidth); - *ty = (int)floorf((pos[2]-m_orig[2]) / m_tileHeight); -} - -dtStatus dtNavMesh::getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - if (ip >= (unsigned int)m_tiles[it].header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - *tile = &m_tiles[it]; - *poly = &m_tiles[it].polys[ip]; - return DT_SUCCESS; -} - -/// @par -/// -/// @warning Only use this function if it is known that the provided polygon -/// reference is valid. This function is faster than #getTileAndPolyByRef, but -/// it does not validate the reference. -void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const -{ - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - *tile = &m_tiles[it]; - *poly = &m_tiles[it].polys[ip]; -} - -bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const -{ - if (!ref) return false; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return false; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false; - if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false; - return true; -} - -/// @par -/// -/// This function returns the data for the tile so that, if desired, -/// it can be added back to the navigation mesh at a later point. -/// -/// @see #addTile -dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSize) -{ - if (!ref) - return DT_FAILURE | DT_INVALID_PARAM; - unsigned int tileIndex = decodePolyIdTile((dtPolyRef)ref); - unsigned int tileSalt = decodePolyIdSalt((dtPolyRef)ref); - if ((int)tileIndex >= m_maxTiles) - return DT_FAILURE | DT_INVALID_PARAM; - dtMeshTile* tile = &m_tiles[tileIndex]; - if (tile->salt != tileSalt) - return DT_FAILURE | DT_INVALID_PARAM; - - // Remove tile from hash lookup. - int h = computeTileHash(tile->header->x,tile->header->y,m_tileLutMask); - dtMeshTile* prev = 0; - dtMeshTile* cur = m_posLookup[h]; - while (cur) - { - if (cur == tile) - { - if (prev) - prev->next = cur->next; - else - m_posLookup[h] = cur->next; - break; - } - prev = cur; - cur = cur->next; - } - - // Remove connections to neighbour tiles. - // Create connections with neighbour tiles. - static const int MAX_NEIS = 32; - dtMeshTile* neis[MAX_NEIS]; - int nneis; - - // Connect with layers in current tile. - nneis = getTilesAt(tile->header->x, tile->header->y, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - if (neis[j] == tile) continue; - unconnectExtLinks(neis[j], tile); - } - - // Connect with neighbour tiles. - for (int i = 0; i < 8; ++i) - { - nneis = getNeighbourTilesAt(tile->header->x, tile->header->y, i, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - unconnectExtLinks(neis[j], tile); - } - - // Reset tile. - if (tile->flags & DT_TILE_FREE_DATA) - { - // Owns data - dtFree(tile->data); - tile->data = 0; - tile->dataSize = 0; - if (data) *data = 0; - if (dataSize) *dataSize = 0; - } - else - { - if (data) *data = tile->data; - if (dataSize) *dataSize = tile->dataSize; - } - - tile->header = 0; - tile->flags = 0; - tile->linksFreeList = 0; - tile->polys = 0; - tile->verts = 0; - tile->links = 0; - tile->detailMeshes = 0; - tile->detailVerts = 0; - tile->detailTris = 0; - tile->bvTree = 0; - tile->offMeshCons = 0; - - // Update salt, salt should never be zero. - tile->salt = (tile->salt+1) & ((1<salt == 0) - tile->salt++; - - // Add to free list. - tile->next = m_nextFree; - m_nextFree = tile; - - return DT_SUCCESS; -} - -dtTileRef dtNavMesh::getTileRef(const dtMeshTile* tile) const -{ - if (!tile) return 0; - const unsigned int it = (unsigned int)(tile - m_tiles); - return (dtTileRef)encodePolyId(tile->salt, it, 0); -} - -/// @par -/// -/// Example use case: -/// @code -/// -/// const dtPolyRef base = navmesh->getPolyRefBase(tile); -/// for (int i = 0; i < tile->header->polyCount; ++i) -/// { -/// const dtPoly* p = &tile->polys[i]; -/// const dtPolyRef ref = base | (dtPolyRef)i; -/// -/// // Use the reference to access the polygon data. -/// } -/// @endcode -dtPolyRef dtNavMesh::getPolyRefBase(const dtMeshTile* tile) const -{ - if (!tile) return 0; - const unsigned int it = (unsigned int)(tile - m_tiles); - return encodePolyId(tile->salt, it, 0); -} - -struct dtTileState -{ - int magic; // Magic number, used to identify the data. - int version; // Data version number. - dtTileRef ref; // Tile ref at the time of storing the data. -}; - -struct dtPolyState -{ - unsigned short flags; // Flags (see dtPolyFlags). - unsigned char area; // Area ID of the polygon. -}; - -/// @see #storeTileState -int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const -{ - if (!tile) return 0; - const int headerSize = dtAlign4(sizeof(dtTileState)); - const int polyStateSize = dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); - return headerSize + polyStateSize; -} - -/// @par -/// -/// Tile state includes non-structural data such as polygon flags, area ids, etc. -/// @note The state data is only valid until the tile reference changes. -/// @see #getTileStateSize, #restoreTileState -dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const -{ - // Make sure there is enough space to store the state. - const int sizeReq = getTileStateSize(tile); - if (maxDataSize < sizeReq) - return DT_FAILURE | DT_BUFFER_TOO_SMALL; - - dtTileState* tileState = (dtTileState*)data; data += dtAlign4(sizeof(dtTileState)); - dtPolyState* polyStates = (dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); - - // Store tile state. - tileState->magic = DT_NAVMESH_STATE_MAGIC; - tileState->version = DT_NAVMESH_STATE_VERSION; - tileState->ref = getTileRef(tile); - - // Store per poly state. - for (int i = 0; i < tile->header->polyCount; ++i) - { - const dtPoly* p = &tile->polys[i]; - dtPolyState* s = &polyStates[i]; - s->flags = p->flags; - s->area = p->getArea(); - } - - return DT_SUCCESS; -} - -/// @par -/// -/// Tile state includes non-structural data such as polygon flags, area ids, etc. -/// @note This function does not impact the tile's #dtTileRef and #dtPolyRef's. -/// @see #storeTileState -dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize) -{ - // Make sure there is enough space to store the state. - const int sizeReq = getTileStateSize(tile); - if (maxDataSize < sizeReq) - return DT_FAILURE | DT_INVALID_PARAM; - - const dtTileState* tileState = (const dtTileState*)data; data += dtAlign4(sizeof(dtTileState)); - const dtPolyState* polyStates = (const dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); - - // Check that the restore is possible. - if (tileState->magic != DT_NAVMESH_STATE_MAGIC) - return DT_FAILURE | DT_WRONG_MAGIC; - if (tileState->version != DT_NAVMESH_STATE_VERSION) - return DT_FAILURE | DT_WRONG_VERSION; - if (tileState->ref != getTileRef(tile)) - return DT_FAILURE | DT_INVALID_PARAM; - - // Restore per poly state. - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* p = &tile->polys[i]; - const dtPolyState* s = &polyStates[i]; - p->flags = s->flags; - p->setArea(s->area); - } - - return DT_SUCCESS; -} - -/// @par -/// -/// Off-mesh connections are stored in the navigation mesh as special 2-vertex -/// polygons with a single edge. At least one of the vertices is expected to be -/// inside a normal polygon. So an off-mesh connection is "entered" from a -/// normal polygon at one of its endpoints. This is the polygon identified by -/// the prevRef parameter. -dtStatus dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const -{ - unsigned int salt, it, ip; - - if (!polyRef) - return DT_FAILURE; - - // Get current polygon - decodePolyId(polyRef, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - const dtPoly* poly = &tile->polys[ip]; - - // Make sure that the current poly is indeed off-mesh link. - if (poly->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) - return DT_FAILURE; - - // Figure out which way to hand out the vertices. - int idx0 = 0, idx1 = 1; - - // Find link that points to first vertex. - for (unsigned int i = poly->firstLink; i != DT_NULL_LINK; i = tile->links[i].next) - { - if (tile->links[i].edge == 0) - { - if (tile->links[i].ref != prevRef) - { - idx0 = 1; - idx1 = 0; - } - break; - } - } - - dtVcopy(startPos, &tile->verts[poly->verts[idx0]*3]); - dtVcopy(endPos, &tile->verts[poly->verts[idx1]*3]); - - return DT_SUCCESS; -} - - -const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) const -{ - unsigned int salt, it, ip; - - if (!ref) - return 0; - - // Get current polygon - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return 0; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return 0; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return 0; - const dtPoly* poly = &tile->polys[ip]; - - // Make sure that the current poly is indeed off-mesh link. - if (poly->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) - return 0; - - const unsigned int idx = ip - tile->header->offMeshBase; - dtAssert(idx < (unsigned int)tile->header->offMeshConCount); - return &tile->offMeshCons[idx]; -} - - -dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags) -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - dtPoly* poly = &tile->polys[ip]; - - // Change flags. - poly->flags = flags; - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - const dtPoly* poly = &tile->polys[ip]; - - *resultFlags = poly->flags; - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area) -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - dtPoly* poly = &tile->polys[ip]; - - poly->setArea(area); - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::getPolyArea(dtPolyRef ref, unsigned char* resultArea) const -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - const dtPoly* poly = &tile->polys[ip]; - - *resultArea = poly->getArea(); - - return DT_SUCCESS; -} - diff --git a/critterai/.svn/pristine/68/6849ba831242d4d6549b907ddd43ea21aa000cda.svn-base b/critterai/.svn/pristine/68/6849ba831242d4d6549b907ddd43ea21aa000cda.svn-base deleted file mode 100644 index a60925ab..00000000 --- a/critterai/.svn/pristine/68/6849ba831242d4d6549b907ddd43ea21aa000cda.svn-base +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#if NUNITY - -using System.Runtime.InteropServices; - -namespace org.critterai -{ - /// - /// Represents a 3D floating point vector. - /// - /// - /// - /// Not present in the Unity build. - /// - /// - /// This structure's API kept very simple in order to minimize conflicts with other - /// vector implementations. The class provides some standard - /// vector operations. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct Vector3 - { - - /// - /// The x-value of vector (x, y, z). - /// - public float x; - - /// - /// The y-value of vector (x, y, z). - /// - public float y; - - /// - /// The z-value of teh vector (x, y, z) - /// - public float z; - - /// - /// Constructor. - /// - /// The x-value of vector (x, y, z). - /// The y-value of vector (x, y, z). - /// The z-value of vector (x, y, z). - public Vector3(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - } - - /// - /// The vector equality operator. - /// - /// A vector. - /// A vector. - /// True if each element of the vectors are equal. - public static bool operator ==(Vector3 v, Vector3 u) - { - return (v.x == u.x && v.y == u.y && v.z == u.z); - } - - /// - /// The vector inequality operator. - /// - /// A vector. - /// A vector. - /// True if any equivalent element of the vectors is not equal. - public static bool operator !=(Vector3 v, Vector3 u) - { - return !(v.x == u.x && v.y == u.y && v.z == u.z); - } - - /// - /// Vector subtraction operator. (v - u) - /// - /// The l-value vector. - /// The r-value vector. - /// A vector represnting (v - u). - public static Vector3 operator -(Vector3 v, Vector3 u) - { - return new Vector3(v.x - u.x, v.y - u.y, v.z - u.z); - } - - /// - /// Vector addition operator. (v + u) - /// - /// A vector. - /// A vector. - /// A vector represnting (v + u). - public static Vector3 operator +(Vector3 v, Vector3 u) - { - return new Vector3(v.x + u.x, v.y + u.y, v.z + u.z); - } - - /// - /// The vector hash code. - /// - /// The vector hash code. - public override int GetHashCode() - { - int result = 17; - result = 31 * result + x.GetHashCode(); - result = 31 * result + y.GetHashCode(); - result = 31 * result + z.GetHashCode(); - return result; - } - - - /// - /// Tests the vector for equality. - /// - /// The vector to compare. - /// True if each element of the vector is equal to this vector. - public override bool Equals(object obj) - { - if (obj is Vector3) - { - Vector3 u = (Vector3)obj; - return (x == u.x && y == u.y && z == u.z); - } - return false; - } - } -} - -#endif \ No newline at end of file diff --git a/critterai/.svn/pristine/68/68a53e9d10736054db66b30d0fea13f7eedc4109.svn-base b/critterai/.svn/pristine/68/68a53e9d10736054db66b30d0fea13f7eedc4109.svn-base deleted file mode 100644 index 521b5ef7..00000000 --- a/critterai/.svn/pristine/68/68a53e9d10736054db66b30d0fea13f7eedc4109.svn-base +++ /dev/null @@ -1,1151 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.interop; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Represents the data used to build a . - /// - /// - /// - /// This class marshals data between the navigation mesh generation pipeline and the - /// navigation system. The NMGen PolyMesh and PolyMeshDetail classes provide details on - /// data stucture and limits. - /// - /// - /// The standard load process is as follows: - /// - ///
    - ///
  1. Construct the object.
  2. - ///
  3. - ///
  4. - ///
  5. (Optional)
  6. - ///
  7. (Optional)
  8. - ///
- /// - /// The design permits re-use of the data buffers for multiple tile builds. Just set the - /// buffer sizes to the maximum size required then use the load methods to reload the data - /// as needed. The only restriction is that all polygon data must have the same - /// maximum vertices per polygon. - /// - /// - /// Behavior is undefined if used after disposal. - /// - ///
- [StructLayout(LayoutKind.Sequential)] - public sealed class NavmeshTileBuildData - { - /// - /// The minimum allowed cell size. - /// - public const float MinCellSize = 0.01f; - - /// - /// The absolute minimum allowed value for . - /// - public const float MinAllowedTraversableHeight = 3 * MinCellSize; - - #region dtNavMeshCreateParams Fields (private) - - /// - /// ushort buffer. - /// - private IntPtr mPolyVerts = IntPtr.Zero; - - private int mPolyVertCount = 0; - - /// - /// ushort buffer. - /// - private IntPtr mPolys = IntPtr.Zero; - - /// - /// ushort buffer. - /// - private IntPtr mPolyFlags = IntPtr.Zero; - - /// - /// byte buffer - /// - private IntPtr mPolyAreas = IntPtr.Zero; - - private int mPolyCount = 0; - private int mMaxVertsPerPoly = 0; - - /// - /// uint buffer - /// - /// - /// Note: Used by Detour to detect if there detail meshes - /// are available. - /// - private IntPtr mDetailMeshes = IntPtr.Zero; - - /// - /// float buffer - /// - private IntPtr mDetailVerts = IntPtr.Zero; - - private int mDetailVertCount = 0; - - /// - /// byte array - /// - private IntPtr mDetailTris = IntPtr.Zero; - - private int mDetailTriCount = 0; - - /// - /// float array - /// - private IntPtr mConnVerts = IntPtr.Zero; - - /// - /// float array - /// - private IntPtr mConnRadii = IntPtr.Zero; - - /// - /// ushort array - /// - private IntPtr mConnFlags = IntPtr.Zero; - - /// - /// byte array - /// - private IntPtr mConnAreas = IntPtr.Zero; - - /// - /// byte array - /// - private IntPtr mConnDirs = IntPtr.Zero; - - /// - /// uint array - /// - private IntPtr mConnUserIds = IntPtr.Zero; - - /// - /// Connection Count - /// - /// - /// Note: Used by Detour to detect if there are any connections. - /// - private int mConnCount = 0; - - private uint mTileUserId = 0; - private int mTileX = 0; - private int mTileY = 0; - private int mTileLayer = 0; - - // Note: Keep bounds storage in the native format. - // Convert to Vector3 as needed. - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - private float[] mBoundsMin = new float[3]; - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - private float[] mBoundsMax = new float[3]; - - private float mWalkableHeight = 0; - private float mWalkableRadius = 0; - private float mWalkableStep = 0; - private float mXZCellSize = 0; - private float mYCellSize = 0; - private bool mBVTreeEnabled = false; - - #endregion - - #region rcnNavMeshCreateParams Fields (private) - - private bool mIsDisposed = true; // Default is accurate. - - private int mMaxPolyVerts = 0; - private int mMaxPolys = 0; - - private int mMaxDetailVerts = 0; - private int mMaxDetailTris = 0; - - private int mMaxConns = 0; - - #endregion - - /// - /// The maximum allowed polygon vertices. - /// - public int MaxPolyVerts { get { return mMaxPolyVerts; } } - - /// - /// The maximum allowed polygons. - /// - public int MaxPolys { get { return mMaxPolys; } } - - /// - /// The maximum allowed detail vertices. - /// - public int MaxDetailVerts { get { return mMaxDetailVerts; } } - - /// - /// The maximum allowed detail triangles. - /// - public int MaxDetailTris { get { return mMaxDetailTris; } } - - /// - /// The maximum allowed off-mesh connections. - /// - public int MaxConns { get { return mMaxConns; } } - - /// - /// The number of polygon vertices. - /// - public int PolyVertCount { get { return mPolyVertCount; } } - - /// - /// The number of polygons. - /// - public int PolyCount { get { return mPolyCount; } } - - /// - /// The maximum vertices per polygon. - /// - public int MaxVertsPerPoly { get { return mMaxVertsPerPoly; } } - - /// - /// The number of detail vertices. - /// - public int DetailVertCount { get { return mDetailVertCount; } } - - /// - /// The number of detail triangles. - /// - public int DetailTriCount { get { return mDetailTriCount; } } - - /// - /// The number of off-mesh connections. - /// - public int ConnCount { get { return mConnCount; } } - - /// - /// The user id of the tile. - /// - public uint TileUserId { get { return mTileUserId; } } - - /// - /// The tile grid x-location. - /// - public int TileX { get { return mTileX; } } - - /// - /// The tile grid z-location. - /// - public int TileZ { get { return mTileY; } } - - /// - /// The tile's layer. - /// - public int TileLayer { get { return mTileLayer; } } - - /// - /// The minimum bounds of the tile's AABB. - /// - public Vector3 BoundsMin - { - get - { - return new Vector3(mBoundsMin[0], mBoundsMin[1], mBoundsMin[2]); - } - } - - /// - /// The maximum bounds of the tile's AABB. - /// - public Vector3 BoundsMax - { - get - { - return new Vector3(mBoundsMax[0], mBoundsMax[1], mBoundsMax[2]); - } - } - - /// - /// The walkable height to use for the tile. - /// - public float WalkableHeight { get { return mWalkableHeight; } } - - /// - /// The walkable radius to use for the tile. - /// - public float WalkableRadius { get { return mWalkableRadius; } } - - /// - /// The walkable step to use for the tile. - /// - public float MaxTraversableStep { get { return mWalkableStep; } } - - /// - /// The xz-plane cell size of the tile. - /// - public float XZCellSize { get { return mXZCellSize; } } - - /// - /// The y-axis cell size of the tile. - /// - public float YCellSize { get { return mYCellSize; } } - - /// - /// True if bounding volumn data should be generated for the tile. - /// - /// This value is normally set to false if the tile is small - /// or layers are being used. - public bool BVTreeEnabled { get { return mBVTreeEnabled; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return mIsDisposed; } } - - private void InitializeBuffers(int maxPolyVerts - , int maxPolys - , int maxVertsPerPoly - , int maxDetailVerts - , int maxDetailTris - , int maxConns) - { - mMaxPolyVerts = maxPolyVerts; - mMaxPolys = maxPolys; - mMaxDetailVerts = maxDetailVerts; - mMaxDetailTris = maxDetailTris; - mMaxConns = maxConns; - - mMaxVertsPerPoly = maxVertsPerPoly; - - // Polygons - - int size = maxPolyVerts * sizeof(ushort) * 3; - mPolyVerts = UtilEx.GetBuffer(size, true); - - size = maxPolys * sizeof(ushort) * 2 * mMaxVertsPerPoly; - mPolys = UtilEx.GetBuffer(size, true); - - size = maxPolys * sizeof(ushort); - mPolyFlags = UtilEx.GetBuffer(size, true); - - size = maxPolys * sizeof(byte); - mPolyAreas = UtilEx.GetBuffer(size, true); - - // Detail meshes - - if (maxDetailTris > 0) - { - size = maxDetailVerts * sizeof(float) * 3; - mDetailVerts = UtilEx.GetBuffer(size, true); - - size = maxDetailTris * sizeof(byte) * 4; - mDetailTris = UtilEx.GetBuffer(size, true); - - size = maxPolys * sizeof(uint) * 4; - mDetailMeshes = UtilEx.GetBuffer(size, true); - } - - // Connections - - if (maxConns > 0) - { - size = maxConns * sizeof(float) * 2 * 3; - mConnVerts = UtilEx.GetBuffer(size, true); - - size = maxConns * sizeof(float); - mConnRadii = UtilEx.GetBuffer(size, true); - - size = maxConns * sizeof(ushort); - mConnFlags = UtilEx.GetBuffer(size, true); - - size = maxConns * sizeof(byte); - mConnAreas = UtilEx.GetBuffer(size, true); - mConnDirs = UtilEx.GetBuffer(size, true); - - size = maxConns * sizeof(uint); - mConnUserIds = UtilEx.GetBuffer(size, true); - } - } - - /// - /// Constructor. - /// - /// - /// If invalid parameter values are supplied the resulting object - /// will not be usable. (Buffers won't be initialized, all maximum - /// size values set to zero.) - /// - /// The maximum allowed polygon vertices. - /// The maximum allowed polygons. - /// The maximum vertices per polygon. - /// The maximum allowed detail vertices. - /// The maximum allowed detail vetices. - /// The maximum allowed off-mesh connections. - public NavmeshTileBuildData(int maxPolyVerts - , int maxPolys - , int maxVertsPerPoly - , int maxDetailVerts - , int maxDetailTris - , int maxConns) - { - if (!IsValid(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , maxDetailVerts - , maxDetailTris - , maxConns)) - { - return; - } - - InitializeBuffers(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , maxDetailVerts - , maxDetailTris - , maxConns); - - mIsDisposed = false; - } - - /// - /// Constructor. (No off-mesh connections.) - /// - /// - /// If invalid parameter values are supplied the resulting object - /// will not be usable. (Buffers won't be initialized, all maximum - /// size values set to zero.) - /// - /// The maximum allowed polygon vertices. - /// The maximum allowed polygons. - /// The maximum vertices per polygon. - /// The maximum allowed detail vertices. - /// The maximum allowed detail vetices. - public NavmeshTileBuildData(int maxPolyVerts - , int maxPolys - , int maxVertsPerPoly - , int maxDetailVerts - , int maxDetailTris) - { - if (!IsValid(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , maxDetailVerts - , maxDetailTris - , 0)) - { - return; - } - - InitializeBuffers(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , maxDetailVerts - , maxDetailTris - , 0); - - mIsDisposed = false; - } - - /// - /// Constructor. (No detail mesh.) - /// - /// - /// - /// If invalid parameter values are supplied the resulting object will not be usable. - /// (Buffers won't be initialized, all maximum size values set to zero.) - /// - /// - /// The maximum allowed polygon vertices. - /// The maximum allowed polygons. - /// The maximum vertices per polygon. - /// The maximum allowed off-mesh connections. - public NavmeshTileBuildData(int maxPolyVerts - , int maxPolys - , int maxVertsPerPoly - , int maxConns) - { - if (!IsValid(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , 0 - , 0 - , maxConns)) - { - return; - } - - InitializeBuffers(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , 0 - , 0 - , maxConns); - - mIsDisposed = false; - } - - /// - /// Constructor. (No detail mesh or off-mesh connections.) - /// - /// - /// - /// If invalid parameter values are supplied the resulting object will not be usable. - /// (Buffers won't be initialized, all maximum size values set to zero.) - /// - /// - /// The maximum allowed polygon vertices. - /// The maximum allowed polygons. - /// The maximum vertices per polygon. - public NavmeshTileBuildData(int maxPolyVerts - , int maxPolys - , int maxVertsPerPoly) - { - if (!IsValid(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , 0 - , 0 - , 0)) - { - return; - } - - InitializeBuffers(maxPolyVerts - , maxPolys - , maxVertsPerPoly - , 0 - , 0 - , 0); - - mIsDisposed = false; - } - - /// - /// Destructor - /// - ~NavmeshTileBuildData() - { - Dispose(); - } - - /// - /// Disposes of all resources and marks the object as disposed. - /// - public void Dispose() - { - if (mIsDisposed) - return; - - // Polygons - if (mPolys != IntPtr.Zero) - { - Marshal.FreeHGlobal(mPolyVerts); - Marshal.FreeHGlobal(mPolys); - Marshal.FreeHGlobal(mPolyFlags); - Marshal.FreeHGlobal(mPolyAreas); - } - - // Detail meshes - if (mDetailMeshes != IntPtr.Zero) - { - Marshal.FreeHGlobal(mDetailVerts); - Marshal.FreeHGlobal(mDetailTris); - Marshal.FreeHGlobal(mDetailMeshes); - } - - // Connections - - if (mConnVerts != IntPtr.Zero) - { - Marshal.FreeHGlobal(mConnVerts); - Marshal.FreeHGlobal(mConnRadii); - Marshal.FreeHGlobal(mConnFlags); - Marshal.FreeHGlobal(mConnAreas); - Marshal.FreeHGlobal(mConnDirs); - Marshal.FreeHGlobal(mConnUserIds); - } - - mBoundsMin = new float[3] { 0, 0, 0 }; - mBoundsMax = new float[3] { 0, 0, 0 }; - - mMaxVertsPerPoly = 0; - - mPolyVerts = IntPtr.Zero; - mPolys = IntPtr.Zero; - mPolyFlags = IntPtr.Zero; - mPolyAreas = IntPtr.Zero; - - mDetailVerts = IntPtr.Zero; - mDetailTris = IntPtr.Zero; - mDetailMeshes = IntPtr.Zero; - - mConnVerts = IntPtr.Zero; - mConnRadii = IntPtr.Zero; - mConnFlags = IntPtr.Zero; - mConnAreas = IntPtr.Zero; - mConnDirs = IntPtr.Zero; - mConnUserIds = IntPtr.Zero; - - mPolyVertCount = 0; - mPolyCount = 0; - mDetailVertCount = 0; - mDetailTriCount = 0; - mConnCount = 0; - mTileUserId = 0; - mTileX = 0; - mTileY = 0; - mTileLayer = 0; - mWalkableHeight = 0; - mWalkableStep = 0; - mWalkableRadius = 0; - mXZCellSize = 0; - mYCellSize = 0; - mBVTreeEnabled = false; - - mMaxConns = 0; - mMaxDetailTris = 0; - mMaxDetailVerts = 0; - mMaxPolys = 0; - mMaxPolyVerts = 0; - - mIsDisposed = true; - } - - /// - /// Load the base configuration. - /// - /// The tile grid x-location. - /// The tile grid y-location. - /// The tile layer. - /// The tile's user assigned id. - /// The minumum bounds. - /// The maximum bounds. - /// The xz-plane cell size. - /// The y-axis cell size. - /// The walkable height. - /// The walkable radius. - /// The walkable step. - /// True if bounding volumes should beused. - /// True if the load succeeded. - public bool LoadBase(int tileX - , int tileZ - , int tileLayer - , uint tileUserId - , Vector3 boundsMin - , Vector3 boundsMax - , float xzCellSize - , float yCellSize - , float walkableHeight - , float walkableRadius - , float walkableStep - , bool bvTreeEnabled) - { - if (mIsDisposed - || xzCellSize < MinCellSize - || yCellSize < MinCellSize - || walkableHeight < MinAllowedTraversableHeight - || walkableStep < 0 - || walkableRadius < 0) - { - return false; - } - - mTileX = tileX; - mTileY = tileZ; - mTileLayer = tileLayer; - mTileUserId = tileUserId; - - GetVector(boundsMin, mBoundsMin); - GetVector(boundsMax, mBoundsMax); - - mXZCellSize = xzCellSize; - mYCellSize = yCellSize; - - mWalkableHeight = walkableHeight; - mWalkableStep = walkableStep; - mWalkableRadius = walkableRadius; - - mBVTreeEnabled = bvTreeEnabled; - - return true; - } - - /// - /// Load the polygon data. - /// - /// Polygon vertices. - /// The number of vertices. - /// Polygons. - /// Polygon flags. - /// Polygon areas ids. - /// The number of polygons. - /// True if the load succeeded. - public bool LoadPolys(ushort[] polyVerts - , int vertCount - , ushort[] polys - , ushort[] polyFlags - , byte[] polyAreas - , int polyCount) - { - if (mIsDisposed - || vertCount < 3 - || polyCount < 1 - || polyVerts == null - || polyVerts.Length < 3 * vertCount - || vertCount > mMaxPolyVerts - || polys == null - || polys.Length < polyCount * 2 * mMaxVertsPerPoly - || polyCount > mMaxPolys - || polyFlags == null - || polyFlags.Length < polyCount - || polyAreas == null - || polyAreas.Length < polyCount) - { - return false; - } - - // Design note: Considered allowing null flags and areas, then - // filling the arrays with default values. But haven't found - // a memset equivalent. So don't see a memory/processing efficient - // way to implement it. - - mPolyVertCount = vertCount; - mPolyCount = polyCount; - - UtilEx.Copy(polyVerts, 0, mPolyVerts, vertCount * 3); - UtilEx.Copy(polys, 0, mPolys, mPolyCount * 2 * mMaxVertsPerPoly); - - UtilEx.Copy(polyFlags, 0, mPolyFlags, mPolyCount); - Marshal.Copy(polyAreas, 0, mPolyAreas, mPolyCount); - - return true; - } - - /// - /// Load the detail mesh data. - /// - /// Detail vertices. - /// The number of detail vertices. - /// Detail triangles. - /// The number of detail triagles. - /// Detail meshes. - /// The number of detail meshes. - /// True if the load succeeded. - public bool LoadDetail(Vector3[] verts - , int vertCount - , byte[] tris - , int triCount - , uint[] meshes - , int meshCount) - { - if (mIsDisposed - || mDetailMeshes == IntPtr.Zero - || vertCount < 3 - || triCount < 1 - || verts == null - || verts.Length < vertCount - || vertCount > mMaxDetailVerts - || tris == null - || tris.Length < triCount * 4 - || triCount > mMaxDetailTris - || meshes == null - || meshes.Length < meshCount * 4 - || meshCount > mMaxPolys) - { - return false; - } - - mDetailVertCount = vertCount; - mDetailTriCount = triCount; - - // Necessary since polys may not be loaded yet. - // The poly load will override this. - if (mPolyCount == 0) - mPolyCount = meshCount; - - float[] fverts = Vector3Util.Flatten(verts, vertCount); - - Marshal.Copy(fverts, 0, mDetailVerts, vertCount * 3); - Marshal.Copy(tris, 0, mDetailTris, triCount * 4); - UtilEx.Copy(meshes, 0, mDetailMeshes, meshCount * 4); - - return true; - } - - /// - /// Load the off-mesh connection data. - /// - /// The connection vertices - /// Connection radii. - /// Connection direction data. - /// Connection areas. - /// Connection flags. - /// Connection user ids. - /// The number of connections. - /// True if the load succeeded. - public bool LoadConns(Vector3[] connVerts - , float[] connRadii - , byte[] connDirs - , byte[] connAreas - , ushort[] connFlags - , uint[] connUserIds - , int connCount) - { - if (mIsDisposed) - return false; - - if (connCount == 0) - { - mConnCount = 0; - return true; - } - - if (mConnVerts == IntPtr.Zero - || connCount < 0 - || connCount > mMaxConns - || connVerts == null - || connVerts.Length < connCount * 2 - || connRadii == null - || connRadii.Length < connCount - || connDirs == null - || connDirs.Length < connCount - || connAreas == null - || connAreas.Length < connCount - || connFlags == null - || connFlags.Length < connCount - || connUserIds == null - || connUserIds.Length < connCount) - { - return false; - } - - mConnCount = connCount; - - float[] fverts = Vector3Util.Flatten(connVerts, connCount * 2); - Marshal.Copy(fverts, 0, mConnVerts, connCount * 2 * 3); - Marshal.Copy(connRadii, 0, mConnRadii, connCount); - Marshal.Copy(connDirs, 0, mConnDirs, connCount); - Marshal.Copy(connAreas, 0, mConnAreas, connCount); - UtilEx.Copy(connFlags, 0, mConnFlags, connCount); - UtilEx.Copy(connUserIds, 0, mConnUserIds, connCount); - - return true; - } - - /// - /// Returns a copy of the vertex information for each polygon. - /// - /// - /// The buffer to load the results into. [Length: >= * 3] - /// - /// The number of vertices returned, or -1 on error. - public int GetPolyVerts(ushort[] buffer) - { - if (mPolyVerts == IntPtr.Zero - || buffer == null - || buffer.Length < mPolyVertCount * 3) - { - return -1; - } - UtilEx.Copy(mPolyVerts, buffer, mPolyVertCount * 3); - return mPolyVertCount; - } - - /// - /// Returns a copy of polygon and neighbor information. - /// - /// - /// The buffer to load the results into. - /// [Length: >= * 2 * ] - /// - /// The number of polygons returned, or -1 on error. - public int GetPolys(ushort[] buffer) - { - if (mPolys == IntPtr.Zero - || buffer == null - || buffer.Length < mPolyCount * 2 * mMaxVertsPerPoly) - { - return -1; - } - UtilEx.Copy(mPolys, buffer, mPolyCount * 2 * mMaxVertsPerPoly); - return mPolyCount; - } - - /// - /// Returns a copy of the area for each polygon. - /// - /// - /// The buffer to load the results into. [Length: >= ] - /// - /// The number of areas returned, or -1 on error. - public int GetPolyAreas(byte[] buffer) - { - if (mPolyAreas == IntPtr.Zero - || buffer == null - || buffer.Length < mPolyCount) - { - return -1; - } - Marshal.Copy(mPolyAreas, buffer, 0, mPolyCount); - return mPolyCount; - } - - /// - /// Returns a copy of the user-defined flags for each polygon. - /// - /// - /// The buffer to load the results into. [Length: >= ] - /// - /// The number of flags returned, or -1 on error. - public int GetPolyFlags(ushort[] buffer) - { - if (mPolyFlags == IntPtr.Zero - || buffer == null - || buffer.Length < mPolyCount) - { - return -1; - } - UtilEx.Copy(mPolyFlags, buffer, mPolyCount); - return mPolyCount; - } - - /// - /// Returns a copy of the sub-mesh data for the detail mesh. - /// - /// - /// The buffer to load the results into. [Length: >= ] * 4 - /// - /// The number of sub-meshes returned, or -1 on error. - public int GetDetailMeshes(uint[] buffer) - { - if (mDetailMeshes == IntPtr.Zero - || buffer == null - || buffer.Length < mPolyCount * 4) - { - return -1; - } - UtilEx.Copy(mDetailMeshes, buffer, mPolyCount * 4); - return mPolyCount; - } - - /// - /// Returns a copy of the triangle/flag data for the detail mesh. - /// - /// - /// The buffer to load the results into. [Length: >= * 4] - /// - /// The number of triangles returned, or -1 on error. - public int GetDetailTris(byte[] buffer) - { - if (mDetailTris == IntPtr.Zero - || buffer == null - || buffer.Length < mDetailTriCount * 4) - { - return -1; - } - Marshal.Copy(mDetailTris, buffer, 0, mDetailTriCount * 4); - return mDetailTriCount; - } - - /// - /// Returns a copy of the vertex data for the detail mesh. - /// - /// - /// The buffer to load the results into. [Length: >= * 3] - /// - /// The number of vertices returned, or -1 on error. - public int GetDetailVerts(Vector3[] buffer) - { - if (mDetailVerts == IntPtr.Zero - || buffer == null - || buffer.Length < mDetailVertCount) - { - return -1; - } - float[] fverts = new float[mDetailVertCount * 3]; - Marshal.Copy(mDetailVerts, fverts, 0, fverts.Length); - Vector3Util.GetVectors(fverts, 0, buffer, 0, mDetailVertCount); - return mDetailVertCount; - } - - /// - /// Returns a copy of the off-mesh connection vertices. - /// - /// - /// The buffer to load the results into. [Length: >= * 6] - /// - /// The number of vertices returned, or -1 on error. - public int GetConnVerts(Vector3[] buffer) - { - if (mConnVerts == IntPtr.Zero - || buffer == null - || buffer.Length < mConnCount * 2) - { - return -1; - } - float[] fverts = new float[mConnCount * 2 * 3]; - Marshal.Copy(mConnVerts, fverts, 0, mConnCount * 2 * 3); - Vector3Util.GetVectors(fverts, 0, buffer, 0, mConnCount * 2); - return mConnCount; - } - - /// - /// Returns a copy of the radii for off-mesh connections. - /// - /// - /// The buffer to load the results into. [Length: >= ] - /// - /// The number of radii returned, or -1 on error. - public int GetConnRadii(float[] buffer) - { - if (mConnRadii == IntPtr.Zero - || buffer == null - || buffer.Length < mConnCount) - { - return -1; - } - Marshal.Copy(mConnRadii, buffer, 0, mConnCount); - return mConnCount; - } - - /// - /// Returns a copy of the user-defined flags for off-mesh connections. - /// - /// - /// The buffer to load the results into. [Length: >= ] - /// - /// The number of flags returned, or -1 on error. - public int GetConnFlags(ushort[] buffer) - { - if (mConnFlags == IntPtr.Zero - || buffer == null - || buffer.Length < mConnCount) - { - return -1; - } - UtilEx.Copy(mConnFlags, buffer, mConnCount); - return mConnCount; - } - - /// - /// Returns a copy of the areas for off-mesh connections. - /// - /// - /// The buffer to load the results into. [Length: >= ] - /// - /// The number of areas returned, or -1 on error. - public int GetConnAreas(byte[] buffer) - { - if (mConnAreas == IntPtr.Zero - || buffer == null - || buffer.Length < mConnCount) - { - return -1; - } - Marshal.Copy(mConnAreas, buffer, 0, mConnCount); - return mConnCount; - } - - /// - /// Returns a copy of the direction flags for off-mesh connections. - /// - /// - /// The buffer to load the results into. [Length: >= ] - /// - /// The number of direction flags returned, or -1 on error. - public int GetConnDirs(byte[] buffer) - { - if (mConnDirs == IntPtr.Zero - || buffer == null - || buffer.Length < mConnCount) - { - return -1; - } - Marshal.Copy(mConnDirs, buffer, 0, mConnCount); - return mConnCount; - } - - /// - /// The user-defined ids for off-mesh connections. - /// - /// - /// The buffer to load the results into. [Length: >= ] - /// - /// The number of user ids returned, or -1 on error. - public int GetConnUserIds(uint[] buffer) - { - if (mConnUserIds == IntPtr.Zero - || buffer == null - || buffer.Length < mConnCount) - { - return -1; - } - UtilEx.Copy(mConnUserIds, buffer, mConnCount); - return mConnCount; - } - - private static bool IsValid(int maxPolyVerts - , int maxPolys - , int maxVertsPerPoly - , int maxDetailVerts - , int maxDetailTris - , int maxConns) - { - if (maxPolyVerts < 3 - || maxPolys < 1 - || maxVertsPerPoly > Navmesh.MaxAllowedVertsPerPoly - || maxVertsPerPoly < 3 - || maxDetailVerts < 0 - || maxDetailTris < 0 - || maxConns < 0) - { - return false; - } - - if ((maxDetailVerts > 0 || maxDetailTris > 0) - && (maxDetailVerts < 3 || maxDetailTris < 1)) - { - return false; - } - - return true; - } - - private static float[] GetVector(Vector3 vector, float[] buffer) - { - buffer[0] = vector.x; - buffer[1] = vector.y; - buffer[2] = vector.z; - return buffer; - } - } -} diff --git a/critterai/.svn/pristine/68/68ccf0f1a4304907385e650d06cc4303418d357b.svn-base b/critterai/.svn/pristine/68/68ccf0f1a4304907385e650d06cc4303418d357b.svn-base deleted file mode 100644 index 4078dd60..00000000 Binary files a/critterai/.svn/pristine/68/68ccf0f1a4304907385e650d06cc4303418d357b.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/69/695b2cfce38efb4c5e27c4126b627391decfd1ec.svn-base b/critterai/.svn/pristine/69/695b2cfce38efb4c5e27c4126b627391decfd1ec.svn-base deleted file mode 100644 index 34f46d8d..00000000 --- a/critterai/.svn/pristine/69/695b2cfce38efb4c5e27c4126b627391decfd1ec.svn-base +++ /dev/null @@ -1,526 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURCOMMON_H -#define DETOURCOMMON_H - -/** -@defgroup detour Detour - -Members in this module are used to create, manipulate, and query navigation -meshes. - -@note This is a summary list of members. Use the index or search -feature to find minor members. -*/ - -/// @name General helper functions -/// @{ - -/// Swaps the values of the two parameters. -/// @param[in,out] a Value A -/// @param[in,out] b Value B -template inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; } - -/// Returns the minimum of two values. -/// @param[in] a Value A -/// @param[in] b Value B -/// @return The minimum of the two values. -template inline T dtMin(T a, T b) { return a < b ? a : b; } - -/// Returns the maximum of two values. -/// @param[in] a Value A -/// @param[in] b Value B -/// @return The maximum of the two values. -template inline T dtMax(T a, T b) { return a > b ? a : b; } - -/// Returns the absolute value. -/// @param[in] a The value. -/// @return The absolute value of the specified value. -template inline T dtAbs(T a) { return a < 0 ? -a : a; } - -/// Returns the square of the value. -/// @param[in] a The value. -/// @return The square of the value. -template inline T dtSqr(T a) { return a*a; } - -/// Clamps the value to the specified range. -/// @param[in] v The value to clamp. -/// @param[in] mn The minimum permitted return value. -/// @param[in] mx The maximum permitted return value. -/// @return The value, clamped to the specified range. -template inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } - -/// Returns the square root of the value. -/// @param[in] x The value. -/// @return The square root of the vlaue. -float dtSqrt(float x); - -/// @} -/// @name Vector helper functions. -/// @{ - -/// Derives the cross product of two vectors. (@p v1 x @p v2) -/// @param[out] dest The cross product. [(x, y, z)] -/// @param[in] v1 A Vector [(x, y, z)] -/// @param[in] v2 A vector [(x, y, z)] -inline void dtVcross(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; - dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; - dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -/// Derives the dot product of two vectors. (@p v1 . @p v2) -/// @param[in] v1 A Vector [(x, y, z)] -/// @param[in] v2 A vector [(x, y, z)] -/// @return The dot product. -inline float dtVdot(const float* v1, const float* v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s)) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)] -/// @param[in] s The amount to scale @p v2 by before adding to @p v1. -inline void dtVmad(float* dest, const float* v1, const float* v2, const float s) -{ - dest[0] = v1[0]+v2[0]*s; - dest[1] = v1[1]+v2[1]*s; - dest[2] = v1[2]+v2[2]*s; -} - -/// Performs a linear interpolation between two vectors. (@p v1 toward @p v2) -/// @param[out] dest The result vector. [(x, y, x)] -/// @param[in] v1 The starting vector. -/// @param[in] v2 The destination vector. -/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0] -inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t) -{ - dest[0] = v1[0]+(v2[0]-v1[0])*t; - dest[1] = v1[1]+(v2[1]-v1[1])*t; - dest[2] = v1[2]+(v2[2]-v1[2])*t; -} - -/// Performs a vector addition. (@p v1 + @p v2) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to add to @p v1. [(x, y, z)] -inline void dtVadd(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]+v2[0]; - dest[1] = v1[1]+v2[1]; - dest[2] = v1[2]+v2[2]; -} - -/// Performs a vector subtraction. (@p v1 - @p v2) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)] -inline void dtVsub(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]-v2[0]; - dest[1] = v1[1]-v2[1]; - dest[2] = v1[2]-v2[2]; -} - -/// Scales the vector by the specified value. (@p v * @p t) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v The vector to scale. [(x, y, z)] -/// @param[in] t The scaling factor. -inline void dtVscale(float* dest, const float* v, const float t) -{ - dest[0] = v[0]*t; - dest[1] = v[1]*t; - dest[2] = v[2]*t; -} - -/// Selects the minimum value of each element from the specified vectors. -/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)] -/// @param[in] v A vector. [(x, y, z)] -inline void dtVmin(float* mn, const float* v) -{ - mn[0] = dtMin(mn[0], v[0]); - mn[1] = dtMin(mn[1], v[1]); - mn[2] = dtMin(mn[2], v[2]); -} - -/// Selects the maximum value of each element from the specified vectors. -/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)] -/// @param[in] v A vector. [(x, y, z)] -inline void dtVmax(float* mx, const float* v) -{ - mx[0] = dtMax(mx[0], v[0]); - mx[1] = dtMax(mx[1], v[1]); - mx[2] = dtMax(mx[2], v[2]); -} - -/// Sets the vector elements to the specified values. -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] x The x-value of the vector. -/// @param[in] y The y-value of the vector. -/// @param[in] z The z-value of the vector. -inline void dtVset(float* dest, const float x, const float y, const float z) -{ - dest[0] = x; dest[1] = y; dest[2] = z; -} - -/// Performs a vector copy. -/// @param[out] dest The result. [(x, y, z)] -/// @param[in] a The vector to copy. [(x, y, z)] -inline void dtVcopy(float* dest, const float* a) -{ - dest[0] = a[0]; - dest[1] = a[1]; - dest[2] = a[2]; -} - -/// Derives the scalar length of the vector. -/// @param[in] v The vector. [(x, y, z)] -/// @return The scalar length of the vector. -inline float dtVlen(const float* v) -{ - return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); -} - -/// Derives the square of the scalar length of the vector. (len * len) -/// @param[in] v The vector. [(x, y, z)] -/// @return The square of the scalar length of the vector. -inline float dtVlenSqr(const float* v) -{ - return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; -} - -/// Returns the distance between two points. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The distance between the two points. -inline float dtVdist(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; - const float dz = v2[2] - v1[2]; - return dtSqrt(dx*dx + dy*dy + dz*dz); -} - -/// Returns the square of the distance between two points. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The square of the distance between the two points. -inline float dtVdistSqr(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; - const float dz = v2[2] - v1[2]; - return dx*dx + dy*dy + dz*dz; -} - -/// Derives the distance between the specified points on the xz-plane. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The distance between the point on the xz-plane. -/// -/// The vectors are projected onto the xz-plane, so the y-values are ignored. -inline float dtVdist2D(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dz = v2[2] - v1[2]; - return dtSqrt(dx*dx + dz*dz); -} - -/// Derives the square of the distance between the specified points on the xz-plane. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The square of the distance between the point on the xz-plane. -inline float dtVdist2DSqr(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dz = v2[2] - v1[2]; - return dx*dx + dz*dz; -} - -/// Normalizes the vector. -/// @param[in,out] v The vector to normalize. [(x, y, z)] -inline void dtVnormalize(float* v) -{ - float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2])); - v[0] *= d; - v[1] *= d; - v[2] *= d; -} - -/// Performs a 'sloppy' colocation check of the specified points. -/// @param[in] p0 A point. [(x, y, z)] -/// @param[in] p1 A point. [(x, y, z)] -/// @return True if the points are considered to be at the same location. -/// -/// Basically, this function will return true if the specified points are -/// close enough to eachother to be considered colocated. -inline bool dtVequal(const float* p0, const float* p1) -{ - static const float thr = dtSqr(1.0f/16384.0f); - const float d = dtVdistSqr(p0, p1); - return d < thr; -} - -/// Derives the dot product of two vectors on the xz-plane. (@p u . @p v) -/// @param[in] u A vector [(x, y, z)] -/// @param[in] v A vector [(x, y, z)] -/// @return The dot product on the xz-plane. -/// -/// The vectors are projected onto the xz-plane, so the y-values are ignored. -inline float dtVdot2D(const float* u, const float* v) -{ - return u[0]*v[0] + u[2]*v[2]; -} - -/// Derives the xz-plane 2D perp product of the two vectors. (uz*vx - ux*vz) -/// @param[in] u The LHV vector [(x, y, z)] -/// @param[in] v The RHV vector [(x, y, z)] -/// @return The dot product on the xz-plane. -/// -/// The vectors are projected onto the xz-plane, so the y-values are ignored. -inline float dtVperp2D(const float* u, const float* v) -{ - return u[2]*v[0] - u[0]*v[2]; -} - -/// @} -/// @name Computational geometry helper functions. -/// @{ - -/// Derives the signed xz-plane area of the triangle ABC, or the relationship of line AB to point C. -/// @param[in] a Vertex A. [(x, y, z)] -/// @param[in] b Vertex B. [(x, y, z)] -/// @param[in] c Vertex C. [(x, y, z)] -/// @return The signed xz-plane area of the triangle. -inline float dtTriArea2D(const float* a, const float* b, const float* c) -{ - const float abx = b[0] - a[0]; - const float abz = b[2] - a[2]; - const float acx = c[0] - a[0]; - const float acz = c[2] - a[2]; - return acx*abz - abx*acz; -} - -/// Determines if two axis-aligned bounding boxes overlap. -/// @param[in] amin Minimum bounds of box A. [(x, y, z)] -/// @param[in] amax Maximum bounds of box A. [(x, y, z)] -/// @param[in] bmin Minimum bounds of box B. [(x, y, z)] -/// @param[in] bmax Maximum bounds of box B. [(x, y, z)] -/// @return True if the two AABB's overlap. -/// @see dtOverlapBounds -inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3], - const unsigned short bmin[3], const unsigned short bmax[3]) -{ - bool overlap = true; - overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; - overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; - overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; - return overlap; -} - -/// Determines if two axis-aligned bounding boxes overlap. -/// @param[in] amin Minimum bounds of box A. [(x, y, z)] -/// @param[in] amax Maximum bounds of box A. [(x, y, z)] -/// @param[in] bmin Minimum bounds of box B. [(x, y, z)] -/// @param[in] bmax Maximum bounds of box B. [(x, y, z)] -/// @return True if the two AABB's overlap. -/// @see dtOverlapQuantBounds -inline bool dtOverlapBounds(const float* amin, const float* amax, - const float* bmin, const float* bmax) -{ - bool overlap = true; - overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; - overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; - overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; - return overlap; -} - -/// Derives the closest point on a triangle from the specified reference point. -/// @param[out] closest The closest point on the triangle. -/// @param[in] p The reference point from which to test. [(x, y, z)] -/// @param[in] a Vertex A of triangle ABC. [(x, y, z)] -/// @param[in] b Vertex B of triangle ABC. [(x, y, z)] -/// @param[in] c Vertex C of triangle ABC. [(x, y, z)] -void dtClosestPtPointTriangle(float* closest, const float* p, - const float* a, const float* b, const float* c); - -/// Derives the y-axis height of the closest point on the triangle from the specified reference point. -/// @param[in] p The reference point from which to test. [(x, y, z)] -/// @param[in] a Vertex A of triangle ABC. [(x, y, z)] -/// @param[in] b Vertex B of triangle ABC. [(x, y, z)] -/// @param[in] c Vertex C of triangle ABC. [(x, y, z)] -/// @param[out] h The resulting height. -bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h); - -bool dtIntersectSegmentPoly2D(const float* p0, const float* p1, - const float* verts, int nverts, - float& tmin, float& tmax, - int& segMin, int& segMax); - -/// Determines if the specified point is inside the convex polygon on the xz-plane. -/// @param[in] pt The point to check. [(x, y, z)] -/// @param[in] verts The polygon vertices. [(x, y, z) * @p nverts] -/// @param[in] nverts The number of vertices. [Limit: >= 3] -/// @return True if the point is inside the polygon. -bool dtPointInPolygon(const float* pt, const float* verts, const int nverts); - -bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts, - float* ed, float* et); - -float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t); - -/// Derives the centroid of a convex polygon. -/// @param[out] tc The centroid of the polgyon. [(x, y, z)] -/// @param[in] idx The polygon indices. [(vertIndex) * @p nidx] -/// @param[in] nidx The number of indices in the polygon. [Limit: >= 3] -/// @param[in] verts The polygon vertices. [(x, y, z) * vertCount] -void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts); - -/// Determines if the two convex polygons overlap on the xz-plane. -/// @param[in] polya Polygon A vertices. [(x, y, z) * @p npolya] -/// @param[in] npolya The number of vertices in polygon A. -/// @param[in] polyb Polygon B vertices. [(x, y, z) * @p npolyb] -/// @param[in] npolyb The number of vertices in polygon B. -/// @return True if the two polygons overlap. -bool dtOverlapPolyPoly2D(const float* polya, const int npolya, - const float* polyb, const int npolyb); - -/// @} -/// @name Miscellanious functions. -/// @{ - -inline unsigned int dtNextPow2(unsigned int v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - -inline unsigned int dtIlog2(unsigned int v) -{ - unsigned int r; - unsigned int shift; - r = (v > 0xffff) << 4; v >>= r; - shift = (v > 0xff) << 3; v >>= shift; r |= shift; - shift = (v > 0xf) << 2; v >>= shift; r |= shift; - shift = (v > 0x3) << 1; v >>= shift; r |= shift; - r |= (v >> 1); - return r; -} - -inline int dtAlign4(int x) { return (x+3) & ~3; } - -inline int dtOppositeTile(int side) { return (side+4) & 0x7; } - -inline void dtSwapByte(unsigned char* a, unsigned char* b) -{ - unsigned char tmp = *a; - *a = *b; - *b = tmp; -} - -inline void dtSwapEndian(unsigned short* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+1); -} - -inline void dtSwapEndian(short* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+1); -} - -inline void dtSwapEndian(unsigned int* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); -} - -inline void dtSwapEndian(int* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); -} - -inline void dtSwapEndian(float* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); -} - -void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas, - const float s, const float t, float* out); - -/// @} - -#endif // DETOURCOMMON_H - -/////////////////////////////////////////////////////////////////////////// - -// This section contains detailed documentation for members that don't have -// a source file. It reduces clutter in the main section of the header. - -/** - -@fn float dtTriArea2D(const float* a, const float* b, const float* c) -@par - -The vertices are projected onto the xz-plane, so the y-values are ignored. - -This is a low cost function than can be used for various purposes. Its main purpose -is for point/line relationship testing. - -In all cases: A value of zero indicates that all vertices are collinear or represent the same point. -(On the xz-plane.) - -When used for point/line relationship tests, AB usually represents a line against which -the C point is to be tested. In this case: - -A positive value indicates that point C is to the left of line AB, looking from A toward B.
-A negative value indicates that point C is to the right of lineAB, looking from A toward B. - -When used for evaluating a triangle: - -The absolute value of the return value is two times the area of the triangle when it is -projected onto the xz-plane. - -A positive return value indicates: - -
    -
  • The vertices are wrapped in the normal Detour wrap direction.
  • -
  • The triangle's 3D face normal is in the general up direction.
  • -
- -A negative return value indicates: - -
    -
  • The vertices are reverse wrapped. (Wrapped opposite the normal Detour wrap direction.)
  • -
  • The triangle's 3D face normal is in the general down direction.
  • -
- -*/ diff --git a/critterai/.svn/pristine/6b/6b34e98888e8ba062c4aa1aafda1ad7c2f009ef1.svn-base b/critterai/.svn/pristine/6b/6b34e98888e8ba062c4aa1aafda1ad7c2f009ef1.svn-base deleted file mode 100644 index cbe44069..00000000 --- a/critterai/.svn/pristine/6b/6b34e98888e8ba062c4aa1aafda1ad7c2f009ef1.svn-base +++ /dev/null @@ -1,59 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {1FF01BFD-2593-406A-959E-D4D84CEB662C} - Library - Properties - org.critterai - cai-util-u3d-editor - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - none - true - ..\bin\Release\ - TRACE - prompt - 4 - AnyCPU - ..\bin\Release\cai-util-u3d-editor.XML - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEditor.dll - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - Properties\AssemblyInfo.cs - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/6b/6b9a4150fc8c8c531408098dfb0aad0ca3725790.svn-base b/critterai/.svn/pristine/6b/6b9a4150fc8c8c531408098dfb0aad0ca3725790.svn-base deleted file mode 100644 index 20603410..00000000 --- a/critterai/.svn/pristine/6b/6b9a4150fc8c8c531408098dfb0aad0ca3725790.svn-base +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.geom; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal struct InputAssets - { - public InputBuildInfo info; - public TriangleMesh geometry; - public byte[] areas; - public ConnectionSet conns; - public INMGenProcessor[] processors; - } -} diff --git a/critterai/.svn/pristine/6b/6bf78c921fd678a3a98fae110af751c46408d08f.svn-base b/critterai/.svn/pristine/6b/6bf78c921fd678a3a98fae110af751c46408d08f.svn-base deleted file mode 100644 index e11df179..00000000 --- a/critterai/.svn/pristine/6b/6bf78c921fd678a3a98fae110af751c46408d08f.svn-base +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.geom -{ - /// - /// Provides various 3D triangle utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Triangle3 - { - /// - /// Returns the area of the triangle ABC. (Costly method!) - /// - /// - /// - /// Use GetAreaComp if the value is only needed - /// for comparison with other triangles. - /// - /// - /// Vertex A of triangle ABC. - /// Vertex B of triangle ABC. - /// Vertex C of triangle ABC. - /// The area of the triangle ABC. - public static float GetArea(Vector3 a, Vector3 b, Vector3 c) - { - return (float)(Math.Sqrt(GetAreaComp(a, b, c)) / 2); - } - - /// - /// Returns a value suitable for comparing the relative area of two triangles. (E.g. - /// Is triangle A larger than triangle B.) - /// - /// - /// - /// The value returned by this method can be converted to an area as follows: - /// Area = Math.sqrt(value) / 2 - /// - /// - /// Useful for cheaply comparing the size of triangles. - /// - /// - /// Vertex A of triangle ABC. - /// Vertex B of triangle ABC. - /// Vertex C of triangle ABC. - /// A value suitable for comparing the relative area of two triangles. - public static float GetAreaComp(Vector3 a, Vector3 b, Vector3 c) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - - // Get directional vectors. - - Vector3 u = b - a; // A -> B - Vector3 v = c - a; // A -> C - - // Cross product. - Vector3 n = new Vector3(u.y * v.z - u.z * v.y - , -u.x * v.z + u.z * v.x - , u.x * v.y - u.y * v.x); - - return Vector3Util.GetLengthSq(n); - } - - /// - /// Returns the normal for the triangle. (Costly method!) - /// - /// - /// - /// The normal of a triangle is the vector perpendicular to the triangle's plane - /// with the direction determined by the - /// - /// right-handed rule. - /// - /// - /// Vertex A of triangle ABC. - /// Vertex B of triangle ABC. - /// Vertex C of triangle ABC. - /// The normal of the triangle. - public static Vector3 GetNormal(Vector3 a, Vector3 b, Vector3 c) - { - // Reference: - // http://en.wikipedia.org/wiki/Surface_normal#Calculating_a_surface_normal - // N = (B - A) x (C - A) with the final result normalized. - - return Vector3Util.Normalize(Vector3Util.Cross(b - a, c - a)); - } - - /// - /// Returns the normal for the triangle. (Costly method!) - /// - /// - /// - /// The normal of a triangle is the vector perpendicular to the triangle's plane with - /// the direction determined by the right-handed rule. - /// - /// - /// - /// An array of vertices which contains a representation of triangles. The wrap direction - /// is expected to be clockwise. - /// - /// The index of the first vertex in the triangle. - /// The normal of the triangle. - public static Vector3 GetNormal(Vector3[] vertices, int triangle) - { - return GetNormal(vertices[triangle], vertices[triangle + 1], vertices[triangle + 2]); - } - } -} diff --git a/critterai/.svn/pristine/6b/6bf975518ce49127f595e5afcbf0f5b1a031c424.svn-base b/critterai/.svn/pristine/6b/6bf975518ce49127f595e5afcbf0f5b1a031c424.svn-base deleted file mode 100644 index 4a1630da..00000000 --- a/critterai/.svn/pristine/6b/6bf975518ce49127f595e5afcbf0f5b1a031c424.svn-base +++ /dev/null @@ -1,285 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; - -import org.junit.Before; -import org.junit.Test; - -/** - * Tests related to the OpenHeightSpan class. - */ -public class OpenHeightSpanTests -{ - - private static final int ROOT_REGION = 1; - private static final int AXIS_NEGIHBOR0_REGION = 100; - private static final int AXIS_NEGIHBOR1_REGION = 101; - private static final int AXIS_NEGIHBOR2_REGION = 102; - private static final int AXIS_NEGIHBOR3_REGION = 103; - private static final int DIAG_NEGIHBOR4_REGION = 104; - private static final int DIAG_NEGIHBOR5_REGION = 105; - private static final int DIAG_NEGIHBOR6_REGION = 106; - private static final int DIAG_NEGIHBOR7_REGION = 107; - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - private static final int UNUSED_REGION = 9972; - - private final OpenHeightSpan mRootSpan = new OpenHeightSpan(4, 9); - private final OpenHeightSpan mAxisNeighbor0 = new OpenHeightSpan(5, 10); - private final OpenHeightSpan mAxisNeighbor1 = new OpenHeightSpan(5, 11); - private final OpenHeightSpan mAxisNeighbor2 = new OpenHeightSpan(5, 12); - private final OpenHeightSpan mAxisNeighbor3 = new OpenHeightSpan(5, 13); - private final OpenHeightSpan mDiagNeighbor4 = new OpenHeightSpan(6, 14); - private final OpenHeightSpan mDiagNeighbor5 = new OpenHeightSpan(6, 15); - private final OpenHeightSpan mDiagNeighbor6 = new OpenHeightSpan(6, 16); - private final OpenHeightSpan mDiagNeighbor7 = new OpenHeightSpan(6, 17); - - private final int[] mMap = new int[10]; - - @Before - public void setUp() throws Exception - { - mRootSpan.setRegionID(ROOT_REGION); - mAxisNeighbor0.setRegionID(AXIS_NEGIHBOR0_REGION); - mAxisNeighbor1.setRegionID(AXIS_NEGIHBOR1_REGION); - mAxisNeighbor2.setRegionID(AXIS_NEGIHBOR2_REGION); - mAxisNeighbor3.setRegionID(AXIS_NEGIHBOR3_REGION); - mDiagNeighbor4.setRegionID(DIAG_NEGIHBOR4_REGION); - mDiagNeighbor5.setRegionID(DIAG_NEGIHBOR5_REGION); - mDiagNeighbor6.setRegionID(DIAG_NEGIHBOR6_REGION); - mDiagNeighbor7.setRegionID(DIAG_NEGIHBOR7_REGION); - - mRootSpan.setNeighbor(0, mAxisNeighbor0); - mRootSpan.setNeighbor(1, mAxisNeighbor1); - mRootSpan.setNeighbor(2, mAxisNeighbor2); - mRootSpan.setNeighbor(3, mAxisNeighbor3); - - mAxisNeighbor0.setNeighbor(1, mDiagNeighbor4); - mAxisNeighbor0.setNeighbor(2, mRootSpan); - mAxisNeighbor0.setNeighbor(3, mDiagNeighbor7); - - mAxisNeighbor1.setNeighbor(0, mDiagNeighbor4); - mAxisNeighbor1.setNeighbor(2, mDiagNeighbor5); - mAxisNeighbor1.setNeighbor(3, mRootSpan); - - mAxisNeighbor2.setNeighbor(0, mRootSpan); - mAxisNeighbor2.setNeighbor(1, mDiagNeighbor5); - mAxisNeighbor2.setNeighbor(3, mDiagNeighbor6); - - mAxisNeighbor3.setNeighbor(0, mDiagNeighbor7); - mAxisNeighbor3.setNeighbor(1, mRootSpan); - mAxisNeighbor3.setNeighbor(2, mDiagNeighbor6); - - mDiagNeighbor4.setNeighbor(2, mAxisNeighbor1); - mDiagNeighbor4.setNeighbor(3, mAxisNeighbor0); - - mDiagNeighbor5.setNeighbor(1, mAxisNeighbor1); - mDiagNeighbor5.setNeighbor(3, mAxisNeighbor2); - - mDiagNeighbor6.setNeighbor(0, mAxisNeighbor3); - mDiagNeighbor6.setNeighbor(2, mAxisNeighbor2); - - mDiagNeighbor7.setNeighbor(1, mAxisNeighbor0); - mDiagNeighbor7.setNeighbor(2, mAxisNeighbor3); - - // Corrupt the map. - for (int i = 0; i < 10; i++) - mMap[i] = UNUSED_REGION; - - } - - @Test - public void testGetDetailedRegionMapBase() - { - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN0() - { - mRootSpan.setNeighbor(0, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == NULL_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN1() - { - mRootSpan.setNeighbor(1, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == NULL_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN2() - { - mRootSpan.setNeighbor(2, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == NULL_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN3() - { - mRootSpan.setNeighbor(3, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == NULL_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN4() - { - mAxisNeighbor0.setNeighbor(1, null); - mAxisNeighbor1.setNeighbor(0, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == NULL_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN5() - { - mAxisNeighbor1.setNeighbor(2, null); - mAxisNeighbor2.setNeighbor(1, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == NULL_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN6() - { - mAxisNeighbor2.setNeighbor(3, null); - mAxisNeighbor3.setNeighbor(2, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == NULL_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN7() - { - mAxisNeighbor3.setNeighbor(0, null); - mAxisNeighbor0.setNeighbor(3, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == NULL_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachPartial() - { - mAxisNeighbor0.setNeighbor(1, null); - mAxisNeighbor0.setNeighbor(3, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - -} diff --git a/critterai/.svn/pristine/6c/6cb51bc63ce4ee0fbf33f1bbbe14c055a92e5c50.svn-base b/critterai/.svn/pristine/6c/6cb51bc63ce4ee0fbf33f1bbbe14c055a92e5c50.svn-base deleted file mode 100644 index 37e7d61c..00000000 --- a/critterai/.svn/pristine/6c/6cb51bc63ce4ee0fbf33f1bbbe14c055a92e5c50.svn-base +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmgen; -using org.critterai.nav; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Used to compile a set of off-mesh connections in a dynamic fashion. - /// - /// - /// - /// Used for dynamically building a set of off-mesh connections. - /// - /// - /// - public sealed class ConnectionSetCompiler - { - private readonly List mVerts; - private readonly List mRadii; - private readonly List mDirs; - private readonly List mAreas; - private readonly List mFlags; - private readonly List mUserIds; - - /// - /// The number of loaded connections. - /// - public int Count { get { return mRadii.Count; } } - - /// - /// Constructor. - /// - /// The initial capacity of the internal buffers. - public ConnectionSetCompiler(int initialCapacity) - { - mVerts = new List(initialCapacity); - mRadii = new List(initialCapacity); - mDirs = new List(initialCapacity); - mAreas = new List(initialCapacity); - mFlags = new List(initialCapacity); - mUserIds = new List(initialCapacity); - } - - /// - /// The connections in the set. - /// - /// - /// The index of the connection. [Limits: 0 <= value < ]. - /// - /// The connection. - public OffMeshConnection this[int index] - { - get - { - // Not using parameterized constructor. Don't need validation cost. - OffMeshConnection result = new OffMeshConnection(); - - result.start = mVerts[index * 2 + 0]; - result.end = mVerts[index * 2 + 1]; - result.radius = mRadii[index]; - result.direction = mDirs[index]; - result.flags = mFlags[index]; - result.area = mAreas[index]; - result.userId = mUserIds[index]; - - return result; - } - - set - { - // Must be validated. - // Let exceptions be thrown. - - mRadii[index] = MathUtil.ClampToPositiveNonZero(value.radius); - mDirs[index] = (byte)(value.IsBiDirectional ? 1 : 0); - mAreas[index] = NMGen.ClampArea(value.area); - mFlags[index] = value.flags; - mUserIds[index] = value.userId; - - // Keep verts last. - mVerts[index * 2 + 0] = value.start; - mVerts[index * 2 + 1] = value.end; - } - } - - /// - /// Add a connection. - /// - /// - /// - /// All values are auto-clamped to valid values. - /// - /// - /// The connection start point. - /// The connection end point. - /// The radius of the connection vertices. - /// True if the connection can be traversed in both - /// directions. (Start to end, end to start.) - /// The connection area id. - /// The connection flags. - /// The connection user id. - public void Add(Vector3 start, Vector3 end, float radius - , bool isBidirectional, byte area, ushort flags, uint userId) - { - mVerts.Add(start); - mVerts.Add(end); - mRadii.Add(System.Math.Max(MathUtil.Epsilon, radius)); - mDirs.Add((byte)(isBidirectional ? 1 : 0)); - mAreas.Add(NMGen.ClampArea(area)); - mFlags.Add(flags); - mUserIds.Add(userId); - } - - /// - /// Add a connection. - /// - /// - /// - /// The connection fields are auto-clamped to valid values. - /// - /// - /// The connection to add. - public void Add(OffMeshConnection connection) - { - // Must be validated. - mVerts.Add(connection.start); - mVerts.Add(connection.end); - mRadii.Add(MathUtil.ClampToPositiveNonZero(connection.radius)); - mDirs.Add((byte)(connection.IsBiDirectional ? 1 : 0)); - mAreas.Add(NMGen.ClampArea(connection.area)); - mFlags.Add(connection.flags); - mUserIds.Add(connection.userId); - } - - /// - /// Removes the connection at the specified index. - /// - /// The connection index. - public void RemoveAt(int index) - { - // Let exceptions be thrown. - - mRadii.RemoveAt(index); - mDirs.RemoveAt(index); - mAreas.RemoveAt(index); - mFlags.RemoveAt(index); - mUserIds.RemoveAt(index); - - // Keep last. - mVerts.RemoveAt(index * 2 + 1); - mVerts.RemoveAt(index * 2 + 0); - } - - /// - /// Resets the compiler to zero connections. - /// - public void Reset() - { - mVerts.Clear(); - mRadii.Clear(); - mDirs.Clear(); - mAreas.Clear(); - mFlags.Clear(); - mUserIds.Clear(); - } - - /// - /// Creates a thread-safe, immutable, fully validated connection set from the - /// connections. - /// - /// A conneciton set created from the connections. - public ConnectionSet CreateConnectionSet() - { - if (mVerts.Count == 0) - return ConnectionSet.CreateEmpty(); - - Vector3[] lverts = mVerts.ToArray(); - float[] lradii = mRadii.ToArray(); - byte[] ldirs = mDirs.ToArray(); - byte[] lareas = mAreas.ToArray(); - ushort[] lflags = mFlags.ToArray(); - uint[] lids = mUserIds.ToArray(); - - if (ConnectionSet.IsValid(lverts, lradii, ldirs, lareas, lflags, lids)) - { - return ConnectionSet.UnsafeCreate(mVerts.ToArray() - , mRadii.ToArray() - , mDirs.ToArray() - , mAreas.ToArray() - , mFlags.ToArray() - , mUserIds.ToArray()); - } - - return null; - } - } -} diff --git a/critterai/.svn/pristine/6c/6ceb11ecc65c09f5ef2722a12c303a19bd10bfe9.svn-base b/critterai/.svn/pristine/6c/6ceb11ecc65c09f5ef2722a12c303a19bd10bfe9.svn-base deleted file mode 100644 index c081f5c2..00000000 Binary files a/critterai/.svn/pristine/6c/6ceb11ecc65c09f5ef2722a12c303a19bd10bfe9.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/6c/6cec641411dd7d6f79fe84febf12a120afd66486.svn-base b/critterai/.svn/pristine/6c/6cec641411dd7d6f79fe84febf12a120afd66486.svn-base deleted file mode 100644 index c2ea4e68..00000000 --- a/critterai/.svn/pristine/6c/6cec641411dd7d6f79fe84febf12a120afd66486.svn-base +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Text; -using org.critterai.nmgen.rcn; - -namespace org.critterai.nmgen -{ - /// - /// Provides logging functionality. - /// - /// - /// - /// This class can be used as a base for a more complete build context. - /// - /// - /// The message buffer can hold a maximum of 1000 messages comprised of 64K characters. - /// Any messages added after the buffer limit is reached will be ignored. - /// - /// - public class BuildContext - { - /// - /// The message prefix used for informational messages. - /// - public const string InfoLabel = "INFO"; - - /// - /// The message prefix used for error messages. - /// - public const string ErrorLabel = "ERROR"; - - /// - /// The message prefix used for warning messages. - /// - public const string WarningLabel = "WARNING"; - - private const int MessagePoolSize = 65536; - - internal IntPtr root = IntPtr.Zero; - - /// - /// The number of messages in the buffer. [Limit: <= 1000] - /// - public int MessageCount - { - get { return BuildContextEx.nmbcGetMessageCount(root); } - } - - /// - /// Constructor. - /// - public BuildContext() - { - root = BuildContextEx.nmbcAllocateContext(true); - } - - /// - /// Destructor. - /// - ~BuildContext() - { - if (root != IntPtr.Zero) - { - BuildContextEx.nmbcFreeContext(root); - root = IntPtr.Zero; - } - } - - /// - /// Clears all messages from the message buffer. - /// - public void ResetLog() - { - BuildContextEx.nmbcResetLog(root); - } - - /// - /// Posts an informational message to the message buffer. - /// - /// The message to post. - /// The context of the message. (Optional) - public void Log(string message, Object context) - { - Log(InfoLabel, message, context); - } - - /// - /// Appends log messages to the current context. - /// - /// The messages to append. - public void Log(string[] messages) - { - if (messages == null || messages.Length == 0) - return; - - foreach (string msg in messages) - { - BuildContextEx.nmbcLog(root, msg); - } - } - - /// - /// Posts a message to the message buffer with a custom category. - /// - /// The message category. - /// The message to post. - /// The context of the message. (Optional) - public void Log(string category, string message, Object context) - { - if (message != null && message.Length > 0) - { - BuildContextEx.nmbcLog(root, string.Format("{0}: {1}{2}" - , category, message, ContextPart(context))); - } - } - - /// - /// Posts a warning message to the message buffer. - /// - /// The message to post. - /// The context of the message. (Optional) - public void LogWarning(string message, Object context) - { - Log(WarningLabel, message, context); - } - - /// - /// Posts an error message to the message buffer. - /// - /// The message to post. - /// The context of the message. (Optional) - public void LogError(string message, Object context) - { - Log(ErrorLabel, message, context); - } - - /// - /// Gets all messages in the message buffer. - /// - /// - /// - /// The length of the result will always equal . - /// - /// - /// - /// All messages in the message buffer, or a zero length array if there are no messages. - /// - public string[] GetMessages() - { - byte[] buffer = new byte[MessagePoolSize]; - - int messageCount = BuildContextEx.nmbcGetMessagePool(root - , buffer - , buffer.Length); - - if (messageCount == 0) - return new string[0]; - - string aggregateMsg = - ASCIIEncoding.ASCII.GetString(buffer); - char[] delim = { '\0' }; - return aggregateMsg.Split(delim - , StringSplitOptions.RemoveEmptyEntries); - } - - /// - /// Gets all messages in the message buffer as a single, new line delimited string. - /// - /// The messages in the message buffer. - public string GetMessagesFlat() - { - string[] msgs = GetMessages(); - - if (msgs.Length == 0) - return ""; - - StringBuilder sb = new StringBuilder(); - - foreach (string msg in msgs) - { - sb.AppendLine(msg); - } - - return sb.ToString(); - } - - /// - /// Appends messages from the specified context to the current context. - /// - /// The context to append the messages from. - public void AppendMessages(BuildContext fromContext) - { - if (fromContext == null || fromContext.MessageCount == 0) - return; - - string[] msgs = fromContext.GetMessages(); - foreach (string msg in msgs) - { - BuildContextEx.nmbcLog(root, msg); - } - } - - private static string ContextPart(Object context) - { - return (context == null ? "" : " (" + context.GetType().Name + ")"); - } - - /// - /// Tests the operation of the context by adding up to 100 test messages. - /// - /// - /// - /// The only purpose of this method is to permit testing. - /// - /// The context to test. - /// The number of messages to add. (Limit <100) - public static void LoadTestMessages(BuildContext context, int count) - { - if (context != null) - BuildContextEx.nmgTestContext(context.root, Math.Min(100, count)); - } - - } -} diff --git a/critterai/.svn/pristine/6d/6d3ada8af7c46aff97b62aaf95547006b7ce3f58.svn-base b/critterai/.svn/pristine/6d/6d3ada8af7c46aff97b62aaf95547006b7ce3f58.svn-base deleted file mode 100644 index 15f733ad..00000000 --- a/critterai/.svn/pristine/6d/6d3ada8af7c46aff97b62aaf95547006b7ce3f58.svn-base +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.interop; -using org.critterai.nmgen.rcn; - -namespace org.critterai.nmgen -{ - /// - /// A heightfield layer set built from a - /// . - /// - /// - /// - /// Undocumented: Equivalent to Recast: rcHeightfieldLayerSet. - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - public sealed class HeightfieldLayerSet - : IManagedObject - { - private IntPtr root; - private HeightfieldLayer[] mLayers; - private int mLayerCount; - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return (root == IntPtr.Zero); } } - - /// - /// The type of unmanaged resources within the object. - /// - public AllocType ResourceType { get { return AllocType.External; } } - - /// - /// The number of layers in the set. - /// - public int LayerCount { get { return mLayerCount; } } - - private HeightfieldLayerSet(IntPtr root, int layerCount) - { - this.root = root; - mLayerCount = layerCount; - mLayers = new HeightfieldLayer[layerCount]; - - for (int i = 0; i < mLayerCount; i++) - { - HeightfieldLayer layer = new HeightfieldLayer(); - HeightfieldLayserSetEx.nmlsGetLayer(root, i, layer); - mLayers[i] = layer; - } - } - - /// - /// Destructor. - /// - ~HeightfieldLayerSet() - { - RequestDisposal(); - } - - /// - /// Frees and marks as disposed all resoures associated with the object. - /// (Including its objects.) - /// - public void RequestDisposal() - { - if (!IsDisposed) - { - HeightfieldLayserSetEx.nmlsFreeLayers(root); - root = IntPtr.Zero; - mLayerCount = 0; - for (int i = 0; i < mLayers.Length; i++) - { - mLayers[i].Reset(); - } - } - } - - /// - /// Gets the specified layser. - /// - /// The layer. [Limit: 0 <= value < LayerCount] - /// The layer, or null on error. - public HeightfieldLayer GetLayer(int index) - { - if (IsDisposed || index < 0 || index >= mLayerCount) - return null; - - return mLayers[index]; - } - - /// - /// Builds a layer set from the . - /// - /// The context to use duing the operation. - /// The source field. - /// The resulting layer set, or null on failure. - public static HeightfieldLayerSet Build(BuildContext context, CompactHeightfield field) - { - if (context == null) - return null; - - IntPtr ptr = IntPtr.Zero; - - int layerCount = HeightfieldLayserSetEx.nmlsBuildLayers(context.root - , field - , field.BorderSize - , field.WalkableHeight - , ref ptr); - - if (ptr == IntPtr.Zero) - return null; - - return new HeightfieldLayerSet(ptr, layerCount); - } - } -} diff --git a/critterai/.svn/pristine/6d/6dc633cd766968a616910140bea7e33a1740acd3.svn-base b/critterai/.svn/pristine/6d/6dc633cd766968a616910140bea7e33a1740acd3.svn-base deleted file mode 100644 index 2c02f158..00000000 --- a/critterai/.svn/pristine/6d/6dc633cd766968a616910140bea7e33a1740acd3.svn-base +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.u3d; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal class TileGridDebugView - { - private bool mEnabled; - private bool mShow; - private bool mNeedsRepaint; - private float mYOffset; - - public float YOffset - { - get { return mYOffset; } - set - { - if (mYOffset != value) - { - mYOffset = Mathf.Clamp01(value); - mNeedsRepaint = true; - } - } - } - - public bool NeedsRepaint - { - get { return mNeedsRepaint; } - set { mNeedsRepaint = value; } - } - - public bool Enabled - { - get { return mEnabled; } - set - { - if (mEnabled != value) - { - mEnabled = value; - mNeedsRepaint = true; - } - } - } - - public bool Show - { - get { return mShow; } - set - { - if (mShow != value) - { - mShow = value; - mNeedsRepaint = true; - } - } - } - - public void OnRenderObject(NavmeshBuild build) - { - if (!build || !(mEnabled && mShow && build.HasInputData)) - return; - - Vector3 whd; - Vector3 origin; - int gridWidth; - int gridDepth; - - float tileWorldSize = build.Config.TileWorldSize; - TileSetDefinition tdef = build.TileSetDefinition; - - if (tdef != null) - { - // Use the real grid. - origin = tdef.BoundsMin; - whd = tdef.BoundsMax - tdef.BoundsMin; - gridWidth = tdef.Width; - gridDepth = tdef.Depth; - } - else if (build.HasInputData) - { - // Estimate from the input geometry. - InputGeometry geom = build.InputGeom; - origin = geom.BoundsMin; - whd = geom.BoundsMax - geom.BoundsMin; - gridWidth = Mathf.CeilToInt(whd.x / tileWorldSize); - gridDepth = Mathf.CeilToInt(whd.z / tileWorldSize); - } - else - // Don't have the needed data. - return; - - origin.y += whd.y * mYOffset; - - if (build.Config.TileSize >= NavmeshBuild.MinAllowedTileSize) - DebugDraw.Grid(origin, tileWorldSize, gridWidth, gridDepth, Color.gray); - else - // Single tile. - DebugDraw.Rect(origin, whd.x, whd.z, Color.gray, false); - } - } -} diff --git a/critterai/.svn/pristine/6f/6f31f45cbeaf6da80c274453c6b25b69a71c6fc7.svn-base b/critterai/.svn/pristine/6f/6f31f45cbeaf6da80c274453c6b25b69a71c6fc7.svn-base deleted file mode 100644 index a25f6dbf..00000000 --- a/critterai/.svn/pristine/6f/6f31f45cbeaf6da80c274453c6b25b69a71c6fc7.svn-base +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - The navigation mesh query is the most important class to understand since most navigation clients will interact with the query - rather than the navigation mesh itself. The mesh contains the data, but the query provides almost all of the features - necessary for pathfinding. - - - - Core Class: NavmeshQuery - - - - Query features fall into two general categories: Pathfinding and local search. - - - - Pathfinding involves standard A* and Dijkstra searches that find the best path(s) between two points. Paths are made up of - a list polygon references that represent a polygon corridor from the start to the end position. Path straightening is used to - convert the path into a list of waypoints. (I.e. String pulling.) - - - - The local search features offer various methods for locating polygons and points on polygons, and for querying - the local environment. I.e. Raycasting, finding the distance to the nearest wall, etc. - - - - Many of the query methods require a NavmeshQueryFilter. Filters define area traversal costs as well as flags - used for including/excluding polygons and off-mesh connections from results. - - - - The best way to understand the query class is to play around with it. The CAINavExplorerDownload includes the Query Explorer - demo that permits experimentation with all of the main query features. - - - - -
- - Common Operations - - - - - This section contains some simple examples of common query operations. - - -
- - Finding a Point in the Navigation Mesh - - - - - You can't do much without first getting a valid point on the navigation mesh. So the first step is to find one. - - - - - M:org.critterai.nav.NavmeshQuery.GetNearestPoint(UnityEngine.Vector3,UnityEngine.Vector3,org.critterai.nav.NavmeshQueryFilter,org.critterai.nav.NavmeshPoint@) - - - - - - // Where 'query' is a NavmeshQuery object and 'filter' is a NavmeshQueryFilter object. - // 'position' is a Vector3 indicating the world position of the client. - - NavmeshPoint result; - Vector3 extents = new Vector3(1, 1, 1); // Keep this to the minimum extents practical. - - NavStatus status = query.GetNearestPoly(position, extents, filter - , out result); - - if (result.polyRef == Navmesh.NullPoly) - { - // Handle error. Could not find a result. - // The status can be checked to see if there was an error. If not, then - // the cause is that the search extents did not overlap any polygons. - } - - // Use the result point, which includes a vector point and the reference of - // the polygon that contains the point. - - - - - -
- -
- - Basic Pathfinding - - - - - Even if you are planning to use PathCorridor or CrowdManager, - you'll always need to do long distance planning using the basic NavmeshQuery features. - First, get a path, then optionally straighten it. - - - - - // Where 'query' is a NavmeshQuery object and 'filter' is a NavmeshQueryFilter object. - // 'start' and 'end' are NavmeshPoints known to be on the navigation mesh. - - int pathCount; - // The path will be a list of polygon references. - uint[] path = new uint[100]; // Size for maximum allowed path length. - NavStatus status; - - if (start.polyRef == end.polyRef) - { - // No need to do any planning. - pathCount = 1; - path[0] = start.polyRef; - } - else - { - status = query.FindPath(start, end, filter, path - , out pathCount); - - if (NavUtil.Failed(status) || path.pathCount == 0) - { - // Handle pathfinding failure. - } - else if (end.polyRef != path[pathCount - 1]) - { - // Handle a partial path. - // The query either could not reach the end point, - // or the path buffer was too small to hold the - // entire path. (A check of 'status' will reveal if - // the buffer was too small.) - } - - } - - // If you need to straighten the path... - - const int MaxStraightPath = 4; // Just getting the first 4 waypoints. - int wpCount; - - // The waypoints. - Vector3[] wpPoints = new Vecotr3[MaxStraightPath]; - - // A list of polygon references. (The polygon being entered at each waypoint.) - uint[] wpPath = new uint[MaxStraightPath]; - - // The type of each waypoint. (Start, end, off-mesh connection.) - WaypointFlag[] wpFlags = new WaypointFlag[MaxStraightPath]; - - status = query.GetStraightPath(start.point - , goal.point - , path - , 0 // The index of the start of the path. - , pathCount // The length of the path. - , wpPoints - , wpFlags - , wpPath - , out wpCount); - - if (NavUtil.Failed(status) || wpCount == 0) - { - // Handle the failure. There should always be at least one waypoint - // (the goal) for a valid point/path combination, - } - - // Use the path and waypoints. - - - - - -
- -
- -
- - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshQueryFilter - - - - - - - - -
-
\ No newline at end of file diff --git a/critterai/.svn/pristine/6f/6fe7122af063cb37904b8abc1fb653c65c9f8a2f.svn-base b/critterai/.svn/pristine/6f/6fe7122af063cb37904b8abc1fb653c65c9f8a2f.svn-base deleted file mode 100644 index 9951dcd0..00000000 --- a/critterai/.svn/pristine/6f/6fe7122af063cb37904b8abc1fb653c65c9f8a2f.svn-base +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Mesh colocation options. (Editor Only) - /// - public enum MeshColocationOption - { - /// - /// Always compile the mesh filter. (Ignore colliders.) - /// - MeshFilter, - - /// - /// Compile supported collider, if one exists. (Collider is preferred.) - /// - Collider - } -} diff --git a/critterai/.svn/pristine/70/7020d98306687eff3c0ccd7e0c67d33f4638bbf4.svn-base b/critterai/.svn/pristine/70/7020d98306687eff3c0ccd7e0c67d33f4638bbf4.svn-base deleted file mode 100644 index 1e40f4aa..00000000 --- a/critterai/.svn/pristine/70/7020d98306687eff3c0ccd7e0c67d33f4638bbf4.svn-base +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.interop; -using org.critterai.nmgen.rcn; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -// Unity is improperly indicating that mSpan is unused. -#pragma warning disable 414 - -namespace org.critterai.nmgen -{ - /// - /// Provides a representation of the open (unobstructed) space above the solid surfaces of - /// a voxel field. - /// - /// - /// - /// For this type of heightfield, the spans represent the floor and ceiling of the open spaces. - /// - /// - /// Data is stored in a compact, efficient manner. - /// - /// - /// The following process can be used to iterate spans: - /// - /// - /// int w = chf.Width; - /// int d = chf.Depth; - /// - /// CompactCell[] cells = new CompactCell[w * d]; - /// chf.GetCellData(cells); - /// - /// CompactSpan[] spans = new CompactSpan[chf.SpanCount]; - /// chf.GetSpanData(spans); - /// - /// for (int z = 0; z < d; ++z) - /// { - /// for (int x = 0; x < w; ++x) - /// { - /// CompactCell c = cells[x + z * w]; - /// for (int i = (int)c.Index, ni = (int)(c.Index + c.Count) - /// ; i < ni - /// ; ++i) - /// { - /// CompactSpan s = spans[i]; - /// - /// // Do something... - /// - /// // If you have extracted area and distance data, you - /// // can access it with the same index. - /// // E.g. areas[i] or distance[i]. - /// - /// // To access neighbor information... - /// - /// for (int dir = 0; dir < 4; ++dir) - /// { - /// if (s.GetConnection(dir) != CompactSpan.NotConnected) - /// { - /// int nx = x + CompactSpan.GetDirOffsetX(dir); - /// int nz = z + CompactSpan.GetDirOffsetZ(dir); - /// int ni = (int)cells[ax + az * w].Index - /// + s.GetConnection(dir); - /// - /// // ni represents the index of the neighbor. - /// // So spans[ni], areas[ni], directions[ni] - /// // gets the neighbor. - /// } - /// } - /// } - /// } - /// } - /// - /// - /// Spans contain neighbor connection data that can be used to locate axis-neighbors. - /// Axis neighbors are spans that are offset from the current cell column as follows: - /// - /// - /// Direction 0 = (-1, 0)
- /// Direction 1 = (0, 1)
- /// Direction 2 = (1, 0)
- /// Direction 3 = (0, -1) - ///
- /// - /// These standard offset can be obtained from the - /// and methods. - /// - /// - /// See the earlier example code for information on how to use connection information. - /// - /// - /// Behavior is undefined if used after disposal. - /// - ///
- [StructLayout(LayoutKind.Sequential)] - public sealed class CompactHeightfield - : IManagedObject - { - private int mWidth = 0; - private int mDepth = 0; - private int mSpanCount = 0; - private int mWalkableHeight = 0; - private int mWalkableStep = 0; - private int mBorderSize = 0; - private ushort mMaxDistance = 0; - private ushort mMaxRegions = 0; - - private Vector3 mBoundsMin; - - private Vector3 mBoundsMax; - - private float mXZCellSize = 0; - private float mYCellSize = 0; - private IntPtr mCells = IntPtr.Zero; // rcCompactCell[width*depth] - private IntPtr mSpans = IntPtr.Zero; // rcCompactSpan[spanCount] - private IntPtr mDistanceToBorder = IntPtr.Zero; // ushort[spanCount] - private IntPtr mAreas = IntPtr.Zero; // byte[spanCount] - - /// - /// The width of the heightfield. (Along the x-axis in cell units.) - /// - public int Width { get { return mWidth; } } - - /// - /// The depth of the heighfield. (Along the z-axis in cell units.) - /// - public int Depth { get { return mDepth; } } - - /// - /// The minimum bounds of the heightfield in world space. - /// - /// The minimum bounds of the heighfield. - public Vector3 BoundsMin { get { return mBoundsMin; } } - - /// - /// The maximum bounds of the heightfield in world space. - /// - /// The maximum bounds of the heightfield. - public Vector3 BoundsMax { get { return mBoundsMax; } } - - /// - /// The width/depth size of each cell. (On the xz-plane.) - /// - /// - /// - /// The smallest span can be XZCellSize width * XZCellSize depth * YCellSize height. - /// - /// - /// A width or depth value within the field can be converted to world units as follows: - /// - /// - /// boundsMin[0] + (width * XZCellSize) - /// boundsMin[2] + (depth * XZCellSize) - /// - /// - public float XZCellSize { get { return mXZCellSize; } } - - /// - /// The height increments for span data. (On the y-axis.) - /// - /// - /// - /// The smallest span can be - /// (XZCellSize width * XZCellSize depth * YCellSize) height. - /// - /// - /// A height within the field is converted to world units as follows: - /// - /// boundsMin[1] + (height * YCellSize) - /// - /// - public float YCellSize { get { return mYCellSize; } } - - /// - /// The number of spans in the field. - /// - public int SpanCount { get { return mSpanCount; } } - - /// - /// The walkable height used during the build of the field. - /// - public int WalkableHeight { get { return mWalkableHeight; } } - - /// - /// The walkable step used during the build of the field. - /// - public int WalkableStep { get { return mWalkableStep; } } - - /// - /// The AABB border size used during the build of the field. - /// - public int BorderSize { get { return mBorderSize; } } - - /// - /// The maximum distance value for any span within the field. - /// - /// - /// - /// The value is only useful if the distance field has been built. - /// - /// - public ushort MaxDistance { get { return mMaxDistance; } } - - /// - /// The maximum region id for any span within the field. - /// - /// - /// - /// The value is only useful if the regions have been built. - /// - /// - public ushort MaxRegion { get { return mMaxRegions; } } - - /// - /// The type of unmanaged resources within the object. - /// - public AllocType ResourceType { get { return AllocType.External; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return (mCells == IntPtr.Zero); } } - - private CompactHeightfield() { } - - /// - /// Destructor. - /// - ~CompactHeightfield() - { - RequestDisposal(); - } - - /// - /// Frees all unmanaged resources controlled by the object and marks it as disposed. - /// - public void RequestDisposal() - { - if (!IsDisposed) - { - CompactHeightfieldEx.nmcfFreeFieldData(this); - mWidth = 0; - mDepth = 0; - mBorderSize = 0; - mBoundsMin = Vector3Util.Zero; - mBoundsMax = Vector3Util.Zero; - mMaxDistance = 0; - mMaxRegions = 0; - mSpanCount = 0; - mWalkableHeight = 0; - mWalkableStep = 0; - mXZCellSize = 0; - mYCellSize = 0; - } - } - - /// - /// Loads the heighfield's data into the provided buffer. - /// - /// The buffer to load the data into. [Size: >= Width * Depth] - /// True if the buffer was successfully loaded. - public bool GetCellData(CompactCell[] buffer) - { - if (IsDisposed) - return false; - - return CompactHeightfieldEx.nmcfGetCellData(this - , buffer - , buffer.Length); - } - - /// - /// Loads the heightfield's data into the provided buffer. - /// - /// The buffer to load the data into. [Size: >= SpanCount] - /// True if the buffer was successfully loaded. - public bool GetSpanData(CompactSpan[] buffer) - { - if (IsDisposed) - return false; - - return CompactHeightfieldEx.nmcfGetSpanData(this - , buffer - , buffer.Length); - } - - /// - /// Loads the heightfield's distance field data into the provided buffer. - /// - /// - /// - /// This data is only available after the distance field has been built. - /// - /// - /// Each value represents the estimated distance of the span from the nearest - /// boundary/obstruction. The index is the same as for the span data. - /// E.g. span[i], distance[i] - /// - /// - /// The buffer to load the data into. [Size: >= SpanCount] - /// True if the buffer was successfully loaded. - public bool GetDistanceData(ushort[] buffer) - { - if (IsDisposed - || mDistanceToBorder == IntPtr.Zero - || buffer.Length < mSpanCount) - { - return false; - } - - UtilEx.Copy(mDistanceToBorder - , buffer - , mSpanCount); - - return true; - } - - /// - /// Loads the heightfield's area data into the provided buffer. - /// - /// - /// - /// Each value represents the id of the area the span belongs to. The index is the same - /// as for the span data. E.g. span[i], area[i] - /// - /// - /// The buffer to load the data into. [Size: >= SpanCount] - /// True if the buffer was successfully loaded. - public bool GetAreaData(byte[] buffer) - { - if (IsDisposed || buffer.Length < mSpanCount) - return false; - - Marshal.Copy(mAreas - , buffer - , 0 - , mSpanCount); - - return true; - } - - /// - /// True if distance data is available. - /// - public bool HasDistanceData - { - get { return (mDistanceToBorder != IntPtr.Zero); } - } - - /// - /// Erodes the walkable area within the heightfield by the specified radius. - /// - /// - /// - /// Basically, any spans that are closer to a boundary or obstruction than the specified - /// radius are marked as unwalkable. - /// - /// - /// This method is usually called immediately after the heightfield has been created. - /// - /// - /// The context to use during the operation. - /// The radius to apply. [Units: Spans] - /// True if the operation completed successfully. - public bool ErodeWalkableArea(BuildContext context, int radius) - { - if (IsDisposed) - return false; - return CompactHeightfieldEx.nmcfErodeWalkableArea(context.root - , radius - , this); - } - - /// - /// Applies a median filter to the walkable areas. (Removes noise.) - /// - /// The context to use duing the operation. - /// True if the operation completed successfully. - public bool ApplyMedianFilter(BuildContext context) - { - if (IsDisposed) - return false; - return CompactHeightfieldEx.nmcfMedianFilterWalkableArea(context.root, this); - } - - /// - /// Applies the area to all spans within the specified bounding box. (AABB) - /// - /// - /// - /// The method will return false if the AABB is completely outside of the heightfield. - /// - /// - /// The context to use duing the operation. - /// The minimum bounds of the AABB. - /// The maximum bounds of the AABB. - /// The area to apply. - /// True if the operation completed successfully. - public bool MarkBoxArea(BuildContext context - , Vector3 boundsMin, Vector3 boundsMax - , byte area) - { - if (IsDisposed) - return false; - - return CompactHeightfieldEx.nmcfMarkBoxArea(context.root - , ref boundsMin - , ref boundsMax - , area - , this); - } - - /// - /// Applies the area to the all spans within the specified convex polygon. - /// - /// - /// - /// The y-values of the polygon vertices are ignored. So the polygon is effectively - /// projected onto the xz-plane at yMin, then extruded to yMax. - /// - /// - /// The method will return false if the polygon is completely outside of the heightfield. - /// - /// - /// The context to use duing the operation. - /// The vertices of the polygon [Length: vertCount] - /// The height of the base of the polygon. - /// The height of the top of the polygon. - /// The area to apply. - /// True if the operation completed successfully. - public bool MarkConvexPolyArea(BuildContext context - , Vector3[] verts, float yMin, float yMax - , byte area) - { - if (IsDisposed) - return false; - return CompactHeightfieldEx.nmcfMarkConvexPolyArea(context.root - , verts - , verts.Length - , yMin - , yMax - , area - , this); - } - - /// - /// Applied the area to all spans within the specified cylinder. - /// - /// - /// - /// The method will return false if the cylinder is completely outside of the heightfield. - /// - /// - /// The context to use duing the operation. - /// The center of the base of the cylinder. - /// The radius of the cylinder. - /// The height of the cylinder. - /// The area to apply. - /// True if the operation completed successfully. - public bool MarkCylinderArea(BuildContext context - , Vector3 centerBase, float radius, float height - , byte area) - { - if (IsDisposed) - return false; - return CompactHeightfieldEx.nmcfMarkCylinderArea(context.root - , ref centerBase - , radius - , height - , area - , this); - } - - /// - /// Builds the distance field for the heightfield. - /// - /// - /// - /// This method must be called before attempting to build region data. - /// - /// - /// The distance data is avaiable via and - /// . - /// - /// - /// The context to use duing the operation. - /// True if the operation completed successfully. - public bool BuildDistanceField(BuildContext context) - { - if (IsDisposed) - return false; - return CompactHeightfieldEx.nmcfBuildDistanceField(context.root, this); - } - - /// - /// Builds region data for the heightfield using watershed partitioning. - /// - /// - /// - /// Non-null regions consist of connected, non-overlapping walkable spans that form a - /// single contour. - /// - /// - /// The region data is available via and . - /// - /// - /// If a region forms an area that is smaller than , - /// all spans in the region is set to . - /// - /// - /// Watershed partitioning can result in smaller than necessary regions, especially - /// in diagonal corridors. helps reduce unecessarily - /// small regions. - /// - /// - /// The context to use duing the operation. - /// The AABB border size to apply. - /// - /// The minimum area allowed for unconnected (island) regions. [Units: Spans] - /// - /// - /// The maximum region size that will be considered for merging with another region. - /// [Units: Spans] - /// - /// True if the operation completed successfully. - public bool BuildRegions(BuildContext context - , int borderSize, int minRegionArea, int mergeRegionArea) - { - if (IsDisposed) - return false; - return CompactHeightfieldEx.nmcfBuildRegions(context.root - , this - , borderSize - , minRegionArea - , mergeRegionArea); - } - - /// - /// Builds region data for the heightfield using simple monotone partitioning. - /// - /// - /// - /// Non-null regions consist of connected, non-overlapping walkable spans that form a - /// single contour. - /// - /// - /// The region data is available via and . - /// - /// - /// If a region forms an area that is smaller than , - /// all spans in the region is set to . - /// - /// - /// Partitioning can result in smaller than necessary regions, especially - /// in diagonal corridors. helps reduce unecessarily - /// small regions. - /// - /// - /// The context to use duing the operation. - /// The AABB border size to apply. - /// - /// The minimum area allowed for unconnected (island) regions. [Units: Spans] - /// - /// - /// The maximum region size that will be considered for merging with another region. - /// [Units: Spans] - /// - /// True if the operation completed successfully. - public bool BuildRegionsMonotone(BuildContext context - , int borderSize, int minRegionArea, int mergeRegionArea) - { - if (IsDisposed) - return false; - - return CompactHeightfieldEx.nmcfBuildRegionsMonotone(context.root - , this - , borderSize - , minRegionArea - , mergeRegionArea); - } - - /// - /// Creates a compact open heightfield from a solid heightfield. - /// - /// The context to use duing the operation. - /// - /// The solid heighfield to derive the compact heightfield from. - /// - /// - /// The minimum floor to ceiling height that is still considered walkable. - /// [Limit: >= ] - /// - /// - /// The maximum floor to floor step that is still considered walkable. - /// True if the operation completed successfully. - public static CompactHeightfield Build(BuildContext context - , Heightfield sourceField - , int walkableHeight - , int walkableStep) - { - if (context == null - || sourceField == null || sourceField.IsDisposed - || walkableHeight < NMGen.MinWalkableHeight - || walkableStep < 0) - { - return null; - } - - CompactHeightfield field = new CompactHeightfield(); - - if (CompactHeightfieldEx.nmcfBuildField(context.root - , walkableHeight - , walkableStep - , sourceField.root - , field)) - { - return field; - } - - return null; - } - - } -} - -#pragma warning restore 414 \ No newline at end of file diff --git a/critterai/.svn/pristine/70/705285ed0e82342a49b080fbd957530254d3dad1.svn-base b/critterai/.svn/pristine/70/705285ed0e82342a49b080fbd957530254d3dad1.svn-base deleted file mode 100644 index b2b7bb47..00000000 Binary files a/critterai/.svn/pristine/70/705285ed0e82342a49b080fbd957530254d3dad1.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/70/708be63eb501607b77fc90cb631bffdcad975b45.svn-base b/critterai/.svn/pristine/70/708be63eb501607b77fc90cb631bffdcad975b45.svn-base deleted file mode 100644 index 712b3e4e..00000000 --- a/critterai/.svn/pristine/70/708be63eb501607b77fc90cb631bffdcad975b45.svn-base +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nav; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.nmgen; -using UnityEngine; - -/// -/// Defines a mapping between areas and flags and applies the flags during the NMGen build process. -/// (Editor Only) -/// -/// -/// -/// Any polygon or off-mesh connection assigned to one of the defined areas will have the -/// associated flags added. E.g. The 'water' area gets the 'swim' flag. -/// -/// -/// The flags are applied to polygons during the NMGen build, and to -/// off-mesh connections during input post-processing. -/// -/// -[System.Serializable] -public sealed class AreaFlagDef - : ScriptableObject, IInputBuildProcessor -{ - /// - /// Flags to associate with areas. - /// - public List flags; - - /// - /// The area associated with the flags. - /// - public List areas; - - [SerializeField] - private int mPriority = NMBuild.DefaultPriority; - - /// - /// The priority of the processor. - /// - public int Priority { get { return mPriority; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// Sets the priority. - /// - /// The new priority. - public void SetPriority(int value) - { - mPriority = NMBuild.ClampPriority(value); - } - - /// - /// Duplicates allowed. (Always true.) - /// - public bool DuplicatesAllowed { get { return true; } } - - /// - /// Processes the context. - /// - /// - /// - /// Applied during the and - /// states. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (state == InputBuildState.CompileInput) - return ProcessCompile(context); - - if (state == InputBuildState.PostProcess) - return ProcessPost(context); - - return true; - } - - private bool ProcessPost(InputBuildContext context) - { - if (!ProcessValidation(context)) - return false; - - context.info.postCount++; - - if (areas.Count == 0) - { - context.Log("No area/flag maps. No action taken.", this); - return true; - } - - ConnectionSetCompiler conns = context.connCompiler; - - bool applied = false; - - for (int i = 0; i < areas.Count; i++) - { - byte area = areas[i]; - ushort flag = (ushort)flags[i]; - - int marked = 0; - - for (int iConn = 0; iConn < conns.Count; iConn++) - { - OffMeshConnection conn = conns[iConn]; - - if (conn.area == area) - { - conn.flags |= flag; - conns[iConn] = conn; - marked++; - } - } - - if (marked > 0) - { - string msg = string.Format( - "Added '0x{0:X}' flags to {1} connections with the area {2}." - , flag, marked, area); - - context.Log(msg, this); - - applied = true; - } - } - - if (!applied) - context.Log("No flags applied.", this); - - return true; - } - - private bool ProcessValidation(InputBuildContext context) - { - if (flags == null || areas == null || flags.Count != areas.Count) - { - context.Log("Area/Flag size error. (Invalid processor state.)", this); - return false; - } - return true; - } - - private bool ProcessCompile(InputBuildContext context) - { - if (!ProcessValidation(context)) - return false; - - context.info.compilerCount++; - - if (areas.Count == 0) - { - context.Log("No area/flag maps. No action taken.", this); - return true; - } - - ushort[] sflags = new ushort[flags.Count]; - - for (int i = 0; i < sflags.Length; i++) - { - // The editor should prevent overflows. - sflags[i] = (ushort)flags[i]; - } - - AreaFlagMapper mapper = AreaFlagMapper.Create(name, Priority, areas.ToArray(), sflags); - - if (mapper == null) - { - context.LogError("Failed to create NMGen processor. Unexpected invalid data.", this); - return false; - } - - context.processors.Add(mapper); - - context.Log(string.Format("Added {0} NMGen processor.", typeof(AreaFlagMapper).Name), this); - - return true; - } -} diff --git a/critterai/.svn/pristine/70/708e526ae1095a78fffb921766be4e8af0e84586.svn-base b/critterai/.svn/pristine/70/708e526ae1095a78fffb921766be4e8af0e84586.svn-base deleted file mode 100644 index 88c40deb..00000000 --- a/critterai/.svn/pristine/70/708e526ae1095a78fffb921766be4e8af0e84586.svn-base +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.u3d; - -namespace org.critterai.nav.u3d -{ - /// - /// Provides debug visualizations for objects. - /// - /// - /// - /// All draw methods in this class use GL, so they should generally be called from within the - /// OnRenderObject() method. - /// - /// - /// The design of this class minimizes impact on garbage collection. - /// - /// - /// Instances of this class are not thread-safe. - /// - /// - public sealed class CrowdAgentDebug - { - /// - /// The color to use when drawing neighbor visualizations. - /// - public static Color neighborColor = - new Color(Color.yellow.r, Color.yellow.g, Color.yellow.b, 0.66f); - - /// - /// The base color to use when drawing visualizations. - /// - public static Color baseColor = - new Color(Color.blue.r, Color.blue.g, Color.blue.b, 0.66f); - - /// - /// The color to use when drawing the agent velocity. - /// - public static Color velocityColor = - new Color(Color.blue.r, Color.blue.g, Color.blue.b, 0.66f); - - /// - /// The color to use when drawing the agent desired velocity. - /// - public static Color desiredVelocityColor = - new Color(Color.cyan.r, Color.cyan.g, Color.cyan.b, 0.5f); - - /// - /// The color to use when drawing corridor boundary visualizations. - /// - public static Color boundaryColor = - new Color(Color.yellow.r, Color.yellow.g, Color.yellow.b, 0.66f); - - private Navmesh navmesh; - - // Various buffers. (Reduces GC impact.) - private CrowdNeighbor[] neighbors = new CrowdNeighbor[CrowdNeighbor.MaxNeighbors]; - private LocalBoundaryData boundary = new LocalBoundaryData(); - private CornerData corners = new CornerData(); - private PathCorridorData corridor = new PathCorridorData(); - - /// - /// Constructor. - /// - /// The navigation mesh used by the agents. - /// - public CrowdAgentDebug(Navmesh navmesh) - { - this.navmesh = navmesh; - } - - /// - /// Draws all agent debug information. - /// - /// The agent to draw. - public void DrawAll(CrowdAgent agent) - { - agent.GetCornerData(corners); - agent.GetCorridor(corridor); - - // Order matters. - NavDebug.Draw(navmesh, corridor); - DrawNeighbors(agent); - DrawLocalBoundary(agent); - NavDebug.Draw(corners); - DrawBase(agent); - } - - /// - /// Draws the basic agent debug information. - /// - /// - /// - /// This does not include the duplicate agent information such as target and corner - /// positions. - /// - /// - /// The agent to draw. - public void DrawBase(CrowdAgent agent) - { - Vector3 pos = agent.Position; - CrowdAgentParams config = agent.GetConfig(); - - DebugDraw.Circle(pos, config.radius, neighborColor); - - DebugDraw.Arrow(pos + Vector3.up * config.height - , pos + agent.DesiredVelocity + Vector3.up * config.height - , 0, 0.05f, desiredVelocityColor); - - DebugDraw.Arrow(pos + Vector3.up * config.height - , pos + agent.Velocity + Vector3.up * config.height - , 0, 0.05f, velocityColor); - } - - /// - /// Draws agent neighbor information. - /// - /// The agent to draw. - public void DrawNeighbors(CrowdAgent agent) - { - int neighborCount = agent.NeighborCount; - - if (neighborCount == 0) - return; - - agent.GetNeighbors(neighbors); - - for (int i = 0; i < neighborCount; i++) - { - CrowdAgent n = agent.GetNeighbor(neighbors[i]); - if (n == null) - // Not sure why this happens. Bug in CrowdAgent? - continue; - DebugDraw.Arrow(agent.Position, n.Position, 0, 0.05f, neighborColor); - DebugDraw.Circle(n.Position, agent.GetConfig().radius, neighborColor); - } - } - - /// - /// Draws agent local boundary information. - /// - /// The agent to draw. - public void DrawLocalBoundary(CrowdAgent agent) - { - agent.GetBoundary(boundary); - - if (boundary.segmentCount == 0) - return; - - DebugDraw.XMarker(boundary.center - , 0.1f, boundaryColor); - - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(boundaryColor); - - for (int i = 0; i < boundary.segmentCount; i++) - { - int p = i * 2; - GL.Vertex(boundary.segments[p]); - GL.Vertex(boundary.segments[p + 1]); - } - - GL.End(); - } - } -} - diff --git a/critterai/.svn/pristine/70/70f45941751ce3fa7adb94c82b51eddfb98afe10.svn-base b/critterai/.svn/pristine/70/70f45941751ce3fa7adb94c82b51eddfb98afe10.svn-base deleted file mode 100644 index b7a8d0ef..00000000 --- a/critterai/.svn/pristine/70/70f45941751ce3fa7adb94c82b51eddfb98afe10.svn-base +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.critterai.math.Vector2.dot; - -/** - * Provides operations related to 2-dimensional triangles. - *

This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No checks are performed to ensure the arguments represent a valid triangle.

- *

Static operations are thread safe.

- */ -public class Triangle2 -{ - - /** - * Returns TRUE if the point (px, py) is contained by the triangle. - *

The test is inclusive. So points on the vertices or edges - * of the triangle are considered to be contained by the triangle.

- * @param px The x-value for the point to test. (px, py) - * @param py The y-value for the poitn to test. (px, py) - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @return TRUE if the point (x, y) is contained by the triangle ABC. - */ - public static boolean contains(float px, float py - , float ax, float ay - , float bx, float by - , float cx, float cy) - { - float dirABx = bx - ax; - float dirABy = by - ay; - float dirACx = cx - ax; - float dirACy = cy - ay; - float dirAPx = px - ax; - float dirAPy = py - ay; - - float dotABAB = dot(dirABx, dirABy, dirABx, dirABy); - float dotACAB = dot(dirACx, dirACy, dirABx, dirABy); - float dotACAC = dot(dirACx, dirACy, dirACx, dirACy); - float dotACAP = dot(dirACx,dirACy, dirAPx, dirAPy); - float dotABAP = dot(dirABx, dirABy, dirAPx, dirAPy); - - float invDenom = 1 / (dotACAC * dotABAB - dotACAB * dotACAB); - float u = (dotABAB * dotACAP - dotACAB * dotABAP) * invDenom; - float v = (dotACAC * dotABAP - dotACAB * dotACAP) * invDenom; - - // Altered this slightly from the reference so that points on the vertices and edges - // are considered to be inside the triangle. - return (u >= 0) && (v >= 0) && (u + v <= 1); - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle ABC. - *

A positive value indicates:

- *
    - *
  • Counterclockwise wrapping of the vertices.
  • - *
  • Vertex B lies to the right of line AC, looking from A toward C.
  • - *
- *

A negative value indicates:

- *
    - *
  • Clockwise wrapping of the vertices.
  • - *
  • Vertex B lies to the left of line AC, looking from A toward C.
  • - *
- *

A value of zero indicates that all points are collinear or represent the same point.

- *

This is a low cost operation.

- * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @return The absolute value of the returned value is two times the area of the - * triangle ABC. - */ - public static float getSignedAreaX2(float ax, float ay, float bx, float by, float cx, float cy) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - // http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle ABC. - *

A positive value indicates:

- *
    - *
  • Counterclockwise wrapping of the vertices.
  • - *
  • Vertex B lies to the right of line AC, looking from A toward C.
  • - *
- *

A negative value indicates:

- *
    - *
  • Clockwise wrapping of the vertices.
  • - *
  • Vertex B lies to the left of line AC, looking from A toward C.
  • - *
      - *

      A value of zero indicates that all points are collinear or represent the same point.

      - *

      This is a low cost operation.

      - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @return The absolute value of the returned value is two times the area of the - * triangle ABC. - */ - public static int getSignedAreaX2(int ax, int ay, int bx, int by, int cx, int cy) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - // http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - -} diff --git a/critterai/.svn/pristine/71/71fa5729a413e3bce834d837845b84b31b6aa3bf.svn-base b/critterai/.svn/pristine/71/71fa5729a413e3bce834d837845b84b31b6aa3bf.svn-base deleted file mode 100644 index 928392cb..00000000 --- a/critterai/.svn/pristine/71/71fa5729a413e3bce834d837845b84b31b6aa3bf.svn-base +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -/** - * Specifies the position relationship between a point and a line. - */ -public enum PointLineRelType -{ - /** - * The point is on, or very near, the line - */ - ON_LINE, - - /** - * The test point is to the left when looking from point A toward B on the line. - */ - LEFT_SIDE, - - /** - * The test point is to the right when looking from point A toward B on the line. - */ - RIGHT_SIDE -} \ No newline at end of file diff --git a/critterai/.svn/pristine/72/72844fd4608af562279705012446734db0420cac.svn-base b/critterai/.svn/pristine/72/72844fd4608af562279705012446734db0420cac.svn-base deleted file mode 100644 index e4838e48..00000000 --- a/critterai/.svn/pristine/72/72844fd4608af562279705012446734db0420cac.svn-base +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// A point within a navigation mesh. - /// - [StructLayout(LayoutKind.Sequential)] - public struct NavmeshPoint - { - /// - /// The reference of the polygon the contains the point. (Or zero if not known.) - /// - public uint polyRef; - - /// - /// The location of the point. - /// - public Vector3 point; - - /// - /// Constructor. - /// - /// - /// The reference of the polygon that contains the point. (Or zero if not known.) - /// - /// The location of the point. - public NavmeshPoint(uint polyRef, Vector3 point) - { - this.polyRef = polyRef; - this.point = point; - } - - /// - /// Equality operator. - /// - /// A navmesh point. - /// A navmesh point. - /// True if the points are equal. - public static bool operator ==(NavmeshPoint v, NavmeshPoint u) - { - return (v.point == u.point && v.polyRef == u.polyRef); - } - - /// - /// Inequality operator. - /// - /// A navmesh point. - /// A navmesh point. - /// True if the points are not equal. - public static bool operator !=(NavmeshPoint v, NavmeshPoint u) - { - return !(v.point == u.point && v.polyRef == u.polyRef); - } - - /// - /// The navmesh point hash code. - /// - /// The navmesh point hash code. - public override int GetHashCode() - { - int result = 17; - result = 31 * result + point.x.GetHashCode(); - result = 31 * result + point.y.GetHashCode(); - result = 31 * result + point.z.GetHashCode(); - result = 31 * result + polyRef.GetHashCode(); - return result; - } - - /// - /// Tests the navmesh point for equality. - /// - /// The point to compare. - /// True if each element of the point is equal to this point. - public override bool Equals(object obj) - { - if (obj is NavmeshPoint) - { - NavmeshPoint u = (NavmeshPoint)obj; - return (point == u.point && polyRef == u.polyRef); - } - return false; - } - - /// - /// Returns a standard string representation of point. - /// - /// A standard string representation of point. - public override string ToString() - { - return string.Format("[{0:F3}, {1:F3}, {2:F3}] (Ref: {3})" - , point.x, point.y, point.z, polyRef); - } - - /// - /// The zero point. - /// - public static NavmeshPoint Zero - { - get { return new NavmeshPoint(0, Vector3Util.Zero); } - } - - /// - /// Creates an array of vectors from the provided navmesh points. - /// - /// - /// - /// A new array will be created if the array is null. - /// - /// - /// The source array. - /// The start of the copy in the source. - /// The target of the copy. (Optional) - /// The start copy location within the target. - /// The number of vectors to copy. - /// - /// An array containing the copied vectors. (A reference to - /// if it was non-null.) - /// - public static Vector3[] GetPoints(NavmeshPoint[] source, int sourceIndex - , Vector3[] target, int targetIndex - , int count) - { - if (target == null) - target = new Vector3[source.Length + targetIndex]; - - for (int i = 0; i < count; i++) - { - target[targetIndex + i] = source[sourceIndex + i].point; - } - - return target; - } - } -} diff --git a/critterai/.svn/pristine/73/7385955992a1bb1f47137d803f69c4f710a219d3.svn-base b/critterai/.svn/pristine/73/7385955992a1bb1f47137d803f69c4f710a219d3.svn-base deleted file mode 100644 index 4a83d046..00000000 --- a/critterai/.svn/pristine/73/7385955992a1bb1f47137d803f69c4f710a219d3.svn-base +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.critterai.math.MathUtil; -import org.critterai.math.Vector3; - - -/** - * Provides operations related to polygons defined in 3-dimensional space with - * coplanar vertices. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, divide by zero checks only when needed by the algorithm, etc.

      - *

      Static operations are thread safe.

      - */ -public class Polygon3 -{ - - private Polygon3() { } - - /** - * Determines whether a polygon is convex. - *

      Behavior is undefined if vertices are not coplanar.

      - *

      If the area of the triangle formed by the first three vertices of the polygon is too small - * to detect on both the (x, z) and (x, y) planes, then this operation may improperly return - * FALSE.

      - * @param verts An array of vertices which contains a representation of polygons with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * Wrap direction does not matter. - * @param startVertIndex The index of the first vertex in the polygon. - * @param vertCount The number of vertices in the polygon. - * @return TRUE if the polygon is convex. Otherwise FALSE. - */ - public static boolean isConvex(float[] verts, int startVertIndex, int vertCount) - { - - if (vertCount < 3) - return false; - if (vertCount == 3) - // It is a triangle, so it must be convex. - return true; - - // At this point we know that the polygon has at least 4 sides. - - /* - * Process will be to step through the sides, 3 vertices at a time. - * As long the signed area for the triangles formed by each set of - * vertices is the same (negative or positive), then the polygon is convex. - * - * Using a shortcut by projecting onto the (x, z) or (x, y) plane for all calculations. - * For a proper polygon, if the 2D projection is convex, the 3D polygon is convex. - * - * There is one special case: A polygon that is vertical. I.e. 2D on the (x, z) plane. - * This is detected during the first test. - */ - - int offset = 2; // Start by projecting to the (x, z) plane. - - int pStartVert = startVertIndex*3; - - float initDirection = Triangle2.getSignedAreaX2(verts[pStartVert] - , verts[pStartVert+2] - , verts[pStartVert+3] - , verts[pStartVert+5] - , verts[pStartVert+6] - , verts[pStartVert+8]); - - if (initDirection > -2 * MathUtil.EPSILON_STD - && initDirection < 2 * MathUtil.EPSILON_STD) - { - // The polygon is on or very close to the vertical plane. Switch to projecting on the (x, y) plane. - offset = 1; - initDirection = Triangle2.getSignedAreaX2(verts[pStartVert] - , verts[pStartVert+1] - , verts[pStartVert+3] - , verts[pStartVert+4] - , verts[pStartVert+6] - , verts[pStartVert+7]); - // Dev note: This is meant to be a strict zero test. - if (initDirection == 0) - // Some sort of problem. Should very rarely ever get here. - return false; - } - - int vertLength = (startVertIndex+vertCount)*3; - for (int vertAPointer = pStartVert+3; vertAPointer < vertLength; vertAPointer += 3) - { - int vertBPointer = vertAPointer+3; - if (vertBPointer >= vertLength) - // Wrap it back to the start. - vertBPointer = pStartVert; - int vertCPointer = vertBPointer+3; - if (vertCPointer >= vertLength) - // Wrap it back to the start. - vertCPointer = pStartVert; - float direction = Triangle2.getSignedAreaX2( - verts[vertAPointer] - , verts[vertAPointer+offset] - , verts[vertBPointer] - , verts[vertBPointer+offset] - , verts[vertCPointer] - , verts[vertCPointer+offset]); - if (!(initDirection < 0 && direction < 0) && !(initDirection > 0 && direction > 0)) - // The sign of the current direction is not the same as the sign of the - // initial direction. Can't be convex. - return false; - } - - return true; - - } - - /** - * Returns the centroid of a convex polygon. - *

      Behavior is undefined if the polygon is not convex.

      - *

      Behavior is undefined if the vector being overwritten in the out array - * is a vertex in the polygon. (Can only happen if the verts and out arrays - * are the same object.)

      - * @param verts An array of vertices which contains a representation of a polygon with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * Wrap direction does not matter. - * @param startVertIndex The index of the first vertex in the polygon. - * @param vertCount The number of vertices in the polygon. - * @param out The array to store the result in. - * @param outVectorIndex The vector index in the out array to store the result in. (The stride - * is expected to be three. So the insertion point will be outVectorIndex*3.) - * @return A reference to the out argument. - * @see Centroid - */ - public static float[] getCentroid(float[] verts - , int startVertIndex - , int vertCount - , float[] out - , int outVectorIndex) - { - // Reference: http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - int vertLength = (startVertIndex+vertCount)*3; - int pOut = outVectorIndex*3; - out[pOut] = 0; - out[pOut+1] = 0; - out[pOut+2] = 0; - for (int pVert = startVertIndex*3; pVert < vertLength; pVert += 3) - { - out[pOut] += verts[pVert]; - out[pOut+1] += verts[pVert+1]; - out[pOut+2] += verts[pVert+2]; - } - - out[pOut] /= vertCount; - out[pOut+1] /= vertCount; - out[pOut+2] /= vertCount; - - return out; - } - - /** - * Returns the centroid of a polygon. - * @param verts An array of vertices which contains a representation of a polygon with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * Wrap direction does not matter. - *

      Behavior is undefined if the polygon is not convex.

      - * @param startVertIndex The index of the first vertex in the polygon. - * @param vertCount The number of vertices in the polygon. - * @param out The vector to store the result in. - * @return A reference to the out argument. - * @see Centroid - */ - public static Vector3 getCentroid(float[] verts - , int startVertIndex - , int vertCount - , Vector3 out) - { - // Reference: http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - out.set(0, 0, 0); - int vertLength = (startVertIndex+vertCount)*3; - for (int pVert = startVertIndex*3; pVert < vertLength; pVert += 3) - { - out.x += verts[pVert]; - out.y += verts[pVert+1]; - out.z += verts[pVert+2]; - } - - out.x /= vertCount; - out.y /= vertCount; - out.z /= vertCount; - - return out; - - } - - /** - * Returns the centroid of a polygon. - * @param out The vector to store the result in. - * @param verts An list of vertices which represent a polygon with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * @return A reference to the out argument. - * @see Centroid - */ - public static Vector3 getCentroid(Vector3 out, float...verts) - { - // Reference: http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - out.set(0, 0, 0); - - int vertCount = 0; - for (int pVert =0; pVert < verts.length; pVert += 3) - { - out.x += verts[pVert]; - out.y += verts[pVert+1]; - out.z += verts[pVert+2]; - vertCount++; - } - - out.x /= vertCount; - out.y /= vertCount; - out.z /= vertCount; - - return out; - } - -} diff --git a/critterai/.svn/pristine/73/73f89ace4d56480f375a25b146e86255d5742bbd.svn-base b/critterai/.svn/pristine/73/73f89ace4d56480f375a25b146e86255d5742bbd.svn-base deleted file mode 100644 index fed2c1c7..00000000 Binary files a/critterai/.svn/pristine/73/73f89ace4d56480f375a25b146e86255d5742bbd.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/74/742045a3672d63c064bf4fc42dd22edf914e49e7.svn-base b/critterai/.svn/pristine/74/742045a3672d63c064bf4fc42dd22edf914e49e7.svn-base deleted file mode 100644 index 52c5fd79..00000000 --- a/critterai/.svn/pristine/74/742045a3672d63c064bf4fc42dd22edf914e49e7.svn-base +++ /dev/null @@ -1,442 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURCROWD_H -#define DETOURCROWD_H - -#include "DetourNavMeshQuery.h" -#include "DetourObstacleAvoidance.h" -#include "DetourLocalBoundary.h" -#include "DetourPathCorridor.h" -#include "DetourProximityGrid.h" -#include "DetourPathQueue.h" - -/// The maximum number of neighbors that a crowd agent can take into account -/// for steering decisions. -/// @ingroup crowd -static const int DT_CROWDAGENT_MAX_NEIGHBOURS = 6; - -/// The maximum number of corners a crowd agent will look ahead in the path. -/// This value is used for sizing the crowd agent corner buffers. -/// Due to the behavior of the crowd manager, the actual number of useful -/// corners will be one less than this number. -/// @ingroup crowd -static const int DT_CROWDAGENT_MAX_CORNERS = 4; - -/// The maximum number of crowd avoidance configurations supported by the -/// crowd manager. -/// @ingroup crowd -/// @see dtObstacleAvoidanceParams, dtCrowd::setObstacleAvoidanceParams(), dtCrowd::getObstacleAvoidanceParams(), -/// dtCrowdAgentParams::obstacleAvoidanceType -static const int DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS = 8; - -/// Provides neighbor data for agents managed by the crowd. -/// @ingroup crowd -/// @see dtCrowdAgent::neis, dtCrowd -struct dtCrowdNeighbour -{ - int idx; ///< The index of the neighbor in the crowd. - float dist; ///< The distance between the current agent and the neighbor. -}; - -/// The type of navigation mesh polygon the agent is currently traversing. -/// @ingroup crowd -enum CrowdAgentState -{ - DT_CROWDAGENT_STATE_INVALID, ///< The agent is not in a valid state. - DT_CROWDAGENT_STATE_WALKING, ///< The agent is traversing a normal navigation mesh polygon. - DT_CROWDAGENT_STATE_OFFMESH, ///< The agent is traversing an off-mesh connection. -}; - -/// Configuration parameters for a crowd agent. -/// @ingroup crowd -struct dtCrowdAgentParams -{ - float radius; ///< Agent radius. [Limit: >= 0] - float height; ///< Agent height. [Limit: > 0] - float maxAcceleration; ///< Maximum allowed acceleration. [Limit: >= 0] - float maxSpeed; ///< Maximum allowed speed. [Limit: >= 0] - - /// Defines how close a collision element must be before it is considered for steering behaviors. [Limits: > 0] - float collisionQueryRange; - - float pathOptimizationRange; ///< The path visibility optimization range. [Limit: > 0] - - /// How aggresive the agent manager should be at avoiding collisions with this agent. [Limit: >= 0] - float separationWeight; - - /// Flags that impact steering behavior. (See: #UpdateFlags) - unsigned char updateFlags; - - /// The index of the avoidance configuration to use for the agent. - /// [Limits: 0 <= value <= #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS] - unsigned char obstacleAvoidanceType; - - /// User defined data attached to the agent. - void* userData; -}; - -/// Represents an agent managed by a #dtCrowd object. -/// @ingroup crowd -struct dtCrowdAgent -{ - /// 1 if the agent is active, or 0 if the agent is in an unused slot in the agent pool. - unsigned char active; - - /// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState) - unsigned char state; - - /// The path corridor the agent is using. - dtPathCorridor corridor; - - /// The local boundary data for the agent. - dtLocalBoundary boundary; - - float t; - float var; - - /// The last time the agent's path corridor was optimized. - float topologyOptTime; - - /// The known neighbors of the agent. - dtCrowdNeighbour neis[DT_CROWDAGENT_MAX_NEIGHBOURS]; - - /// The number of neighbors. - int nneis; - - /// The desired speed. - float desiredSpeed; - - float npos[3]; ///< The current agent position. [(x, y, z)] - float disp[3]; - float dvel[3]; ///< The desired velocity of the agent. [(x, y, z)] - float nvel[3]; - float vel[3]; ///< The actual velocity of the agent. [(x, y, z)] - - /// The agent's configuration parameters. - dtCrowdAgentParams params; - - /// The local path corridor corners for the agent. (Staight path.) [(x, y, z) * #ncorners] - float cornerVerts[DT_CROWDAGENT_MAX_CORNERS*3]; - - /// The local path corridor corner flags. (See: #dtStraightPathFlags) [(flags) * #ncorners] - unsigned char cornerFlags[DT_CROWDAGENT_MAX_CORNERS]; - - /// The reference id of the polygon being entered at the corner. [(polyRef) * #ncorners] - dtPolyRef cornerPolys[DT_CROWDAGENT_MAX_CORNERS]; - - /// The number of corners. - int ncorners; -}; - -struct dtCrowdAgentAnimation -{ - unsigned char active; - float initPos[3], startPos[3], endPos[3]; - dtPolyRef polyRef; - float t, tmax; -}; - -/// Crowd agent update flags. -/// @ingroup crowd -/// @see dtCrowdAgentParams::updateFlags -enum UpdateFlags -{ - DT_CROWD_ANTICIPATE_TURNS = 1, - DT_CROWD_OBSTACLE_AVOIDANCE = 2, - DT_CROWD_SEPARATION = 4, - DT_CROWD_OPTIMIZE_VIS = 8, ///< Use #dtPathCorridor::optimizePathVisibility() to optimize the agent path. - DT_CROWD_OPTIMIZE_TOPO = 16, ///< Use dtPathCorridor::optimizePathTopology() to optimize the agent path. -}; - -struct dtCrowdAgentDebugInfo -{ - int idx; - float optStart[3], optEnd[3]; - dtObstacleAvoidanceDebugData* vod; -}; - -/// Provides local steering behaviors for a group of agents. -/// @ingroup crowd -class dtCrowd -{ - int m_maxAgents; - dtCrowdAgent* m_agents; - dtCrowdAgent** m_activeAgents; - dtCrowdAgentAnimation* m_agentAnims; - - dtPathQueue m_pathq; - - dtObstacleAvoidanceParams m_obstacleQueryParams[DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS]; - dtObstacleAvoidanceQuery* m_obstacleQuery; - - dtProximityGrid* m_grid; - - dtPolyRef* m_pathResult; - int m_maxPathResult; - - float m_ext[3]; - dtQueryFilter m_filter; - - float m_maxAgentRadius; - - int m_velocitySampleCount; - - enum MoveRequestState - { - MR_TARGET_NONE, - MR_TARGET_FAILED, - MR_TARGET_VALID, - MR_TARGET_REQUESTING, - MR_TARGET_WAITING_FOR_PATH, - MR_TARGET_ADJUST, - }; - - static const int MAX_TEMP_PATH = 32; - - struct MoveRequest - { - unsigned char state; ///< State of the request - int idx; ///< Agent index - dtPolyRef ref; ///< Goal ref - float pos[3]; ///< Goal position - dtPathQueueRef pathqRef; ///< Path find query ref - dtPolyRef aref; ///< Goal adjustment ref - float apos[3]; ///< Goal adjustment pos - dtPolyRef temp[MAX_TEMP_PATH]; ///< Adjusted path to the goal - int ntemp; - bool replan; - }; - MoveRequest* m_moveRequests; - int m_moveRequestCount; - - dtNavMeshQuery* m_navquery; - - void updateTopologyOptimization(dtCrowdAgent** agents, const int nagents, const float dt); - void updateMoveRequest(const float dt); - void checkPathValidty(dtCrowdAgent** agents, const int nagents, const float dt); - - inline int getAgentIndex(const dtCrowdAgent* agent) const { return agent - m_agents; } - const MoveRequest* getActiveMoveTarget(const int idx) const; - - bool requestMoveTargetReplan(const int idx, dtPolyRef ref, const float* pos); - - void purge(); - -public: - dtCrowd(); - ~dtCrowd(); - - /// Initializes the crowd. - /// @param[in] maxAgents The maximum number of agents the crowd can manage. [Limit: >= 1] - /// @param[in] maxAgentRadius The maximum radius of any agent that will be added to the crowd. [Limit: > 0] - /// @param[in] nav The navigation mesh to use for planning. - /// @return True if the initialization succeeded. - bool init(const int maxAgents, const float maxAgentRadius, dtNavMesh* nav); - - /// Sets the shared avoidance configuration for the specified index. - /// @param[in] idx The index. [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS] - /// @param[in] params The new configuration. - void setObstacleAvoidanceParams(const int idx, const dtObstacleAvoidanceParams* params); - - /// Gets the shared avoidance configuration for the specified index. - /// @param[in] idx The index of the configuration to retreive. - /// [Limits: 0 <= value < #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS] - /// @return The requested configuration. - const dtObstacleAvoidanceParams* getObstacleAvoidanceParams(const int idx) const; - - /// Gets the specified agent from the pool. - /// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()] - /// @return The requested agent. - const dtCrowdAgent* getAgent(const int idx); - - /// The maximum number of agents that can be managed by the object. - /// @return The maximum number of agents. - const int getAgentCount() const; - - /// Adds a new agent to the crowd. - /// @param[in] pos The requested position of the agent. [(x, y, z)] - /// @param[in] params The configutation of the agent. - /// @return The index of the agent in the agent pool. Or -1 if the agent could not be added. - int addAgent(const float* pos, const dtCrowdAgentParams* params); - - /// Updates the specified agent's configuration. - /// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()] - /// @param[in] params The new agent configuration. - void updateAgentParameters(const int idx, const dtCrowdAgentParams* params); - - /// Removes the agent from the crowd. - /// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()] - void removeAgent(const int idx); - - /// Submits a new move request for the specified agent. - /// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()] - /// @param[in] ref The position's polygon reference. - /// @param[in] pos The position within the polygon. [(x, y, z)] - /// @return True if the request was successfully submitted. - bool requestMoveTarget(const int idx, dtPolyRef ref, const float* pos); - - /// Sumbits a request to adjust the target position of the specified agent. - /// @param[in] idx The agent index. [Limits: 0 <= value < #getAgentCount()] - /// @param[in] ref The position's polygon reference. - /// @param[in] pos The position within the polygon. [(x, y, z)] - /// @return True if the request was successfully submitted. - bool adjustMoveTarget(const int idx, dtPolyRef ref, const float* pos); - - /// Gets the active agents int the agent pool. - /// @param[out] agents An array of agent pointers. [(#dtCrowdAgent *) * maxAgents] - /// @param[in] maxAgents The size of the crowd agent array. - /// @return The number of agents returned in @p agents. - int getActiveAgents(dtCrowdAgent** agents, const int maxAgents); - - /// Updates the steering and positions of all agents. - /// @param[in] dt The time, in seconds, to update the simulation. [Limit: > 0] - /// @param[out] debug A debug object to load with debug information. [Opt] - void update(const float dt, dtCrowdAgentDebugInfo* debug); - - /// Gets the filter used by the crowd. - /// @return The filter used by the crowd. - const dtQueryFilter* getFilter() const { return &m_filter; } - - /// Gets the filter used by the crowd. - /// @return The filter used by the crowd. - dtQueryFilter* getEditableFilter() { return &m_filter; } - - /// Gets the search extents [(x, y, z)] used by the crowd for query operations. - /// @return The search extents used by the crowd. [(x, y, z)] - const float* getQueryExtents() const { return m_ext; } - - /// Gets the velocity sample count. - /// @return The velocity sample count. - inline int getVelocitySampleCount() const { return m_velocitySampleCount; } - - /// Gets the crowd's proximity grid. - /// @return The crowd's proximity grid. - const dtProximityGrid* getGrid() const { return m_grid; } - - /// Gets the crowd's path request queue. - /// @return The crowd's path request queue. - const dtPathQueue* getPathQueue() const { return &m_pathq; } - - /// Gets the query object used by the crowd. - const dtNavMeshQuery* getNavMeshQuery() const { return m_navquery; } -}; - -/// Allocates a crowd object using the Detour allocator. -/// @return A crowd object that is ready for initialization, or null on failure. -/// @ingroup crowd -dtCrowd* dtAllocCrowd(); - -/// Frees the specified crowd object using the Detour allocator. -/// @param[in] ptr A crowd object allocated using #dtAllocCrowd -/// @ingroup crowd -void dtFreeCrowd(dtCrowd* ptr); - - -#endif // DETOURCROWD_H - -/////////////////////////////////////////////////////////////////////////// - -// This section contains detailed documentation for members that don't have -// a source file. It reduces clutter in the main section of the header. - -/** - -@defgroup crowd Crowd - -Members in this module implement local steering and dynamic avoidance features. - -The crowd is the big beast of the navigation features. It not only handles a -lot of the path management for you, but also local steering and dynamic -avoidance between members of the crowd. I.e. It can keep your agents from -running into each other. - -Main class: #dtCrowd - -The #dtNavMeshQuery and #dtPathCorridor classes provide perfectly good, easy -to use path planning features. But in the end they only give you points that -your navigation client should be moving toward. When it comes to deciding things -like agent velocity and steering to avoid other agents, that is up to you to -implement. Unless, of course, you decide to use #dtCrowd. - -Basically, you add an agent to the crowd, providing various configuration -settings such as maximum speed and acceleration. You also provide a local -target to more toward. The crowd manager then provides, with every update, the -new agent position and velocity for the frame. The movement will be -constrained to the navigation mesh, and steering will be applied to ensure -agents managed by the crowd do not collide with each other. - -This is very powerful feature set. But it comes with limitations. - -The biggest limitation is that you must give control of the agent's position -completely over to the crowd manager. You can update things like maximum speed -and acceleration. But in order for the crowd manager to do its thing, it can't -allow you to constantly be giving it overrides to position and velocity. So -you give up direct control of the agent's movement. It belongs to the crowd. - -The second biggest limitation revolves around the fact that the crowd manager -deals with local planning. So the agent's target should never be more than -256 polygons aways from its current position. If it is, you risk -your agent failing to reach its target. So you may still need to do long -distance planning and provide the crowd manager with intermediate targets. - -Other significant limitations: - -- All agents using the crowd manager will use the same #dtQueryFilter. -- Crowd management is relatively expensive. The maximum agents under crowd - management at any one time is between 20 and 30. A good place to start - is a maximum of 25 agents for 0.5ms per frame. - -@note This is a summary list of members. Use the index or search -feature to find minor members. - -@struct dtCrowdAgentParams -@see dtCrowdAgent, dtCrowd::addAgent(), dtCrowd::updateAgentParameters() - -@var dtCrowdAgentParams::obstacleAvoidanceType -@par - -#dtCrowd permits agents to use different avoidance configurations. This value -is the index of the #dtObstacleAvoidanceParams within the crowd. - -@see dtObstacleAvoidanceParams, dtCrowd::setObstacleAvoidanceParams(), - dtCrowd::getObstacleAvoidanceParams() - -@var dtCrowdAgentParams::collisionQueryRange -@par - -Collision elements include other agents and navigation mesh boundaries. - -This value is often based on the agent radius and/or maximum speed. E.g. radius * 8 - -@var dtCrowdAgentParams::pathOptimizationRange -@par - -Only applicalbe if #updateFlags includes the #DT_CROWD_OPTIMIZE_VIS flag. - -This value is often based on the agent radius. E.g. radius * 30 - -@see dtPathCorridor::optimizePathVisibility() - -@var dtCrowdAgentParams::separationWeight -@par - -A higher value will result in agents trying to stay farther away from each other at -the cost of more difficult steering in tight spaces. - -*/ \ No newline at end of file diff --git a/critterai/.svn/pristine/75/75d3c4522ffdcbd264a86b0eeeecf4fd90aaf724.svn-base b/critterai/.svn/pristine/75/75d3c4522ffdcbd264a86b0eeeecf4fd90aaf724.svn-base deleted file mode 100644 index 4dd4d7df..00000000 --- a/critterai/.svn/pristine/75/75d3c4522ffdcbd264a86b0eeeecf4fd90aaf724.svn-base +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - Depending on the way CAINav is built, it will use either the UnityEngine vectors or the CAINav built-in vectors. - For Unity users, UnityEngine.Vector3 and UnityEngine.Vector2. For .NET-Only users, org.critterai.Vector3 and org.critterai.Vector2. This is great for Unity users, - but means that .NET-users will probably need to marshal between their native vector structures and the CAINav structures. - - - - Advanced users have another option. It may be possible, with only an hour or two of work per version upgrade, to swap your own native vectors - into CAINav. This topic will cover the steps to accomplish this. - - - - -
      - - Overview - - - - - In order to swap your own native vectors into CAINav, you'll need to follow these steps: - - - - Validate that your vector API is compatible. - Update the .NET Visual Studio Projects and code. (Mostly a simple search and replace.) - Build and validate vector data compatibility. - - - - - - - This topic only covers the Vector3 structure. The same basic process can be used for the Vector2 structure. Data compatibility validation is not - required for Vector2 since it is not involved in interop operations. - - - -
      - -
      - - Validate API Compatibility - - - - - The first step is to make sure your native vector's API is compatible with org.critterai.Vector3. To do this, open the .NET Visual Studio - project. It is located in the \build\dotNet directory of the distribution. The source file will be located in the cai-util project. The - Vector3 structure is kept very simple, so the likelihood of conflict is minimal. - - - - While you will be validating data compatibility later, it is a good idea to smoke check that now. (Do the order of the fields match?) - - - - -
      - -
      - - Update the Visual Studio Projects and Code - - - - - Add a reference to your vector library to each project in the Visual Studio solution. - - - - Throughout the CAINav code the following conditional compile statement is used to control which vector is used: - - - - #if NUNITY - using Vector3 = org.critterai.Vector3; - #else - using Vector3 = UnityEngine.Vector3; - #endif - - - - So all you need to do to swap in your own vector is to do a global search and replace. Find "using Vector3 = org.critterai.Vector3;", and - replace it with your own. For example: "using Vector3 = MyEngine.Vector3f;" - - - - Browse to the Vector3 source file in the cai-util project and comment out all code. This makes sure that errors don't accidentally result - in the CAINav vector still being referenced somewhere. - - - - Finally, build the solution. It your API is truly compatible, the build should complete without errors. - - - - -
      - -
      - - Validate Data Compatibility - - - - - The final step is to check data capatibility. (Is the internal data format of your vector the same as the CAINav vector?) To do this, write some - test code that uses the new libraries and run the M:org.critterai.nav.NavUtil.TestVector(UnityEngine.Vector3) and - M:org.critterai.nav.NavUtil.TestVectorArray(UnityEngine.Vector3[],System.Int32,UnityEngine.Vector3[]) test methods. - - - - If the input and output of these test methods matches exactly, then you are good to go. If the tests fail, then you know that there is some - sort of problem and you won't be able to use your native vectors. - - - - -
      - -
      -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/76/769028033897ad1b28db5a671e6b4e6259782e08.svn-base b/critterai/.svn/pristine/76/769028033897ad1b28db5a671e6b4e6259782e08.svn-base deleted file mode 100644 index 49e8ff5f..00000000 --- a/critterai/.svn/pristine/76/769028033897ad1b28db5a671e6b4e6259782e08.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nmbuild")] -[assembly: AssemblyDescription("Design-time navigation mesh build extensions.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/76/769989f578aff0e8d640943d5c1a9023edc57f7d.svn-base b/critterai/.svn/pristine/76/769989f578aff0e8d640943d5c1a9023edc57f7d.svn-base deleted file mode 100644 index 532eae14..00000000 Binary files a/critterai/.svn/pristine/76/769989f578aff0e8d640943d5c1a9023edc57f7d.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/77/779018bdbe4989781b617a64e8341cfe1785c33e.svn-base b/critterai/.svn/pristine/77/779018bdbe4989781b617a64e8341cfe1785c33e.svn-base deleted file mode 100644 index 32a3092a..00000000 --- a/critterai/.svn/pristine/77/779018bdbe4989781b617a64e8341cfe1785c33e.svn-base +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.interop -{ - /// - /// An interface for objects that contain references to unmanaged resources. - /// - public interface IManagedObject - { - /// - /// The type of unmanaged resources held by the object. - /// - AllocType ResourceType { get; } - - /// - /// Request all unmanaged resources controlled by the object be immediately freed and - /// the object marked as disposed. - /// - /// - /// - /// Whether or not unmanaged resources are actually freed depends on whether the - /// resources are owned by the object. In some cases the only action is to mark the - /// object as disposed. - /// - /// - void RequestDisposal(); - - /// - /// True if the object has been disposed and should no longer be used. - /// - bool IsDisposed { get; } - } -} diff --git a/critterai/.svn/pristine/79/7964bcb2b4ac454c6f3627f537db3a59332b7354.svn-base b/critterai/.svn/pristine/79/7964bcb2b4ac454c6f3627f537db3a59332b7354.svn-base deleted file mode 100644 index 8ecc9a9a..00000000 --- a/critterai/.svn/pristine/79/7964bcb2b4ac454c6f3627f537db3a59332b7354.svn-base +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -// Note: The file name does not match the element name because Unity -// doesn't support multiple script files with the same name. And the -// entity name exists in multiple namespaces. - -namespace org.critterai.nmgen.rcn -{ - internal struct InteropUtil - { - #if UNITY_IPHONE && !UNITY_EDITOR - public const string PLATFORM_DLL = "__Internal"; - #else - public const string PLATFORM_DLL = "cai-nmgen-rcn"; - #endif - } -} diff --git a/critterai/.svn/pristine/7a/7a3b792625f7f92228b83aa9d499bf9fc0f06c48.svn-base b/critterai/.svn/pristine/7a/7a3b792625f7f92228b83aa9d499bf9fc0f06c48.svn-base deleted file mode 100644 index 16fffafe..00000000 Binary files a/critterai/.svn/pristine/7a/7a3b792625f7f92228b83aa9d499bf9fc0f06c48.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/7a/7a52953711ddb55b2e54988d03e16fa003878c40.svn-base b/critterai/.svn/pristine/7a/7a52953711ddb55b2e54988d03e16fa003878c40.svn-base deleted file mode 100644 index 4f5fa8d6..00000000 Binary files a/critterai/.svn/pristine/7a/7a52953711ddb55b2e54988d03e16fa003878c40.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/7a/7a5dc72ea3737a1491f07924915e3c6aeb7faf12.svn-base b/critterai/.svn/pristine/7a/7a5dc72ea3737a1491f07924915e3c6aeb7faf12.svn-base deleted file mode 100644 index acefc4c9..00000000 --- a/critterai/.svn/pristine/7a/7a5dc72ea3737a1491f07924915e3c6aeb7faf12.svn-base +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// Represents the result of a NMGen build. - /// - /// - /// - /// All assets will be null if there is no result. Otherwise the only asset guarenteed - /// to be present is the object. - /// - /// - public struct NMGenAssets - { - private readonly int mTileX; - private readonly int mTileZ; - - private readonly PolyMesh mPolyMesh; - private readonly PolyMeshDetail mDetailMesh; - - private readonly Heightfield mHeightfield; - private readonly CompactHeightfield mCompactField; - private readonly ContourSet mContours; - - /// - /// Constructor - /// - /// - /// - /// A 'no result' object will be created if the parameter - /// is null or has a polygon count of zero. - /// - /// - /// The x-index of the tile within the tile grid. (tx, tz) - /// The z-index of the tile within the tile grid. (tx, tz) - /// The polymesh. - /// The detail mesh. - /// The heightfield. - /// The compact field. - /// The contour set. - public NMGenAssets(int tx, int tz - , PolyMesh polyMesh - , PolyMeshDetail detailMesh - , Heightfield heightfield - , CompactHeightfield compactField - , ContourSet contours) - { - mTileX = tx; - mTileZ = tz; - - if (polyMesh == null || polyMesh.PolyCount == 0) - { - mPolyMesh = null; - mDetailMesh = null; - mHeightfield = null; - mCompactField = null; - mContours = null; - } - else - { - mPolyMesh = polyMesh; - mDetailMesh = detailMesh; // OK to be null. - mHeightfield = heightfield; - mCompactField = compactField; - mContours = contours; - } - } - - /// - /// Constructor - /// - /// - /// - /// A 'no result' object will be created if the parameter - /// is null or has a polygon count of zero. - /// - /// - /// The x-index of the tile within the tile grid. (tx, tz) - /// The z-index of the tile within the tile grid. (tx, tz) - /// The polymesh. - /// The detail mesh. (Optional) - public NMGenAssets(int tx, int tz, PolyMesh polyMesh, PolyMeshDetail detailMesh) - { - mTileX = tx; - mTileZ = tz; - - if (polyMesh == null || polyMesh.PolyCount == 0) - { - mPolyMesh = null; - mDetailMesh = null; - } - else - { - mPolyMesh = polyMesh; - mDetailMesh = detailMesh; // OK to be null. - } - - mHeightfield = null; - mCompactField = null; - mContours = null; - } - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int TileX { get { return mTileX; } } - - /// - /// The z-index of the tile within the tile grid. (x, z) - /// - public int TileZ { get { return mTileZ; } } - - /// - /// The polygon mesh. - /// - public PolyMesh PolyMesh { get { return mPolyMesh; } } - - /// - /// The detail mesh. - /// - public PolyMeshDetail DetailMesh { get { return mDetailMesh; } } - - /// - /// The heightfield. - /// - public Heightfield Heightfield { get { return mHeightfield; } } - - /// - /// The compact field. - /// - public CompactHeightfield CompactField { get { return mCompactField; } } - - /// - /// The contour set. - /// - public ContourSet Contours { get { return mContours; } } - - /// - /// The assets are emtpy. (The build did not produce any results.) - /// - /// - /// - /// If true, all assets will be null. - /// - /// - public bool NoResult { get { return (mPolyMesh == null); } } - } -} diff --git a/critterai/.svn/pristine/7a/7a62d216363a5bd1ec0326dffcdcebf5cb20e6af.svn-base b/critterai/.svn/pristine/7a/7a62d216363a5bd1ec0326dffcdcebf5cb20e6af.svn-base deleted file mode 100644 index ea91ce71..00000000 --- a/critterai/.svn/pristine/7a/7a62d216363a5bd1ec0326dffcdcebf5cb20e6af.svn-base +++ /dev/null @@ -1,12 +0,0 @@ -This package contains a study version of NMGen. NMGen is an adaptation -in Java of Recast's static mesh functionality for purposes of study -and experimentation. NMGen takes an arbitrary triangle mesh as input -and generates data representing the traversable surface of the source mesh. - -Recast is a C++ navigation mesh construction toolset created by -Mikko Mononen and released under the MIT license. - -NMGen Home: http://code.google.com/p/critterai/ -Study Home: http://www.critterai.org/nmgen - -Recast Home: http://code.google.com/p/recastnavigation/ diff --git a/critterai/.svn/pristine/7b/7b36f7f86341d8f07f7669dcdde3a785c592cb3c.svn-base b/critterai/.svn/pristine/7b/7b36f7f86341d8f07f7669dcdde3a785c592cb3c.svn-base deleted file mode 100644 index 35d0e521..00000000 --- a/critterai/.svn/pristine/7b/7b36f7f86341d8f07f7669dcdde3a785c592cb3c.svn-base +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nav -{ - /// - /// Bounding volumn node. - /// - [StructLayout(LayoutKind.Sequential)] - public struct NavmeshBVNode - { - /// - /// Minimimum bounds of the node's AABB. [(x, y, z)] - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public ushort[] boundsMin; - - /// - /// Maximum bounds of the node's AABB. [(x, y, z)] - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public ushort[] boundsMax; - - /// - /// The node's index. (Negative for escape indices.) - /// - public int i; - } -} diff --git a/critterai/.svn/pristine/7b/7b83c1e2f13a4aa0dc34b8bac355d13c817bc0f8.svn-base b/critterai/.svn/pristine/7b/7b83c1e2f13a4aa0dc34b8bac355d13c817bc0f8.svn-base deleted file mode 100644 index 26f09151..00000000 --- a/critterai/.svn/pristine/7b/7b83c1e2f13a4aa0dc34b8bac355d13c817bc0f8.svn-base +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nav.rcn; -using org.critterai.interop; - -namespace org.critterai.nav -{ - /// - /// Represents proximity data generated by a object during - /// its update method. - /// - /// - /// - /// Objects of this type can only be obtained from a object. - /// - /// - /// // Example: Iterating the proximity data. - /// - /// // Where 'grid' is a CrowdProximityGrid object. - /// - /// int[] bounds = new int[4]; - /// grid.GetBounds(bounds); - /// float cs = grid.GetCellSize(); - /// - /// for (int y = bounds[1]; y <= bounds[3]; ++y) - /// { - /// // y-bounds of the cell in world units. - /// float minY = y * cs; - /// float maxY = y * cs + cs; - /// for (int x = bounds[0]; x <= bounds[2]; ++x) - /// { - /// int count = grid->getItemCountAt(x, y); - /// // x-bounds of the cell in world units. - /// float minX = x * cs; - /// float maxX = x * cs + cs; - /// } - /// } - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - public sealed class CrowdProximityGrid - { - private IntPtr root; - private bool mIsDisposed = false; - - internal CrowdProximityGrid(IntPtr grid) - { - root = grid; - } - - /// - /// Destructor - /// - ~CrowdProximityGrid() - { - Dispose(); - } - - internal void Dispose() - { - root = IntPtr.Zero; - mIsDisposed = true; - } - - /// - /// True if the object has been disposed. - /// - public bool IsDisposed - { - get { return mIsDisposed; } - } - - /// - /// The item count at the specified grid location. - /// - /// - /// The x-value of the grid location. [Limits: bounds[0] <= value <= bounds[2]] - /// - /// - /// The y-value of the grid location. [Limits: bounds[1] <= value <= bounds[3]] - /// - /// The item count at the specified grid location. - public int GetItemCountAt(int x, int y) - { - if (IsDisposed) - return -1; - return CrowdProximityGridEx.dtpgGetItemCountAt(root, x, y); - } - - /// - /// The cell size of the grid. - /// - /// - /// - /// Used for converting from grid units to world units. - /// - /// - /// The cell size of the grid. - public float GetCellSize() - { - if (IsDisposed) - return -1; - return CrowdProximityGridEx.dtpgGetCellSize(root); - } - - /// - /// Gets the bounds of the grid. [(minX, minY, maxX, maxY)] - /// - /// - /// To convert from grid units to world units, multipy by the grid's cell size. - /// - /// The bounds of the grid. - public int[] GetBounds() - { - if (IsDisposed) - return null; - int[] bounds = new int[4]; - CrowdProximityGridEx.dtpgGetBounds(root, bounds); - return bounds; - } - } -} diff --git a/critterai/.svn/pristine/7c/7c177e62b645c5024aa740862d468ffaf635e1e4.svn-base b/critterai/.svn/pristine/7c/7c177e62b645c5024aa740862d468ffaf635e1e4.svn-base deleted file mode 100644 index 685b62ff..00000000 --- a/critterai/.svn/pristine/7c/7c177e62b645c5024aa740862d468ffaf635e1e4.svn-base +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.nav; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using org.critterai.u3d.editor; -using org.critterai.nav.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(CAIBakedNavmesh))] -public sealed class CAIBakedNavmeshEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - CAIBakedNavmesh targ = (CAIBakedNavmesh)target; - - EditorGUILayout.Separator(); - - EditorGUILayout.LabelField("Status", (targ.HasNavmesh ? "Has mesh" : "Empty")); - EditorGUILayout.LabelField("Version", targ.Version.ToString()); - EditorGUILayout.LabelField("Input Scene", NavEditorUtil.SceneDisplayName(targ.BuildInfo)); - - EditorGUILayout.Separator(); - - NavmeshSceneDraw.Instance.OnGUI(targ, "Show Mesh", true, true); - - EditorGUILayout.Separator(); - - EditorGUILayout.BeginHorizontal(); - - GUI.enabled = targ.HasNavmesh; - if (GUILayout.Button("Save")) - { - string filePath = EditorUtility.SaveFilePanel( - "Save Navigation Mesh" - , "" - , targ.name - , "navmesh"); - SaveMesh(targ, filePath); - } - GUI.enabled = true; - - if (GUILayout.Button("Load")) - { - string filePath = EditorUtility.OpenFilePanel( - "Select Serialized Navmesh" - , "" - , "navmesh"); - if (LoadMesh(targ, filePath)) - GUI.changed = true; - } - - EditorGUILayout.EndHorizontal(); - - if (targ.HasNavmesh) - { - EditorGUILayout.Separator(); - - if (GUILayout.Button("Log Mesh State")) - Debug.Log(targ.GetMeshReport()); - } - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - private static bool LoadMesh(CAIBakedNavmesh targ, string filePath) - { - string msg = null; - - if (filePath.Length == 0) - return false; - - FileStream fs = null; - BinaryFormatter formatter = new BinaryFormatter(); - - try - { - fs = new FileStream(filePath, FileMode.Open); - System.Object obj = formatter.Deserialize(fs); - - NavStatus status = targ.Load((byte[])obj, null); - if ((status & NavStatus.Sucess) == 0) - msg = status.ToString(); - } - catch (System.Exception ex) - { - msg = ex.Message; - } - finally - { - if (fs != null) - fs.Close(); - } - - if (msg != null) - { - Debug.LogError(targ.name + ": BakedNavmesh: Load bytes failed: " - + msg); - return false; - } - - return true; - } - - private static void SaveMesh(CAIBakedNavmesh targ, string filePath) - { - if (filePath.Length == 0 || !targ.HasNavmesh) - return; - - FileStream fs = null; - BinaryFormatter formatter = new BinaryFormatter(); - - try - { - fs = new FileStream(filePath, FileMode.Create); - formatter.Serialize(fs, targ.GetNavmesh().GetSerializedMesh()); - } - catch (System.Exception ex) - { - Debug.LogError(targ.name + ": BakedNavmesh: Save bytes failed: " - + ex.Message); - } - finally - { - if (fs != null) - fs.Close(); - } - } - - [MenuItem(EditorUtil.NavAssetMenu + "Baked Navmesh", false, NavEditorUtil.NavAssetGroup)] - static void CreateAsset() - { - CAIBakedNavmesh item = EditorUtil.CreateAsset(NavEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } - - [MenuItem(EditorUtil.ViewMenu + "Hide Navmesh", true)] - static bool HideNavmeshValidate() - { - return NavmeshSceneDraw.Instance.IsShown(); - } - - [MenuItem(EditorUtil.ViewMenu + "Hide Navmesh", false, EditorUtil.ViewGroup)] - static void HideNavmesh() - { - NavmeshSceneDraw.Instance.Hide(); - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/7c/7cb26d4215aaf7ee04ba7fc8c7e99eb713705614.svn-base b/critterai/.svn/pristine/7c/7cb26d4215aaf7ee04ba7fc8c7e99eb713705614.svn-base deleted file mode 100644 index c1cca30a..00000000 --- a/critterai/.svn/pristine/7c/7cb26d4215aaf7ee04ba7fc8c7e99eb713705614.svn-base +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Represents the mesh data for a object. - /// - /// - /// - /// Warning: The serializable attributewill be removed in v0.5. Use - /// instead of serializing this object. - /// - /// - /// Represents a mesh of potentially overlapping convex polygons of between three and - /// vertices. The mesh exists within the context of an - /// axis-aligned bounding box (AABB) with vertices laid out in an evenly spaced grid - /// based on xz-plane and y-axis cells. - /// - /// - /// This class is not compatible with Unity serialization. - /// - /// - /// - /// Iterating the Polygons - /// - /// int[] pTargetVert = new int[2]; - /// - /// // Loop through the polygons. - /// for (int iPoly = 0; iPoly <polyCount; iPoly++) - /// { - /// int pPoly = iPoly * maxVertsPerPoly * 2; - /// - /// // Loop through the edges. - /// for (int iPolyVert = 0; iPolyVert <maxVertsPerPoly; iPolyVert++) - /// { - /// int iv = polys[pPoly + iPolyVert]; - /// - /// if (iv == NullIndex) - /// // Soft end of the polygon. - /// break; - /// - /// if (polys[pPoly + maxVertsPerPoly + iPolyVert] - /// == NullIndex) - /// { - /// // The edge is a solid border. - /// } - /// else - /// } - /// // The edge connects to another polygon. - /// } - /// - /// // Pointer to first edge vertex. - /// pTargetVert[0] = iv * 3; - /// - /// if (iPolyVert + 1 >= maxVertsPerPoly) - /// // Reached hard end of polygon. Loop back. - /// iv = polys[pPoly + 0]; - /// else - /// { - /// iv = polys[pPoly + iPolyVert + 1]; - /// if (iv == NullIndex) - /// // Reached soft send of polygon. Loop back. - /// iv = polys[pPoly + 0]; - /// } - /// // Pointer to second edge vertex. - /// pTargetVert[1] = iv * 3; - /// - /// for (int i = 0; i <2; i++) - /// { - /// int p = pTargetVert[i]; - /// int x = verts[p + 0]; - /// int y = verts[p + 1]; - /// int z = verts[p + 2]; - /// float worldX = boundsMin[0] + x * xzCellSize; - /// float worldY = boundsMin[1] + y * yCellSize; - /// float worldZ = boundsMin[2] + z * xzCellSize; - /// // Do something with the vertices. - /// } - /// } - /// } - /// - /// - /// - [Serializable] - public sealed class PolyMeshData - { - /// - /// Mesh vertices. - /// [(x, y, z) * vertCount] - /// - /// - /// - /// Minimum bounds and cell size is used to convert vertex coordinates into world space. - /// - /// - /// worldX = boundsMin[0] + vertX * xzCellSize - /// worldY = boundsMin[1] + vertY * yCellSize - /// worldZ = boundsMin[2] + vertZ * xzCellSize - /// - /// - public ushort[] verts; - - /// - /// Polygon and neighbor data. [Length: >= polyCount * 2 * maxVertsPerPoly] - /// - /// - /// - /// Each entry is 2 * MaxVertsPerPoly in length. - /// - /// The first half of the entry contains the indices of the polygon. The first instance of - /// indicates the end of the indices for the entry. - /// - /// - /// The second half contains indices to neighbor polygons. A value of - /// indicates no connection for the associated edge. - /// (Solid wall.) - /// - /// - /// Example: - /// - /// - /// MaxVertsPerPoly = 6
      - /// For the entry: - /// (1, 3, 4, 8, NullIndex, NullIndex, 18, NullIndex, 21, NullIndex, NullIndex, NullIndex) - ///
      - /// - /// (1, 3, 4, 8) defines a polygon with 4 vertices.
      - /// Edge 1->3 is shared with polygon 18.
      - /// Edge 4->8 is shared with polygon 21.
      - /// Edges 3->4 and 4->8 are border edges not shared with any other polygon. - ///
      - ///
      - public ushort[] polys; - - /// - /// The region id assigned to each polygon. [Length: >= polyCount] - /// - public ushort[] regions; - - /// - /// The flags assigned to each polygon. [Length: >= polyCount] - /// - public ushort[] flags; - - /// - /// The area assigned to each polygon. [Length: >= polyCount] - /// - /// - /// - /// During the standard build process, all walkable polygons get the default value - /// of . This value can then be changed to meet user - /// requirements. - /// - /// - public byte[] areas; - - /// - /// The number of vertices. - /// - public int vertCount; - - /// - /// The number of polygons. - /// - public int polyCount; - - /// - /// The maximum vertices per polygon. - /// [Limits: 3 <= value <= ] - /// - public int maxVertsPerPoly; - - /// - /// The minimum bounds of the mesh's AABB. - /// - public Vector3 boundsMin; - - /// - /// The maximum bounds of the mesh's AABB. - /// - public Vector3 boundsMax; - - /// - /// The xz-plane cell size. [Limit: >= ] - /// - public float xzCellSize; - - /// - /// The y-axis cell height. [Limit: >= ] - /// - public float yCellSize; - - /// - /// The AABB border size used to build the mesh. [Limit: >= 0] [Units: XZCellSize] - /// - public int borderSize; - - /// - /// The walkable height used to build the mesh. [Units: World] - /// - public float walkableHeight; - - /// - /// The walkable radius used to build the mesh. [Limit: >= 0] [Units: World] - /// - public float walkableRadius; - - /// - /// The maximum walkable step used to build the mesh. [Limit: >= 0] [Units: World] - /// - public float walkableStep; - - /// - /// Constructor. - /// - /// - /// The maximum veritices the vertex buffer can hold. [Limit: >= 3] - /// - /// - /// The maximum polygons the polygon buffer can hold. [Limit: > 0] - /// - /// - /// The maximum allowed vertices for a polygon. - /// [Limits: 3 <= value <= ] - /// - public PolyMeshData(int maxVerts - , int maxPolys - , int maxVertsPerPoly) - { - if (maxVerts < 3 - || maxPolys < 1 - || maxVertsPerPoly < 3 - || maxVertsPerPoly > NMGen.MaxAllowedVertsPerPoly) - { - return; - } - - polys = new ushort[maxPolys * 2 * maxVertsPerPoly]; - verts = new ushort[maxVerts * 3]; - areas = new byte[maxPolys]; - flags = new ushort[maxPolys]; - regions = new ushort[maxPolys]; - - this.maxVertsPerPoly = maxVertsPerPoly; - } - - /// - /// Clears all object data and resizes the buffers. - /// - /// - /// The maximum veritices the vertex buffer can hold. [Limit: >= 3] - /// - /// - /// The maximum polygons the polygon buffer can hold. [Limit: > 0] - /// - /// - /// The maximum allowed vertices for a polygon. - /// [Limits: 3 <= value <= ] - /// - public void Resize(int maxVerts - , int maxPolys - , int maxVertsPerPoly) - { - Resize(); - - if (maxVerts < 3 - || maxPolys < 1 - || maxVertsPerPoly < 3 - || maxVertsPerPoly > NMGen.MaxAllowedVertsPerPoly) - { - return; - } - - polys = new ushort[maxPolys * 2 * maxVertsPerPoly]; - verts = new ushort[maxVerts * 3]; - areas = new byte[maxPolys]; - flags = new ushort[maxPolys]; - regions = new ushort[maxPolys]; - - this.maxVertsPerPoly = maxVertsPerPoly; - } - - private void Resize() - { - vertCount = 0; - polyCount = 0; - maxVertsPerPoly = 0; - boundsMin = Vector3Util.Zero; - boundsMax = Vector3Util.Zero; - xzCellSize = 0; - yCellSize = 0; - borderSize = 0; - walkableHeight = 0; - walkableStep = 0; - walkableRadius = 0; - polys = null; - verts = null; - areas = null; - flags = null; - regions = null; - } - - /// - /// Checks the size of the buffers to see if they are large enough to hold the specified - /// data. - /// - /// The maximum vertices the vertex buffer needs to hold. - /// The maximum polygons the polygon buffer needs to hold. - /// The maximum allowed vertices for a polygon. - /// True if all buffers are large enough to fit the data. - public bool CanFit(int vertCount - , int polyCount - , int maxVertsPerPoly) - { - if (maxVertsPerPoly != this.maxVertsPerPoly - || polys == null - || polys.Length < polyCount * 2 * maxVertsPerPoly - || verts == null || verts.Length < vertCount * 3 - || areas == null || areas.Length < polyCount - || flags == null || flags.Length < polyCount - || regions == null || regions.Length < polyCount) - { - return false; - } - return true; - } - } -} diff --git a/critterai/.svn/pristine/7d/7d1b9ac34cfce6bc934b5785099f566db8ccfac6.svn-base b/critterai/.svn/pristine/7d/7d1b9ac34cfce6bc934b5785099f566db8ccfac6.svn-base deleted file mode 100644 index 4b262a51..00000000 Binary files a/critterai/.svn/pristine/7d/7d1b9ac34cfce6bc934b5785099f566db8ccfac6.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/7d/7ddd25420f1995579df4a1e0ab0ae0d379d92c16.svn-base b/critterai/.svn/pristine/7d/7ddd25420f1995579df4a1e0ab0ae0d379d92c16.svn-base deleted file mode 100644 index 2e470e24..00000000 --- a/critterai/.svn/pristine/7d/7ddd25420f1995579df4a1e0ab0ae0d379d92c16.svn-base +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.u3d; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal class SelectionDebugView - { - private bool mEnabled; - private bool mShow; - private bool mIncludeRootTile; - private bool mNeedsRepaint; - - public bool NeedsRepaint - { - get { return mNeedsRepaint; } - set { mNeedsRepaint = value; } - } - - public bool Enabled - { - get { return mEnabled; } - set - { - if (mEnabled != value) - { - mEnabled = value; - mNeedsRepaint = true; - } - } - } - - public bool Show - { - get { return mShow; } - set - { - if (mShow != value) - { - mShow = value; - mNeedsRepaint = true; - } - } - } - - public bool IncludeRootTile - { - get { return mIncludeRootTile; } - set - { - if (mIncludeRootTile != value) - { - mIncludeRootTile = value; - mNeedsRepaint = true; - } - } - } - - public void OnRenderObject(NavmeshBuild build, TileSelection selection) - { - if (!build) - return; - - TileSetDefinition tdef = build.TileSetDefinition; - - if (!mShow || !mEnabled || build != selection.Build || tdef == null) - return; - - Color color = ControlUtil.SelectionColor; - - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - - GL.Color(color); - - if (selection.Validate()) - { - Vector3 bmin; - Vector3 bmax; - Vector3 trash; - - TileZone zone = selection.Zone; - - tdef.GetTileBounds(zone.xmin, zone.zmin, true, out bmin, out trash); - tdef.GetTileBounds(zone.xmax, zone.zmax, true, out trash, out bmax); - - DebugDraw.AppendBounds(bmin, bmax); - - if (mIncludeRootTile) - { - GL.Color(new Color(0.93f, 0.58f, 0.11f)); // Orange - - tdef.GetTileBounds(selection.SelectedX, selection.SelectedZ, true - , out bmin, out bmax); - - DebugDraw.AppendBounds(bmin, bmax); - } - } - else - { - Vector3 bmax = tdef.BoundsMin; - float tileSize = build.Config.TileWorldSize; - bmax.x += tileSize * tdef.Width; - bmax.y = tdef.BoundsMax.y; - bmax.z += tileSize * tdef.Depth; - - DebugDraw.AppendBounds(tdef.BoundsMin, bmax); - } - - GL.End(); - } - } -} diff --git a/critterai/.svn/pristine/7e/7ef80f47f0a017f51dac15741e01cb4eb24914da.svn-base b/critterai/.svn/pristine/7e/7ef80f47f0a017f51dac15741e01cb4eb24914da.svn-base deleted file mode 100644 index c70c9008..00000000 --- a/critterai/.svn/pristine/7e/7ef80f47f0a017f51dac15741e01cb4eb24914da.svn-base +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav; -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class NavmeshBuildHelper - { - private readonly NavmeshBuild mBuild; - private readonly UnityBuildContext mContext = new UnityBuildContext(); - - public NavmeshBuildHelper(NavmeshBuild build) - { - if (!build) - throw new System.ArgumentNullException(); - - this.mBuild = build; - } - - public void Build() - { - if (!mBuild) - return; - - mBuild.ResetBuild(); - - // Note: The 'finally' takes care of all cleanup. - - try - { - EditorUtility.DisplayCancelableProgressBar("Build & Bake" - , "Preparing..." - , 0); - - // Prepare the build. - - if (!CompileInput()) - return; - - if (!InitializeBuild()) - return; - - // Build the tiles. - NavmeshParams nconfig = null; - NavmeshTileData[] tiles = null; - bool success = true; - - if (mBuild.TileSetDefinition == null) - { - if (!BuildSingleTile()) - return; - - tiles = new NavmeshTileData[1] { mBuild.BuildData.GetTileData(0, 0) }; - - nconfig = NavUtil.DeriveConfig(tiles[0]); - } - else if (BuildMultiTiled()) - { - success = mBuild.BuildData.GetMeshBuildData(mBuild.TileSetDefinition.BoundsMin - , mBuild.TileSetDefinition.TileWorldSize - , out nconfig, out tiles); - } - else - return; - - if (!success) - { - mContext.PostError("Navigation mesh creation failed.", mBuild); - return; - } - - // Bake the mesh. - - NavStatus nstatus = - mBuild.BuildTarget.Load(nconfig, tiles, NMBEditorUtil.GetConfig(mBuild)); - - if ((nstatus & NavStatus.Sucess) == 0) - mContext.PostError("Bake to target: Target reported failure.", mBuild); - else - EditorUtility.SetDirty((Object)mBuild.BuildTarget); - } - finally - { - mBuild.ResetBuild(); - EditorUtility.ClearProgressBar(); - } - } - - private bool InitializeBuild() - { - mContext.ResetLog(); - - if (!mBuild.InitializeBuild(mContext, false)) - { - mContext.PostError("Build initialization failed.", mBuild); - return false; - } - // Not helpful. - //else - // mContext.PostTrace("Initialized build.", mBuild); - - mContext.ResetLog(); - - return true; - } - - private bool BuildSingleTile() - { - TileBuildData tdata = mBuild.BuildData; - NMGenConfig config = mBuild.Config; - InputGeometry geom = mBuild.InputGeom; - - mContext.ResetLog(); - - /* - * Design note: - * - * Not using the build task since it doesn't provide enough progress - * feedback for a single tile. - * - */ - - // Create the NMGen builder. - - IncrementalBuilder builder = IncrementalBuilder.Create(config.GetConfig() - , config.ResultOptions - , geom - , mBuild.NMGenProcessors); - - if (builder == null) - { - mContext.PostError("Unexpected failure creating NMGen builder.", mBuild); - tdata.SetAsFailed(0, 0); - return false; - } - else if (builder.IsFinished) - { - if (builder.State == NMGenState.NoResult) - { - mContext.PostError("NMGen build did not produce a result. (Early exit.)" - , builder.GetMessages(), mBuild); - tdata.SetAsFailed(0, 0); - return false; - } - else - { - mContext.PostError("Unexpected NMGen builder completion." - , builder.GetMessages(), mBuild); - tdata.SetAsFailed(0, 0); - return false; - } - } - - mBuild.BuildData.SetAsInProgress(0, 0); - - // Run the NMGen builder. - - while (!builder.IsFinished) - { - if (EditorUtility.DisplayCancelableProgressBar("Build Single Tile Mesh" - , IncrementalBuilder.ToLabel(builder.State) - , IncrementalBuilder.ToProgress(builder.State))) - { - return false; - } - - builder.Build(); - } - - // Handle NMGen failures. - - mContext.Log(builder.GetMessages()); // Single tile build. So go ahead an record. - - switch (builder.State) - { - case NMGenState.Aborted: - - mContext.PostError("NMGen build failed.", mBuild); - tdata.SetAsFailed(0, 0); - return false; - - case NMGenState.NoResult: - - mContext.PostError("NMGen build did not produce a result.", mBuild); - tdata.SetAsFailed(0, 0); - return false; - } - - mContext.Log(string.Format("Completed NMGen build: {0} polygons." - , builder.Result.PolyMesh.PolyCount) - , mBuild); - - // Build the tile. - - NMGenAssets result = builder.Result; - - NavmeshTileBuildData tbd = org.critterai.nmbuild.NMBuild.GetBuildData( - mContext, 0, 0 - , result.PolyMesh.GetData(false), result.DetailMesh.GetData(false) - , mBuild.Connections - , (config.BuildFlags & NMGenBuildFlag.BVTreeEnabled) != 0); - - if (tbd == null) - { - // No need to log the error. The above method takes care of that. - tdata.SetAsFailed(0, 0); - return false; - } - - NavmeshTileData td = NavmeshTileData.Create(tbd); - - if (td.Size == 0) - { - mContext.PostError( - "Could not create {0} object. Cause unknown." + typeof(NavmeshTileData) - , mBuild); - tdata.SetAsFailed(0, 0); - return false; - } - - // Finalize the tile. - - tdata.SetWorkingData(0, 0, result.PolyMesh, result.DetailMesh); - tdata.SetWorkingData(0, 0, td, tbd.PolyCount); - - mContext.PostTrace("Completed single tile build.", mBuild); - - return true; - } - - private bool BuildMultiTiled() - { - TileSetDefinition tdef = mBuild.TileSetDefinition; - TileBuildData tdata = mBuild.BuildData; - - mContext.ResetLog(); - - int total = tdef.Width * tdef.Depth; - - string msg = string.Format("Multi-tile build: {0} tiles ({1}x{2})" - , total, tdef.Width, tdef.Depth); - - mContext.Log(msg, mBuild); - - int count = 0; // For the progress bar. - for (int tx = 0; tx < tdef.Width; tx++) - { - for (int tz = 0; tz < tdef.Depth; tz++) - { - count++; - - string tileText = string.Format("({0},{1})", tx, tz); - - if (EditorUtility.DisplayCancelableProgressBar("Multi-tiled Build & Bake" - , string.Format("Tile: {0} ({1} of {2})", tileText, count, total) - , (float)count / total)) - { - return false; - } - - // Create the NMGen builder. - - IncrementalBuilder builder = IncrementalBuilder.Create(tx, tz - , mBuild.Config.ResultOptions - , mBuild.TileSetDefinition - , mBuild.NMGenProcessors); - - if (builder == null) - { - mContext.PostError( - "Unexpected failure creating NMGen builder: Tile: " + tileText - , mBuild); - tdata.SetAsFailed(tx, tz); - return false; - } - - mBuild.BuildData.SetAsInProgress(tx, tz); - - // Create and run the build task. - - NMGenTask ntask = NMGenTask.Create(builder, 0); - - ntask.Run(); - - if (ntask.TaskState == BuildTaskState.Aborted) - { - mContext.PostError("NMGen build task failed: Tile: " + tileText - , ntask.Messages, mBuild); - tdata.SetAsFailed(tx, tz); - return false; - } - - NMGenAssets nr = ntask.Result; - - if (nr.NoResult) - { - mContext.PostTrace("NMGen complete. Empty tile: " + tileText - , builder.GetMessages() - , mBuild); - tdata.SetAsEmpty(tx, tz); - continue; - } - - msg = string.Format("NMGen complete. Tile {0} has {1} polygons." - , tileText, nr.PolyMesh.PolyCount); - - mContext.PostTrace(msg, builder.GetMessages(), mBuild); - - TileBuildTask ttask = TileBuildTask.Create(tx, tz - , nr.PolyMesh.GetData(false), nr.DetailMesh.GetData(false) - , mBuild.Connections - , (mBuild.Config.BuildFlags & NMGenBuildFlag.BVTreeEnabled) != 0 - , false, 0); - - ttask.Run(); - - if (ttask.TaskState == BuildTaskState.Aborted) - { - mContext.PostError("Tile build task failed: Tile: " + tileText - , ttask.Messages - , mBuild); - tdata.SetAsFailed(tx, tz); - return false; - } - - TileBuildAssets tr = ttask.Result; - - tdata.SetWorkingData(tx, tz, nr.PolyMesh, nr.DetailMesh); - tdata.SetWorkingData(tx, tz, tr.Tile, tr.PolyCount); - } - } - - int bakeable = tdata.BakeableCount(); - - if (bakeable == 0) - { - mContext.PostError("Build did not produce any usuable tiles. (All tiles empty?)" - , mBuild); - return false; - } - - msg = string.Format("Tile build complete. {0} tiles produced. {1} empty tiles." - , bakeable, tdata.GetStateCount(TileBuildState.Empty)); - - mContext.PostTrace(msg, mBuild); - - return true; - } - - private bool CompileInput() - { - mContext.ResetLog(); - - InputAssets assets = BuildInput(false); - - if (assets.geometry == null) - { - mContext.PostError("No input geometry generated.", mBuild); - return false; - } - - org.critterai.geom.TriangleMesh mesh = assets.geometry; - - InputGeometryBuilder gbuilder = InputGeometryBuilder.UnsafeCreate(mesh - , assets.areas - , mBuild.Config.GetConfig().WalkableSlope - , true); - - if (gbuilder == null) - { - mContext.PostError("Could not create input geometry builder. (Internal error.)" - , mBuild); - return false; - } - - gbuilder.BuildAll(); - - if (mBuild.SetInputData(mContext, gbuilder.Result - , assets.info, assets.processors, assets.conns - , false)) - { - mContext.PostTrace("Input compile complete.", mBuild); - } - - return true; - } - - public InputAssets BuildInput() - { - if (!mBuild) - return new InputAssets(); - return BuildInput(true); - } - - private InputAssets BuildInput(bool ownProgress) - { - InputBuildOption options = - (mBuild.AutoCleanGeometry ? InputBuildOption.AutoCleanGeometry : 0); - - InputBuilder builder = - InputBuilder.Create(mBuild.SceneQuery, mBuild.GetInputProcessors(), options); - - if (builder == null) - { - mContext.LogError("Could not create input builder.", mBuild); - return new InputAssets(); - } - - try - { - while (!builder.IsFinished) - { - builder.Build(); - if (EditorUtility.DisplayCancelableProgressBar("Compile Input" - , InputBuilder.ToLabel(builder.State) - , InputBuilder.ToProgress(builder.State))) - { - return new InputAssets(); - } - } - } - finally - { - if (ownProgress) - EditorUtility.ClearProgressBar(); - } - - mContext.Log(builder.Messages); - - if (builder.State != InputBuildState.Complete) - { - mContext.LogError("Input builder aborted.", mBuild); - return new InputAssets(); - } - - InputAssets assets = builder.Result; - - org.critterai.geom.TriangleMesh mesh = assets.geometry; - - if (!InputGeometryBuilder.IsValid(mesh, assets.areas)) - { - mContext.LogError("Input geometry failed validation. (Malformed data.)", mBuild); - return new InputAssets(); - } - - return builder.Result; - } - } -} diff --git a/critterai/.svn/pristine/7f/7f7c9e08bbfbfa26fcca5aa975def4e5f378f2ae.svn-base b/critterai/.svn/pristine/7f/7f7c9e08bbfbfa26fcca5aa975def4e5f378f2ae.svn-base deleted file mode 100644 index 579933f2..00000000 Binary files a/critterai/.svn/pristine/7f/7f7c9e08bbfbfa26fcca5aa975def4e5f378f2ae.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/7f/7ff2b1aa4f043f634f91e55e46a30d9704bbc923.svn-base b/critterai/.svn/pristine/7f/7ff2b1aa4f043f634f91e55e46a30d9704bbc923.svn-base deleted file mode 100644 index 364aa45d..00000000 --- a/critterai/.svn/pristine/7f/7ff2b1aa4f043f634f91e55e46a30d9704bbc923.svn-base +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nav -{ - /// - /// The header data for a polygon's detail mesh in a . - /// - /// - /// - /// All indices refer to the vertex and triangle data in the associated - /// . - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct NavmeshDetailMesh - { - /// - /// The index of the base vertex for the detail mesh. - /// - public uint vertBase; - - /// - /// The index of the base triangle for the detail mesh. - /// - public uint triBase; - - /// - /// The number of vertices in the detail mesh. - /// - public byte vertCount; - - /// - /// The number of triangles in the detail mesh. - /// - public byte triCount; - } -} diff --git a/critterai/.svn/pristine/80/807c143b15875f765f07263b834db70dc621682d.svn-base b/critterai/.svn/pristine/80/807c143b15875f765f07263b834db70dc621682d.svn-base deleted file mode 100644 index 630a5942..00000000 --- a/critterai/.svn/pristine/80/807c143b15875f765f07263b834db70dc621682d.svn-base +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// An off-mesh connection not associated with a object. - /// - /// - /// - /// This is a convenience element for use during the build process. - /// - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct OffMeshConnection - { - /// - /// The start point of the connection. - /// - public Vector3 start; - - /// - /// The end point of the connection. - /// - public Vector3 end; - - /// - /// The radius of the start and end points. [Limit: >0] - /// - public float radius; - - - /// - /// The direction of the connection. [Limit: 0 or 1] - /// - /// - /// A vlaue of indicates bi-directional. - /// - public byte direction; - - /// - /// The area of the connection. [Limit: <= ]. - /// - public byte area; - - /// - /// The connection flags. - /// - public ushort flags; - - /// - /// The id of the off-mesh connection. (User defined.) - /// - /// - /// - /// This value has no meaning to the core navigation system. Its purpose is entirely user - /// defined. - /// - /// - public uint userId; - - /// - /// Constructor. - /// - /// The start point. - /// The end point. - /// The radius of the start and end points. [Limit: >0] - /// True if the connection is bi-directional. - /// The area. [Limit: <= ]. - /// The connection flags. - /// The id of the off-mesh connection. (User defined.) - public OffMeshConnection(Vector3 start, Vector3 end - ,float radius, bool isBidDrectional, byte area, ushort flags, uint userId) - { - this.start = start; - this.end = end; - this.radius = MathUtil.ClampToPositiveNonZero(radius); - direction = (byte)(isBidDrectional ? 1 : 0); - this.area = NavUtil.ClampArea(area); - this.flags = flags; - this.userId = userId; - } - - /// - /// True if the conneciton is bi-directional. - /// - public bool IsBiDirectional - { - get { return (direction == 1); } - set { direction = (byte)(value ? 1 : 0); } - } - } -} diff --git a/critterai/.svn/pristine/81/812c6c4a75c97a09959c8051766ee32986e865e4.svn-base b/critterai/.svn/pristine/81/812c6c4a75c97a09959c8051766ee32986e865e4.svn-base deleted file mode 100644 index 0b355a94..00000000 --- a/critterai/.svn/pristine/81/812c6c4a75c97a09959c8051766ee32986e865e4.svn-base +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.nav.rcn -{ - internal static class CrowdAgentEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcaGetAgentParams(IntPtr agent - , ref CrowdAgentParams config); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcaGetAgentCorners(IntPtr agent - , [In, Out] CornerData resultData); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcaGetAgentCoreData(IntPtr agent - , [In, Out] CrowdAgentCoreState resultData); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtcaGetAgentNeighbors(IntPtr agent - , [In, Out] CrowdNeighbor[] neighbors - , int neighborsSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcaGetPathCorridorData(IntPtr agent - , [In, Out] PathCorridorData corridor); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcaGetLocalBoundary(IntPtr agent - , [In, Out] LocalBoundaryData boundary); - } -} diff --git a/critterai/.svn/pristine/81/816dedbd75404ee83dd85d3a2bb80ead7aa5e5d7.svn-base b/critterai/.svn/pristine/81/816dedbd75404ee83dd85d3a2bb80ead7aa5e5d7.svn-base deleted file mode 100644 index 8e4fb880..00000000 --- a/critterai/.svn/pristine/81/816dedbd75404ee83dd85d3a2bb80ead7aa5e5d7.svn-base +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; - -namespace org.critterai.nav -{ - /// - /// Represents tile data extracted from a object. - /// - /// - public struct NavmeshTileExtract - { - /// - /// The tile header. - /// - public NavmeshTileHeader header; - - /// - /// The packed tile data. - /// - public byte[] data; - - /// - /// The tile reference in the original mesh. - /// - public uint tileRef; - } -} diff --git a/critterai/.svn/pristine/81/81727183fa44e19675d7bb00464c88c4ebf30390.svn-base b/critterai/.svn/pristine/81/81727183fa44e19675d7bb00464c88c4ebf30390.svn-base deleted file mode 100644 index bbd1044e..00000000 --- a/critterai/.svn/pristine/81/81727183fa44e19675d7bb00464c88c4ebf30390.svn-base +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav.rcn -{ - internal static class CrowdManagerEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtcDetourCrowdAlloc(int maxAgents - , float maxAgentRadius - , IntPtr navmesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcDetourCrowdFree(IntPtr crowd); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcSetObstacleAvoidanceParams(IntPtr crowd - , int index - , [In] CrowdAvoidanceParams obstacleParams); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcGetObstacleAvoidanceParams(IntPtr crowd - , int index - , [In, Out] CrowdAvoidanceParams config); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtcGetAgent(IntPtr crowd, int idx); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtcGetAgentCount(IntPtr crowd); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtcAddAgent(IntPtr crowd - , [In] ref Vector3 pos - , ref CrowdAgentParams agentParams - , ref IntPtr agent - , ref CrowdAgentCoreState initialState); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcUpdateAgentParameters(IntPtr crowd - , int index - , ref CrowdAgentParams agentParams); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcRemoveAgent(IntPtr crowd - , int index); - - /* - * On the native side, the query filter is a constant pointer. But I'm - * purposefully not protecting it on the managed side. - * I want the filter to be mutable and this is a dirty but quick way - * of doing it. - */ - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtcGetFilter(IntPtr crowd); - - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcGetQueryExtents(IntPtr crowd - , ref Vector3 extents); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtcGetVelocitySampleCount(IntPtr crowd); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtcGetGrid(IntPtr crowd); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtcUpdate(IntPtr crowd - , float deltaTime - , [In, Out] CrowdAgentCoreState[] coreStates); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtcGetNavMeshQuery(IntPtr crowd); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtcRequestMoveTarget(IntPtr crowd - , int agentIndex - , NavmeshPoint position); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtcAdjustMoveTarget(IntPtr crowd - , int agentIndex - , NavmeshPoint position); - } -} diff --git a/critterai/.svn/pristine/81/81911ee8c7d6191938ffc42fbd142c4627b5219f.svn-base b/critterai/.svn/pristine/81/81911ee8c7d6191938ffc42fbd142c4627b5219f.svn-base deleted file mode 100644 index a0c9ab7b..00000000 Binary files a/critterai/.svn/pristine/81/81911ee8c7d6191938ffc42fbd142c4627b5219f.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/82/826c35a4fd5d1c2869af6a9bb66f0e71d3b52d2a.svn-base b/critterai/.svn/pristine/82/826c35a4fd5d1c2869af6a9bb66f0e71d3b52d2a.svn-base deleted file mode 100644 index a42425fa..00000000 --- a/critterai/.svn/pristine/82/826c35a4fd5d1c2869af6a9bb66f0e71d3b52d2a.svn-base +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.nav.u3d.editor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal abstract class BuilderControl - : BuildControl - { - // TODO: EVAL: v0.5: Try for better solution. - // Basically, this only adds shared input build functionality. - - private MiniInputCompile mInputCompile = null; - - protected bool IsBaseBusy { get { return (mInputCompile != null); } } - - public override void Exit() - { - Context.AbortAllReqests("Exiting build."); - mInputCompile = null; - - base.Exit(); - } - - protected void OnGUIMainStandard() - { - if (mInputCompile != null) - { - Rect area = Context.MainArea; - - area = new Rect(area.x + area.width * 0.25f - , area.y + area.height * 0.66f - , area.width * 0.50f - , 25); - - mInputCompile.OnGUI(area); - } - } - - protected bool OnGUIStandardButtons() - { - bool result = false; - - NavmeshBuild build = Context.Build; - - if (!build) - return result; - - bool guiEnabled = GUI.enabled; - - GUI.enabled = guiEnabled - && mInputCompile == null - && Context.TaskCount == 0 - && !NavEditorUtil.SceneMismatch(build.BuildTarget.BuildInfo); - - if (GUILayout.Button("Recompile Input")) - { - mInputCompile = new MiniInputCompile(Context); - - if (mInputCompile.IsFinished) - mInputCompile = null; - } - - GUI.enabled = guiEnabled - && mInputCompile == null - && Context.TaskCount == 0; - - if (GUILayout.Button("Reinitialize Builder")) - { - result = true; - build.DiscardBuildData(); - } - - GUI.enabled = guiEnabled; - - return result; - } - - public override void Update() - { - base.Update(); - - if (Context == null || mInputCompile == null) - return; - - mInputCompile.Update(); - - if (!mInputCompile.IsFinished) - return; - - NavmeshBuild build = Context.Build; - - if (!build) - return; - - UnityBuildContext mLogger = new UnityBuildContext(); - - if (mInputCompile.HasData) - { - if (!build.SetInputData(mLogger, mInputCompile.Geometry - , mInputCompile.Info, mInputCompile.Processors, mInputCompile.Connections - , true)) - { - mLogger.PostError("Could not apply input data.", build); - } - } - else - mLogger.PostError("Input compile did not produce anything.", build); - - mInputCompile = null; - } - } -} diff --git a/critterai/.svn/pristine/82/82cbcc6bd76455d80bfe8497b8c7c1e0c41a4897.svn-base b/critterai/.svn/pristine/82/82cbcc6bd76455d80bfe8497b8c7c1e0c41a4897.svn-base deleted file mode 100644 index d061de92..00000000 --- a/critterai/.svn/pristine/82/82cbcc6bd76455d80bfe8497b8c7c1e0c41a4897.svn-base +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nmbuild")] -[assembly: AssemblyDescription( - "Scene related navigation mesh build extensions for the Unity Editor.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/83/83a768a4ff0cf69a2b45bc51c4fd13f303343360.svn-base b/critterai/.svn/pristine/83/83a768a4ff0cf69a2b45bc51c4fd13f303343360.svn-base deleted file mode 100644 index a5290a3a..00000000 --- a/critterai/.svn/pristine/83/83a768a4ff0cf69a2b45bc51c4fd13f303343360.svn-base +++ /dev/null @@ -1,10 +0,0 @@ -This directory contains shared project libraries. - -Compiled project libraries are not normally stored in -the repository. An exception is made when a library is -meant to be shared between projects. In such cases the -compiled library is placed here so that it is available for -dependant project builds and packaging. - -(The use of this directory is depreciated. New projects usually include -a direct reference to the shared library source.) diff --git a/critterai/.svn/pristine/83/83abe4453ba498dcb496d1b054c42c132b9c0269.svn-base b/critterai/.svn/pristine/83/83abe4453ba498dcb496d1b054c42c132b9c0269.svn-base deleted file mode 100644 index f822bd5a..00000000 --- a/critterai/.svn/pristine/83/83abe4453ba498dcb496d1b054c42c132b9c0269.svn-base +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Filters out all components with the specified tags. (Editor Only) -/// -[System.Serializable] -public sealed class TagInputFilter - : ScriptableObject, IInputBuildProcessor -{ - /// - /// True if the filter should apply to components with a tagged parent. - /// - public bool recursive; - - /// - /// The tags that should result in filtering. - /// - public List tags = new List(); - - [SerializeField] - private int mPriority = NMBuild.DefaultPriority; - - /// - /// The priority of the processor. - /// - public int Priority - { - get { return mPriority; } - set { mPriority = NMBuild.ClampPriority(value); } - } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// Multiple processors of this type are allowed. (Always true.) - /// - public bool DuplicatesAllowed { get { return true; } } - - /// - /// Processes the context. - /// - /// - /// - /// Applied during the state. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (state != InputBuildState.FilterComponents) - return true; - - context.info.filterCount++; - - if (tags == null) - { - context.Log(name + " Mesh exclusion list is null. (Invalid processor state.)", this); - return false; - } - - if (tags.Count == 0) - { - context.Log(name + ": Filter is inactive. No tags configured to filter.", this); - return true; - } - - List targetItems = context.components; - - int removed = 0; - for (int iTarget = targetItems.Count - 1; iTarget >= 0; iTarget--) - { - Component targetItem = targetItems[iTarget]; - - if (!targetItem) - continue; - - int iSource = tags.IndexOf(targetItem.tag); - - if (iSource != -1) - { - // One of the tags is on this item. - targetItems.RemoveAt(iTarget); - removed++; - continue; - } - - if (recursive) - { - // Need to see if the tag is on any parent. - Transform parent = targetItem.transform.parent; - - while (parent != null) - { - iSource = tags.IndexOf(parent.tag); - - if (iSource != -1) - { - // One of the tags is on this item. - targetItems.RemoveAt(iTarget); - removed++; - break; - } - parent = parent.parent; - } - } - } - - if (removed > 0) - context.Log(string.Format("{0}: Filtered out {1} components.", name, removed), this); - else - context.Log(name + ": No components filtered.", this); - - return true; - } -} diff --git a/critterai/.svn/pristine/85/85228392e557cb5b94c119cd0f4b2357b2db8c5f.svn-base b/critterai/.svn/pristine/85/85228392e557cb5b94c119cd0f4b2357b2db8c5f.svn-base deleted file mode 100644 index d009292c..00000000 --- a/critterai/.svn/pristine/85/85228392e557cb5b94c119cd0f4b2357b2db8c5f.svn-base +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.nmgen; -using org.critterai.u3d.editor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class NMGenConfigControl - : BuildControl - { - private const float MarginSize = ControlUtil.MarginSize; - - private const string DefaultStatusMessage = - "Values in parentheses represent the effective" - + " world units based on cell size."; - - public override void Exit() - { - base.Exit(); - Logger.ResetLog(); - } - - protected override void OnGUIMain() - { - NavmeshBuild build = Context.Build; - - if (!build) - return; - - NMGenConfig config = build.Config; - - GUI.Box(Context.MainArea, ""); - - Rect colA = Context.MainArea; - colA.width = colA.width * 0.5f - 4 * MarginSize; - - Rect colB = colA; - - colA.x += MarginSize; - - colB.x += Context.MainArea.width * 0.5f + MarginSize; - - GUILayout.BeginArea(colA); - - OnGUIPrimary(build, config, false); - - if (GUI.changed) - // Conservative: Just in case the tile size was altered. - DebugContext.NeedsRepaint = true; - - GUILayout.EndArea(); - - GUILayout.BeginArea(colB); - OnGUIAdvanced(config, false); - GUILayout.EndArea(); - - if (GUI.changed) - build.IsDirty = true; - } - - protected override void OnGUIButtons() - { - NavmeshBuild build = Context.Build; - - if (!build) - return; - - NMGenConfig config = build.Config; - - // Buttons area. - - ControlUtil.BeginButtonArea(Context.ButtonArea); - - // Standard config buttons. - - OnGUIButtons(build, config, false); - - // Build initialialization buttons. - - bool guiEnabled = GUI.enabled; - - bool targetOK = build.CanLoadFromTarget(null, false); - - GUILayout.Space(MarginSize * 2); - - if (build.BuildState == NavmeshBuildState.Buildable) - { - GUI.enabled = (Context.TaskCount == 0); - - if (GUILayout.Button("Reinitialize Builder")) - build.DiscardBuildData(); - } - else if (build.HasInputData) - { - if (targetOK) - { - if (GUILayout.Button("Load Target's Config")) - { - if (!build.SetConfigFromTarget(Logger)) - Logger.PostError("Could not load target config.", Context.Build); - Logger.ResetLog(); - } - - GUILayout.Space(MarginSize); - GUILayout.Label("Initialize Build:"); - GUILayout.Space(MarginSize); - - if (GUILayout.Button("From Scratch", ControlUtil.HighlightedButton)) - InitializeBuild(false); - - if (GUILayout.Button("Based on Target")) - InitializeBuild(true); - - GUILayout.Space(MarginSize); - GUILayout.Box("Basing your build on the target's navigation" - + " mesh will automatically lock you in to the" - + " target's configuration settings." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - } - else - { - if (GUILayout.Button("Ready to Build", ControlUtil.HighlightedButton)) - InitializeBuild(false); - } - } - - GUI.enabled = guiEnabled; - - ViewOption option = build.HasInputData - ? (ViewOption.Grid | ViewOption.Input) : 0; - - DebugContext.SetViews(option); - - ControlUtil.OnGUIStandardButtons(Context, DebugContext, true); - - ControlUtil.EndButtonArea(); - - if (GUI.changed) - build.IsDirty = true; - } - - private void InitializeBuild(bool fromTarget) - { - if (!Context.Build.InitializeBuild(Logger, fromTarget)) - Logger.PostError("Could not initialize the build.", Context.Build); - } - - public static void OnGUIPrimary(NavmeshBuild build - , NMGenConfig config - , bool includeSlope) - { - if (!build) - return; - - bool guiEnabled = GUI.enabled; - - EditorGUIUtility.LookLikeControls(155); - - float xz = config.XZCellSize; - float y = config.YCellSize; - float a = xz * xz; - float effective; - - ////////////////////////////////////////////////////////////// - - GUILayout.Label("Agent Settings"); - GUILayout.Space(MarginSize); - - TileBuildData tdata = build.BuildData; - - GUI.enabled = guiEnabled && (tdata == null); - - effective = (float)Mathf.Ceil(config.WalkableHeight / y) * y; - - config.WalkableHeight = EditorGUILayout.FloatField( - NMGenConfig.HeightLabel + Effective(effective) - , config.WalkableHeight); - - - effective = (float)Mathf.Floor(config.WalkableStep / y) * y; - config.WalkableStep = EditorGUILayout.FloatField( - NMGenConfig.StepLabel + Effective(effective) - , config.WalkableStep); - - effective = (float)Mathf.Ceil(config.WalkableRadius / xz) * xz; - config.WalkableRadius = EditorGUILayout.FloatField( - NMGenConfig.RadiusLabel + Effective(effective) - , config.WalkableRadius); - - GUI.enabled = guiEnabled; - - if (includeSlope) - { - config.WalkableSlope = EditorGUILayout.FloatField( - NMGenConfig.SlopeLabel - , config.WalkableSlope); - } - - ///////////////////////////////////////////////////////////////// - - GUILayout.Space(2 * MarginSize); - GUILayout.Label("Resolution and Tile Settings"); - GUILayout.Space(MarginSize); - - GUI.enabled = guiEnabled && (tdata == null); - - config.XZCellSize = EditorGUILayout.FloatField( - NMGenConfig.XZSizeLabel - , config.XZCellSize); - - config.YCellSize = EditorGUILayout.FloatField( - NMGenConfig.YSizeLabel - , config.YCellSize); - - config.TileSize = EditorGUILayout.IntField( - NMGenConfig.TileSizeLabel - + " (" + config.TileSize * config.XZCellSize + ")" - , config.TileSize); - - - config.BorderSize = EditorGUILayout.IntField( - NMGenConfig.HFBorderLabel - , config.BorderSize); - - GUI.enabled = guiEnabled; - - int derBorderSize = NMGenConfig.DeriveBorderSize(config); - float derXZ = NMGenConfig.DeriveXZCellSize(config); - float derY = NMGenConfig.DeriveYCellSize(config); - - if ((config.TileSize == 0 && config.BorderSize != derBorderSize) - || config.BorderSize < derBorderSize - || config.XZCellSize > derXZ - || config.YCellSize > derY) - { - GUILayout.Space(MarginSize); - - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - - sb.AppendLine("Recommendations:"); - - if (config.XZCellSize > derXZ) - sb.AppendLine(NMGenConfig.XZSizeLabel + " of " + derXZ + " or less."); - - if (config.YCellSize > derY) - sb.AppendLine(NMGenConfig.YSizeLabel + " of " + derY + " or less."); - - if (config.TileSize == 0 && config.BorderSize != derBorderSize) - sb.AppendLine("Border Size of " + derBorderSize + "."); - else if (config.BorderSize < derBorderSize) - sb.AppendLine("Border Size of " + derBorderSize + " or higher."); - - GUILayout.Box(sb.ToString().Trim(), EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - } - - if (build.HasInputData) - { - InputGeometry geom = build.InputGeom; - - Vector3 bmin = geom.BoundsMin; - Vector3 bmax = geom.BoundsMax; - - float w = bmax.x - bmin.x; - float d = bmax.z - bmin.z; - - GUILayout.Space(MarginSize); - - int tw = Mathf.CeilToInt(w / xz); - int td = Mathf.CeilToInt(d / xz); - GUILayout.Label(string.Format("Cells: {0:N0} ({1:N0} x {2:N0})" - , tw * td, tw, td)); - - if (config.TileSize > 0) - { - tw = Mathf.Max(1, Mathf.CeilToInt((float)tw / config.TileSize)); - td = Mathf.Max(1, Mathf.CeilToInt((float)td / config.TileSize)); - } - else - { - tw = 1; - td = 1; - } - GUILayout.Label(string.Format("Tiles: {0:N0} ({1:N0} x {2:N0})" - , tw * td, tw, td)); - } - - ///////////////////////////////////////////////////////////////// - - GUILayout.Space(2 * MarginSize); - GUILayout.Label("Miscellaneous Settings"); - GUILayout.Space(MarginSize); - - config.DetailSampleDistance = EditorGUILayout.FloatField( - NMGenConfig.DetailSampleLabel - , config.DetailSampleDistance); - - config.DetailMaxDeviation = EditorGUILayout.FloatField( - NMGenConfig.DetailDevLabel - , config.DetailMaxDeviation); - - effective = Mathf.Ceil(config.MinRegionArea / a) * a; - config.MinRegionArea = EditorGUILayout.FloatField( - NMGenConfig.IslandRegionLabel + Effective(effective) - , config.MinRegionArea); - } - - public static void OnGUIAdvanced(NMGenConfig config - , bool isInspector) - { - GUILayout.Label("Advanced Settings"); - - EditorGUIUtility.LookLikeControls(170); - - float xz = config.XZCellSize; - - float a = xz * xz; - float effective; - - ///////////////////////////////////////////////////////////// - - GUILayout.Space(MarginSize); - - effective = Mathf.Ceil(config.MaxEdgeLength / xz) * xz; - - config.MaxEdgeLength = EditorGUILayout.FloatField( - NMGenConfig.EdgeLenLabel + Effective(effective) - , config.MaxEdgeLength); - - config.EdgeMaxDeviation = EditorGUILayout.FloatField( - NMGenConfig.EdgeDevLabel - , config.EdgeMaxDeviation); - - config.MaxVertsPerPoly = EditorGUILayout.IntSlider( - NMGenConfig.MaxPolyVertLabel - , config.MaxVertsPerPoly - , 3 - , NMGen.MaxAllowedVertsPerPoly); - - effective = Mathf.Ceil(config.MergeRegionArea / a) * a; - - config.MergeRegionArea = EditorGUILayout.FloatField( - NMGenConfig.MergeSizeLabel + Effective(effective) - , config.MergeRegionArea); - - GUILayout.Space(MarginSize * 2); - - NMGenBuildFlag flags = config.BuildFlags; - - HandleFlagGUI(ref flags - , NMGenConfig.LedgeSpansLabel - , NMGenBuildFlag.LedgeSpansNotWalkable - , isInspector); - - HandleFlagGUI(ref flags - , NMGenConfig.LowHeightLabel - , NMGenBuildFlag.LowHeightSpansNotWalkable - , isInspector); - - HandleFlagGUI(ref flags - , NMGenConfig.LowObstacleLabel - , NMGenBuildFlag.LowObstaclesWalkable - , isInspector); - - ContourBuildFlags cflags = config.ContourOptions; - - HandleFlagGUI(ref cflags - , NMGenConfig.TessWallsLabel - , ContourBuildFlags.TessellateWallEdges - , isInspector); - - HandleFlagGUI(ref cflags - , NMGenConfig.TessAreasLabel - , ContourBuildFlags.TessellateAreaEdges - , isInspector); - - config.ContourOptions = cflags; - - if (isInspector) - { - config.UseMonotone = EditorGUILayout.Toggle(NMGenConfig.UseMonoLabel - , config.UseMonotone); - } - else - { - config.UseMonotone = GUILayout.Toggle(config.UseMonotone - , NMGenConfig.UseMonoLabel); - } - - HandleFlagGUI(ref flags - , NMGenConfig.FlagPolysLabel - , NMGenBuildFlag.ApplyPolyFlags - , isInspector); - - bool includeDetail; - if (isInspector) - { - includeDetail = EditorGUILayout.Toggle("Include Detail Mesh" - , (config.ResultOptions & NMGenAssetFlag.DetailMesh) != 0); - } - else - { - includeDetail = GUILayout.Toggle( - (config.ResultOptions & NMGenAssetFlag.DetailMesh) != 0 - , "Include Detail Mesh"); - } - - if (includeDetail) - config.ResultOptions |= NMGenAssetFlag.DetailMesh; - else - config.ResultOptions &= ~NMGenAssetFlag.DetailMesh; - - HandleFlagGUI(ref flags - , NMGenConfig.BVTreeLabel - , NMGenBuildFlag.BVTreeEnabled - , isInspector); - - config.BuildFlags = flags; - } - - public static void OnGUIButtons(NavmeshBuild build - , NMGenConfig config - , bool isInspector) - { - if (!build) - return; - - if (build.HasBuildData) - // Not an option if the build is in progress. - return; - - if (isInspector) - EditorGUILayout.BeginHorizontal(); - - if (GUILayout.Button("Clean")) - { - config.Clean(); - config.ApplyDecimalLimits(); - GUI.changed = true; - } - - if (GUILayout.Button("Reset")) - { - config.Reset(); - GUI.changed = true; - } - - if (!isInspector) - GUILayout.Space(2 * MarginSize); - - if (build.HasInputData) - { - if (GUILayout.Button("Derive")) - { - InputGeometry geom = build.InputGeom; - - config.Derive(geom.BoundsMin, geom.BoundsMax); - config.ApplyDecimalLimits(); - - GUI.changed = true; - } - } - - if (isInspector) - EditorGUILayout.EndHorizontal(); - - } - - private static string Effective(float value) - { - return " (" + System.Math.Round(value, 2) + ")"; - } - - private static void HandleFlagGUI(ref ContourBuildFlags flags - , string label - , ContourBuildFlags flag - , bool isInspector) - { - if (isInspector) - { - flags = EditorGUILayout.Toggle(label, (flags & flag) != 0) - ? (flags | flag) - : (flags & ~flag); - } - else - { - flags = GUILayout.Toggle((flags & flag) != 0, label) - ? (flags | flag) - : (flags & ~flag); - } - } - - private static void HandleFlagGUI(ref NMGenBuildFlag flags - , string label - , NMGenBuildFlag flag - , bool isInspector) - { - if (isInspector) - { - flags = EditorGUILayout.Toggle(label, (flags & flag) != 0) - ? (flags | flag) - : (flags & ~flag); - } - else - { - flags = GUILayout.Toggle((flags & flag) != 0, label) - ? (flags | flag) - : (flags & ~flag); - } - } - } -} diff --git a/critterai/.svn/pristine/85/853169f0b8a3a39524a309de089ff167d0ec5379.svn-base b/critterai/.svn/pristine/85/853169f0b8a3a39524a309de089ff167d0ec5379.svn-base deleted file mode 100644 index cc9ab7ab..00000000 --- a/critterai/.svn/pristine/85/853169f0b8a3a39524a309de089ff167d0ec5379.svn-base +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav.rcn -{ - internal static class NavmeshEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmBuildSingleTileMesh( - NavmeshTileBuildData buildData - , ref IntPtr resultMesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmBuildDTNavMeshFromRaw([In] byte[] rawMeshData - , int dataSize - , bool safeStorage - , ref IntPtr resultNavMesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmInitTiledNavMesh(NavmeshParams config - , ref IntPtr navmesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtnmFreeNavMesh(ref IntPtr navmesh, bool freeTiles); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtnmGetParams(IntPtr navmesh - , [In, Out] NavmeshParams config); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmAddTile(IntPtr navmesh - , [In, Out] NavmeshTileData tileData - , uint lastRef - , ref uint resultRef); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmRemoveTile(IntPtr navmesh - , uint tileRef - , ref IntPtr resultData - , ref int resultDataSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtnmCalcTileLoc(IntPtr navmesh - , [In] ref Vector3 position - , ref int tx - , ref int tz); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtnmGetTileAt(IntPtr navmesh - , int x - , int z - , int layer); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetTilesAt(IntPtr navmesh - , int x - , int z - , [In, Out] IntPtr[] tiles - , int tilesSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern uint dtnmGetTileRefAt(IntPtr navMesh - , int x - , int z - , int layer); - - // The other get tile id method is in NavmeshTileEx. - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtnmGetTileByRef(IntPtr navmesh - , uint tileRef); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int dtnmGetMaxTiles(IntPtr navmesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtnmGetTile(IntPtr navmesh - , int tileIndex); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmGetTileAndPolyByRef(IntPtr navmesh - , uint polyRef - , ref IntPtr tile - , ref IntPtr poly); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool dtnmIsValidPolyRef(IntPtr navmesh - , uint polyRef); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmGetConnectionEndPoints( - IntPtr navmesh - , uint previousPolyRef - , uint polyRef - , [In, Out] ref Vector3 startPosition - , [In, Out] ref Vector3 endPosition); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtnmGetOffMeshConnectionByRef(IntPtr navmesh - , uint polyRef); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmGetPolyFlags(IntPtr navmesh - , uint polyRef - , ref ushort flags); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmSetPolyFlags(IntPtr navmesh - , uint polyRef - , ushort flags); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmGetPolyArea(IntPtr navmesh - , uint polyRef - , ref byte area); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern NavStatus dtnmSetPolyArea(IntPtr navmesh - , uint polyRef - , byte area); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtnmGetNavMeshRawData(IntPtr navmesh - , ref IntPtr resultData - , ref int dataSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtnmFreeBytes(ref IntPtr data); - } -} diff --git a/critterai/.svn/pristine/86/861a590041e138b34a8eb0cbe46b067905ab7a47.svn-base b/critterai/.svn/pristine/86/861a590041e138b34a8eb0cbe46b067905ab7a47.svn-base deleted file mode 100644 index c3ca3cd6..00000000 --- a/critterai/.svn/pristine/86/861a590041e138b34a8eb0cbe46b067905ab7a47.svn-base +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.u3d; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal class InputDebugView - { - private bool mEnabled; - private bool mShow; - private bool mNeedsRepaint; - - public bool NeedsRepaint - { - get { return mNeedsRepaint; } - set { mNeedsRepaint = value; } - } - - public bool Enabled - { - get { return mEnabled; } - set - { - if (mEnabled != value) - { - mEnabled = value; - mNeedsRepaint = true; - } - } - } - - public bool Show - { - get { return mShow; } - set - { - if (mShow != value) - { - mShow = value; - mNeedsRepaint = true; - } - } - } - - public void OnRenderObject(NavmeshBuild build) - { - if (mEnabled && mShow && build && build.HasInputData) - { - InputGeometry geom = build.InputGeom; - DebugDraw.Bounds(geom.BoundsMin, geom.BoundsMax, Color.grey); - } - } - } -} diff --git a/critterai/.svn/pristine/86/86e9d421294640847990bb61c62dfb1789976b07.svn-base b/critterai/.svn/pristine/86/86e9d421294640847990bb61c62dfb1789976b07.svn-base deleted file mode 100644 index 9f61d0e3..00000000 --- a/critterai/.svn/pristine/86/86e9d421294640847990bb61c62dfb1789976b07.svn-base +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** -Provides data structures and algorithms useful for generating navigation meshes -which represent the traversable surface area of an arbitrary source triangle -mesh. - */ -package org.critterai.nmgen; diff --git a/critterai/.svn/pristine/87/87121f33996068993c43b7c7c879ebd06f8ea8b0.svn-base b/critterai/.svn/pristine/87/87121f33996068993c43b7c7c879ebd06f8ea8b0.svn-base deleted file mode 100644 index f81bea7d..00000000 --- a/critterai/.svn/pristine/87/87121f33996068993c43b7c7c879ebd06f8ea8b0.svn-base +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.nmgen; -using System.Collections.Generic; -using org.critterai.nav; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(TagAreaDef))] -public sealed class TagAreaDefEditor - : Editor -{ - private CAINavEditorSettingsEditor.AreaGUIControl mAreaControl; - - void OnEnable() - { - mAreaControl = CAINavEditorSettingsEditor.CreateAreaControl(""); - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - TagAreaDef targ = (TagAreaDef)target; - - // Has someone done something naughty? - - if (targ.areas == null || targ.tags == null) - { - Debug.LogError("Data null reference. Resetting component.", targ); - targ.areas = new List(); - targ.tags = new List(); - } - - List areas = targ.areas; - List tags = targ.tags; - - if (areas.Count > tags.Count) - { - areas.RemoveRange(tags.Count, areas.Count - tags.Count); - Debug.LogError("Data size mismatch. Area list truncated.", targ); - } - else if (tags.Count > areas.Count) - { - tags.RemoveRange(areas.Count, tags.Count - areas.Count); - Debug.LogError("Data size mismatch. Mesh list truncated.", targ); - } - - EditorGUILayout.Separator(); - - targ.SetPriority(EditorGUILayout.IntField("Priority", targ.Priority)); - - EditorGUILayout.Separator(); - - targ.recursive = EditorGUILayout.Toggle("Recursive", targ.recursive); - - EditorGUILayout.Separator(); - - GUILayout.Label("Tag / Area"); - - EditorGUILayout.Separator(); - - if (areas.Count > 0) - { - EditorGUILayout.BeginVertical(); - - int delChoice = -1; - - for (int i = 0; i < areas.Count; i++) - { - EditorGUILayout.BeginHorizontal(); - - string tag = EditorGUILayout.TagField(tags[i]); - - if (tag == tags[i] || !tags.Contains(tag)) - tags[i] = tag; - - areas[i] = mAreaControl.OnGUI(areas[i]); - - if (GUILayout.Button("X", GUILayout.Width(30))) - delChoice = i; - - EditorGUILayout.EndHorizontal(); - } - - if (delChoice >= 0) - { - tags.RemoveAt(delChoice); - areas.RemoveAt(delChoice); - } - - EditorGUILayout.EndVertical(); - } - - EditorGUILayout.BeginVertical(); - EditorGUILayout.Separator(); - - EditorGUILayout.BeginHorizontal(); - - string ntag = EditorGUILayout.TagField("Add", ""); - - if (ntag.Length > 0) - { - if (!tags.Contains(ntag)) - { - tags.Add(ntag); - areas.Add(NMGen.MaxArea); - } - } - - EditorGUILayout.EndHorizontal(); - - EditorGUILayout.EndVertical(); - - EditorGUILayout.Separator(); - - string msg = - "Input Build Processor\n\nApplies areas to components based on the specified tags."; - - if (targ.recursive) - { - msg += "\n\nRecursive: Will apply area if a parent has one of the tags."; - } - - GUILayout.Box(msg, EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Area Definition : Tag", false, NMBEditorUtil.AreaGroup)] - static void CreateAsset() - { - TagAreaDef item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/87/87abf17c7dc7e54d168b54c3031447748709c1d6.svn-base b/critterai/.svn/pristine/87/87abf17c7dc7e54d168b54c3031447748709c1d6.svn-base deleted file mode 100644 index c8be5912..00000000 --- a/critterai/.svn/pristine/87/87abf17c7dc7e54d168b54c3031447748709c1d6.svn-base +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.geom -{ - /// - /// Specifies the relationship between two lines. - /// - public enum LineRelType : byte - { - /// - /// Lines are parallel and overlap each other. (Share all points.) - /// - Collinear, - - /// - /// Lines intersect, but their segments do not. - /// - LinesIntersect, - - /// - /// Line segments intersect each other. - /// - SegmentsIntersect, - - /// - /// Line segment B is crossed by line A. - /// - ALineCrossesBSeg, - - /// - /// Line segment A is crossed by line B. - /// - BLineCrossesASeg, - - /// - /// Lines are parallel and do not overlap each other. (Share no points.) - /// - Parallel, - - /// - /// Lines do not intersect, but are not parallel. - /// (Share no points. Only applicable to 3-dimensional lines.) - /// - Skew - } -} diff --git a/critterai/.svn/pristine/87/87d0f62e5f4f1d0bfdbb10721dd40b4aa230e046.svn-base b/critterai/.svn/pristine/87/87d0f62e5f4f1d0bfdbb10721dd40b4aa230e046.svn-base deleted file mode 100644 index d77a1369..00000000 --- a/critterai/.svn/pristine/87/87d0f62e5f4f1d0bfdbb10721dd40b4aa230e046.svn-base +++ /dev/null @@ -1,61 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURLOCALBOUNDARY_H -#define DETOURLOCALBOUNDARY_H - -#include "DetourNavMeshQuery.h" - - -class dtLocalBoundary -{ - static const int MAX_LOCAL_SEGS = 8; - static const int MAX_LOCAL_POLYS = 16; - - struct Segment - { - float s[6]; ///< Segment start/end - float d; ///< Distance for pruning. - }; - - float m_center[3]; - Segment m_segs[MAX_LOCAL_SEGS]; - int m_nsegs; - - dtPolyRef m_polys[MAX_LOCAL_POLYS]; - int m_npolys; - - void addSegment(const float dist, const float* seg); - -public: - dtLocalBoundary(); - ~dtLocalBoundary(); - - void reset(); - - void update(dtPolyRef ref, const float* pos, const float collisionQueryRange, - dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - bool isValid(dtNavMeshQuery* navquery, const dtQueryFilter* filter); - - inline const float* getCenter() const { return m_center; } - inline int getSegmentCount() const { return m_nsegs; } - inline const float* getSegment(int i) const { return m_segs[i].s; } -}; - -#endif // DETOURLOCALBOUNDARY_H diff --git a/critterai/.svn/pristine/88/88becbf565bc47375cde6ee11228096fb460e049.svn-base b/critterai/.svn/pristine/88/88becbf565bc47375cde6ee11228096fb460e049.svn-base deleted file mode 100644 index d9c71074..00000000 --- a/critterai/.svn/pristine/88/88becbf565bc47375cde6ee11228096fb460e049.svn-base +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nmgen -{ - /// - /// Provides information on the content of a cell column in a - /// object. - /// - /// - /// - /// Useful instances of this type can only by obtained from a - /// object. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct CompactCell - { - private uint mPacked; - - /// - /// The index of the first (lowest) in the cell column. - /// - public uint Index { get { return (mPacked & 0xffffff); } } - - /// - /// The number of spans in the cell column. - /// - public uint Count { get { return (mPacked >> 24); } } - } -} diff --git a/critterai/.svn/pristine/89/894d1c4d48ba2cb7ef63dbc316eacbbc39c5636b.svn-base b/critterai/.svn/pristine/89/894d1c4d48ba2cb7ef63dbc316eacbbc39c5636b.svn-base deleted file mode 100644 index 3c0aa62f..00000000 --- a/critterai/.svn/pristine/89/894d1c4d48ba2cb7ef63dbc316eacbbc39c5636b.svn-base +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Applies an algorithm to an {@link OpenHeightfield} - *

      The algorithm may require the field to be in a supported state. - * E.g. The regions must have been generated.

      - */ -public interface IOpenHeightFieldAlgorithm -{ - /** - * Applies the algorithm to the height field. - * @param field The field to apply the algorithm to. - */ - void apply(OpenHeightfield field); -} diff --git a/critterai/.svn/pristine/89/89b77d9bb31de95bf489489e12904279b314506f.svn-base b/critterai/.svn/pristine/89/89b77d9bb31de95bf489489e12904279b314506f.svn-base deleted file mode 100644 index b3872754..00000000 --- a/critterai/.svn/pristine/89/89b77d9bb31de95bf489489e12904279b314506f.svn-base +++ /dev/null @@ -1,1245 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" - - -static const unsigned RC_UNSET_HEIGHT = 0xffff; - -struct rcHeightPatch -{ - inline rcHeightPatch() : data(0), xmin(0), ymin(0), width(0), height(0) {} - inline ~rcHeightPatch() { rcFree(data); } - unsigned short* data; - int xmin, ymin, width, height; -}; - - -inline float vdot2(const float* a, const float* b) -{ - return a[0]*b[0] + a[2]*b[2]; -} - -inline float vdistSq2(const float* p, const float* q) -{ - const float dx = q[0] - p[0]; - const float dy = q[2] - p[2]; - return dx*dx + dy*dy; -} - -inline float vdist2(const float* p, const float* q) -{ - return sqrtf(vdistSq2(p,q)); -} - -inline float vcross2(const float* p1, const float* p2, const float* p3) -{ - const float u1 = p2[0] - p1[0]; - const float v1 = p2[2] - p1[2]; - const float u2 = p3[0] - p1[0]; - const float v2 = p3[2] - p1[2]; - return u1 * v2 - v1 * u2; -} - -static bool circumCircle(const float* p1, const float* p2, const float* p3, - float* c, float& r) -{ - static const float EPS = 1e-6f; - - const float cp = vcross2(p1, p2, p3); - if (fabsf(cp) > EPS) - { - const float p1Sq = vdot2(p1,p1); - const float p2Sq = vdot2(p2,p2); - const float p3Sq = vdot2(p3,p3); - c[0] = (p1Sq*(p2[2]-p3[2]) + p2Sq*(p3[2]-p1[2]) + p3Sq*(p1[2]-p2[2])) / (2*cp); - c[2] = (p1Sq*(p3[0]-p2[0]) + p2Sq*(p1[0]-p3[0]) + p3Sq*(p2[0]-p1[0])) / (2*cp); - r = vdist2(c, p1); - return true; - } - - c[0] = p1[0]; - c[2] = p1[2]; - r = 0; - return false; -} - -static float distPtTri(const float* p, const float* a, const float* b, const float* c) -{ - float v0[3], v1[3], v2[3]; - rcVsub(v0, c,a); - rcVsub(v1, b,a); - rcVsub(v2, p,a); - - const float dot00 = vdot2(v0, v0); - const float dot01 = vdot2(v0, v1); - const float dot02 = vdot2(v0, v2); - const float dot11 = vdot2(v1, v1); - const float dot12 = vdot2(v1, v2); - - // Compute barycentric coordinates - const float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); - const float u = (dot11 * dot02 - dot01 * dot12) * invDenom; - float v = (dot00 * dot12 - dot01 * dot02) * invDenom; - - // If point lies inside the triangle, return interpolated y-coord. - static const float EPS = 1e-4f; - if (u >= -EPS && v >= -EPS && (u+v) <= 1+EPS) - { - const float y = a[1] + v0[1]*u + v1[1]*v; - return fabsf(y-p[1]); - } - return FLT_MAX; -} - -static float distancePtSeg(const float* pt, const float* p, const float* q) -{ - float pqx = q[0] - p[0]; - float pqy = q[1] - p[1]; - float pqz = q[2] - p[2]; - float dx = pt[0] - p[0]; - float dy = pt[1] - p[1]; - float dz = pt[2] - p[2]; - float d = pqx*pqx + pqy*pqy + pqz*pqz; - float t = pqx*dx + pqy*dy + pqz*dz; - if (d > 0) - t /= d; - if (t < 0) - t = 0; - else if (t > 1) - t = 1; - - dx = p[0] + t*pqx - pt[0]; - dy = p[1] + t*pqy - pt[1]; - dz = p[2] + t*pqz - pt[2]; - - return dx*dx + dy*dy + dz*dz; -} - -static float distancePtSeg2d(const float* pt, const float* p, const float* q) -{ - float pqx = q[0] - p[0]; - float pqz = q[2] - p[2]; - float dx = pt[0] - p[0]; - float dz = pt[2] - p[2]; - float d = pqx*pqx + pqz*pqz; - float t = pqx*dx + pqz*dz; - if (d > 0) - t /= d; - if (t < 0) - t = 0; - else if (t > 1) - t = 1; - - dx = p[0] + t*pqx - pt[0]; - dz = p[2] + t*pqz - pt[2]; - - return dx*dx + dz*dz; -} - -static float distToTriMesh(const float* p, const float* verts, const int /*nverts*/, const int* tris, const int ntris) -{ - float dmin = FLT_MAX; - for (int i = 0; i < ntris; ++i) - { - const float* va = &verts[tris[i*4+0]*3]; - const float* vb = &verts[tris[i*4+1]*3]; - const float* vc = &verts[tris[i*4+2]*3]; - float d = distPtTri(p, va,vb,vc); - if (d < dmin) - dmin = d; - } - if (dmin == FLT_MAX) return -1; - return dmin; -} - -static float distToPoly(int nvert, const float* verts, const float* p) -{ - - float dmin = FLT_MAX; - int i, j, c = 0; - for (i = 0, j = nvert-1; i < nvert; j = i++) - { - const float* vi = &verts[i*3]; - const float* vj = &verts[j*3]; - if (((vi[2] > p[2]) != (vj[2] > p[2])) && - (p[0] < (vj[0]-vi[0]) * (p[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) ) - c = !c; - dmin = rcMin(dmin, distancePtSeg2d(p, vj, vi)); - } - return c ? -dmin : dmin; -} - - -static unsigned short getHeight(const float fx, const float fy, const float fz, - const float /*cs*/, const float ics, const float ch, - const rcHeightPatch& hp) -{ - int ix = (int)floorf(fx*ics + 0.01f); - int iz = (int)floorf(fz*ics + 0.01f); - ix = rcClamp(ix-hp.xmin, 0, hp.width); - iz = rcClamp(iz-hp.ymin, 0, hp.height); - unsigned short h = hp.data[ix+iz*hp.width]; - if (h == RC_UNSET_HEIGHT) - { - // Special case when data might be bad. - // Find nearest neighbour pixel which has valid height. - const int off[8*2] = { -1,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1}; - float dmin = FLT_MAX; - for (int i = 0; i < 8; ++i) - { - const int nx = ix+off[i*2+0]; - const int nz = iz+off[i*2+1]; - if (nx < 0 || nz < 0 || nx >= hp.width || nz >= hp.height) continue; - const unsigned short nh = hp.data[nx+nz*hp.width]; - if (nh == RC_UNSET_HEIGHT) continue; - - const float d = fabsf(nh*ch - fy); - if (d < dmin) - { - h = nh; - dmin = d; - } - -/* const float dx = (nx+0.5f)*cs - fx; - const float dz = (nz+0.5f)*cs - fz; - const float d = dx*dx+dz*dz; - if (d < dmin) - { - h = nh; - dmin = d; - } */ - } - } - return h; -} - - -enum EdgeValues -{ - UNDEF = -1, - HULL = -2, -}; - -static int findEdge(const int* edges, int nedges, int s, int t) -{ - for (int i = 0; i < nedges; i++) - { - const int* e = &edges[i*4]; - if ((e[0] == s && e[1] == t) || (e[0] == t && e[1] == s)) - return i; - } - return UNDEF; -} - -static int addEdge(rcContext* ctx, int* edges, int& nedges, const int maxEdges, int s, int t, int l, int r) -{ - if (nedges >= maxEdges) - { - ctx->log(RC_LOG_ERROR, "addEdge: Too many edges (%d/%d).", nedges, maxEdges); - return UNDEF; - } - - // Add edge if not already in the triangulation. - int e = findEdge(edges, nedges, s, t); - if (e == UNDEF) - { - int* edge = &edges[nedges*4]; - edge[0] = s; - edge[1] = t; - edge[2] = l; - edge[3] = r; - return nedges++; - } - else - { - return UNDEF; - } -} - -static void updateLeftFace(int* e, int s, int t, int f) -{ - if (e[0] == s && e[1] == t && e[2] == UNDEF) - e[2] = f; - else if (e[1] == s && e[0] == t && e[3] == UNDEF) - e[3] = f; -} - -static int overlapSegSeg2d(const float* a, const float* b, const float* c, const float* d) -{ - const float a1 = vcross2(a, b, d); - const float a2 = vcross2(a, b, c); - if (a1*a2 < 0.0f) - { - float a3 = vcross2(c, d, a); - float a4 = a3 + a2 - a1; - if (a3 * a4 < 0.0f) - return 1; - } - return 0; -} - -static bool overlapEdges(const float* pts, const int* edges, int nedges, int s1, int t1) -{ - for (int i = 0; i < nedges; ++i) - { - const int s0 = edges[i*4+0]; - const int t0 = edges[i*4+1]; - // Same or connected edges do not overlap. - if (s0 == s1 || s0 == t1 || t0 == s1 || t0 == t1) - continue; - if (overlapSegSeg2d(&pts[s0*3],&pts[t0*3], &pts[s1*3],&pts[t1*3])) - return true; - } - return false; -} - -static void completeFacet(rcContext* ctx, const float* pts, int npts, int* edges, int& nedges, const int maxEdges, int& nfaces, int e) -{ - static const float EPS = 1e-5f; - - int* edge = &edges[e*4]; - - // Cache s and t. - int s,t; - if (edge[2] == UNDEF) - { - s = edge[0]; - t = edge[1]; - } - else if (edge[3] == UNDEF) - { - s = edge[1]; - t = edge[0]; - } - else - { - // Edge already completed. - return; - } - - // Find best point on left of edge. - int pt = npts; - float c[3] = {0,0,0}; - float r = -1; - for (int u = 0; u < npts; ++u) - { - if (u == s || u == t) continue; - if (vcross2(&pts[s*3], &pts[t*3], &pts[u*3]) > EPS) - { - if (r < 0) - { - // The circle is not updated yet, do it now. - pt = u; - circumCircle(&pts[s*3], &pts[t*3], &pts[u*3], c, r); - continue; - } - const float d = vdist2(c, &pts[u*3]); - const float tol = 0.001f; - if (d > r*(1+tol)) - { - // Outside current circumcircle, skip. - continue; - } - else if (d < r*(1-tol)) - { - // Inside safe circumcircle, update circle. - pt = u; - circumCircle(&pts[s*3], &pts[t*3], &pts[u*3], c, r); - } - else - { - // Inside epsilon circum circle, do extra tests to make sure the edge is valid. - // s-u and t-u cannot overlap with s-pt nor t-pt if they exists. - if (overlapEdges(pts, edges, nedges, s,u)) - continue; - if (overlapEdges(pts, edges, nedges, t,u)) - continue; - // Edge is valid. - pt = u; - circumCircle(&pts[s*3], &pts[t*3], &pts[u*3], c, r); - } - } - } - - // Add new triangle or update edge info if s-t is on hull. - if (pt < npts) - { - // Update face information of edge being completed. - updateLeftFace(&edges[e*4], s, t, nfaces); - - // Add new edge or update face info of old edge. - e = findEdge(edges, nedges, pt, s); - if (e == UNDEF) - addEdge(ctx, edges, nedges, maxEdges, pt, s, nfaces, UNDEF); - else - updateLeftFace(&edges[e*4], pt, s, nfaces); - - // Add new edge or update face info of old edge. - e = findEdge(edges, nedges, t, pt); - if (e == UNDEF) - addEdge(ctx, edges, nedges, maxEdges, t, pt, nfaces, UNDEF); - else - updateLeftFace(&edges[e*4], t, pt, nfaces); - - nfaces++; - } - else - { - updateLeftFace(&edges[e*4], s, t, HULL); - } -} - -static void delaunayHull(rcContext* ctx, const int npts, const float* pts, - const int nhull, const int* hull, - rcIntArray& tris, rcIntArray& edges) -{ - int nfaces = 0; - int nedges = 0; - const int maxEdges = npts*10; - edges.resize(maxEdges*4); - - for (int i = 0, j = nhull-1; i < nhull; j=i++) - addEdge(ctx, &edges[0], nedges, maxEdges, hull[j],hull[i], HULL, UNDEF); - - int currentEdge = 0; - while (currentEdge < nedges) - { - if (edges[currentEdge*4+2] == UNDEF) - completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); - if (edges[currentEdge*4+3] == UNDEF) - completeFacet(ctx, pts, npts, &edges[0], nedges, maxEdges, nfaces, currentEdge); - currentEdge++; - } - - // Create tris - tris.resize(nfaces*4); - for (int i = 0; i < nfaces*4; ++i) - tris[i] = -1; - - for (int i = 0; i < nedges; ++i) - { - const int* e = &edges[i*4]; - if (e[3] >= 0) - { - // Left face - int* t = &tris[e[3]*4]; - if (t[0] == -1) - { - t[0] = e[0]; - t[1] = e[1]; - } - else if (t[0] == e[1]) - t[2] = e[0]; - else if (t[1] == e[0]) - t[2] = e[1]; - } - if (e[2] >= 0) - { - // Right - int* t = &tris[e[2]*4]; - if (t[0] == -1) - { - t[0] = e[1]; - t[1] = e[0]; - } - else if (t[0] == e[0]) - t[2] = e[1]; - else if (t[1] == e[1]) - t[2] = e[0]; - } - } - - for (int i = 0; i < tris.size()/4; ++i) - { - int* t = &tris[i*4]; - if (t[0] == -1 || t[1] == -1 || t[2] == -1) - { - ctx->log(RC_LOG_WARNING, "delaunayHull: Removing dangling face %d [%d,%d,%d].", i, t[0],t[1],t[2]); - t[0] = tris[tris.size()-4]; - t[1] = tris[tris.size()-3]; - t[2] = tris[tris.size()-2]; - t[3] = tris[tris.size()-1]; - tris.resize(tris.size()-4); - --i; - } - } -} - - -inline float getJitterX(const int i) -{ - return (((i * 0x8da6b343) & 0xffff) / 65535.0f * 2.0f) - 1.0f; -} - -inline float getJitterY(const int i) -{ - return (((i * 0xd8163841) & 0xffff) / 65535.0f * 2.0f) - 1.0f; -} - -static bool buildPolyDetail(rcContext* ctx, const float* in, const int nin, - const float sampleDist, const float sampleMaxError, - const rcCompactHeightfield& chf, const rcHeightPatch& hp, - float* verts, int& nverts, rcIntArray& tris, - rcIntArray& edges, rcIntArray& samples) -{ - static const int MAX_VERTS = 127; - static const int MAX_TRIS = 255; // Max tris for delaunay is 2n-2-k (n=num verts, k=num hull verts). - static const int MAX_VERTS_PER_EDGE = 32; - float edge[(MAX_VERTS_PER_EDGE+1)*3]; - int hull[MAX_VERTS]; - int nhull = 0; - - nverts = 0; - - for (int i = 0; i < nin; ++i) - rcVcopy(&verts[i*3], &in[i*3]); - nverts = nin; - - const float cs = chf.cs; - const float ics = 1.0f/cs; - - // Tessellate outlines. - // This is done in separate pass in order to ensure - // seamless height values across the ply boundaries. - if (sampleDist > 0) - { - for (int i = 0, j = nin-1; i < nin; j=i++) - { - const float* vj = &in[j*3]; - const float* vi = &in[i*3]; - bool swapped = false; - // Make sure the segments are always handled in same order - // using lexological sort or else there will be seams. - if (fabsf(vj[0]-vi[0]) < 1e-6f) - { - if (vj[2] > vi[2]) - { - rcSwap(vj,vi); - swapped = true; - } - } - else - { - if (vj[0] > vi[0]) - { - rcSwap(vj,vi); - swapped = true; - } - } - // Create samples along the edge. - float dx = vi[0] - vj[0]; - float dy = vi[1] - vj[1]; - float dz = vi[2] - vj[2]; - float d = sqrtf(dx*dx + dz*dz); - int nn = 1 + (int)floorf(d/sampleDist); - if (nn >= MAX_VERTS_PER_EDGE) nn = MAX_VERTS_PER_EDGE-1; - if (nverts+nn >= MAX_VERTS) - nn = MAX_VERTS-1-nverts; - - for (int k = 0; k <= nn; ++k) - { - float u = (float)k/(float)nn; - float* pos = &edge[k*3]; - pos[0] = vj[0] + dx*u; - pos[1] = vj[1] + dy*u; - pos[2] = vj[2] + dz*u; - pos[1] = getHeight(pos[0],pos[1],pos[2], cs, ics, chf.ch, hp)*chf.ch; - } - // Simplify samples. - int idx[MAX_VERTS_PER_EDGE] = {0,nn}; - int nidx = 2; - for (int k = 0; k < nidx-1; ) - { - const int a = idx[k]; - const int b = idx[k+1]; - const float* va = &edge[a*3]; - const float* vb = &edge[b*3]; - // Find maximum deviation along the segment. - float maxd = 0; - int maxi = -1; - for (int m = a+1; m < b; ++m) - { - float dev = distancePtSeg(&edge[m*3],va,vb); - if (dev > maxd) - { - maxd = dev; - maxi = m; - } - } - // If the max deviation is larger than accepted error, - // add new point, else continue to next segment. - if (maxi != -1 && maxd > rcSqr(sampleMaxError)) - { - for (int m = nidx; m > k; --m) - idx[m] = idx[m-1]; - idx[k+1] = maxi; - nidx++; - } - else - { - ++k; - } - } - - hull[nhull++] = j; - // Add new vertices. - if (swapped) - { - for (int k = nidx-2; k > 0; --k) - { - rcVcopy(&verts[nverts*3], &edge[idx[k]*3]); - hull[nhull++] = nverts; - nverts++; - } - } - else - { - for (int k = 1; k < nidx-1; ++k) - { - rcVcopy(&verts[nverts*3], &edge[idx[k]*3]); - hull[nhull++] = nverts; - nverts++; - } - } - } - } - - - // Tessellate the base mesh. - edges.resize(0); - tris.resize(0); - - delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges); - - if (tris.size() == 0) - { - // Could not triangulate the poly, make sure there is some valid data there. - ctx->log(RC_LOG_WARNING, "buildPolyDetail: Could not triangulate polygon, adding default data."); - for (int i = 2; i < nverts; ++i) - { - tris.push(0); - tris.push(i-1); - tris.push(i); - tris.push(0); - } - return true; - } - - if (sampleDist > 0) - { - // Create sample locations in a grid. - float bmin[3], bmax[3]; - rcVcopy(bmin, in); - rcVcopy(bmax, in); - for (int i = 1; i < nin; ++i) - { - rcVmin(bmin, &in[i*3]); - rcVmax(bmax, &in[i*3]); - } - int x0 = (int)floorf(bmin[0]/sampleDist); - int x1 = (int)ceilf(bmax[0]/sampleDist); - int z0 = (int)floorf(bmin[2]/sampleDist); - int z1 = (int)ceilf(bmax[2]/sampleDist); - samples.resize(0); - for (int z = z0; z < z1; ++z) - { - for (int x = x0; x < x1; ++x) - { - float pt[3]; - pt[0] = x*sampleDist; - pt[1] = (bmax[1]+bmin[1])*0.5f; - pt[2] = z*sampleDist; - // Make sure the samples are not too close to the edges. - if (distToPoly(nin,in,pt) > -sampleDist/2) continue; - samples.push(x); - samples.push(getHeight(pt[0], pt[1], pt[2], cs, ics, chf.ch, hp)); - samples.push(z); - samples.push(0); // Not added - } - } - - // Add the samples starting from the one that has the most - // error. The procedure stops when all samples are added - // or when the max error is within treshold. - const int nsamples = samples.size()/4; - for (int iter = 0; iter < nsamples; ++iter) - { - if (nverts >= MAX_VERTS) - break; - - // Find sample with most error. - float bestpt[3] = {0,0,0}; - float bestd = 0; - int besti = -1; - for (int i = 0; i < nsamples; ++i) - { - const int* s = &samples[i*4]; - if (s[3]) continue; // skip added. - float pt[3]; - // The sample location is jittered to get rid of some bad triangulations - // which are cause by symmetrical data from the grid structure. - pt[0] = s[0]*sampleDist + getJitterX(i)*cs*0.1f; - pt[1] = s[1]*chf.ch; - pt[2] = s[2]*sampleDist + getJitterY(i)*cs*0.1f; - float d = distToTriMesh(pt, verts, nverts, &tris[0], tris.size()/4); - if (d < 0) continue; // did not hit the mesh. - if (d > bestd) - { - bestd = d; - besti = i; - rcVcopy(bestpt,pt); - } - } - // If the max error is within accepted threshold, stop tesselating. - if (bestd <= sampleMaxError || besti == -1) - break; - // Mark sample as added. - samples[besti*4+3] = 1; - // Add the new sample point. - rcVcopy(&verts[nverts*3],bestpt); - nverts++; - - // Create new triangulation. - // TODO: Incremental add instead of full rebuild. - edges.resize(0); - tris.resize(0); - delaunayHull(ctx, nverts, verts, nhull, hull, tris, edges); - } - } - - const int ntris = tris.size()/4; - if (ntris > MAX_TRIS) - { - tris.resize(MAX_TRIS*4); - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Shrinking triangle count from %d to max %d.", ntris, MAX_TRIS); - } - - return true; -} - -static void getHeightData(const rcCompactHeightfield& chf, - const unsigned short* poly, const int npoly, - const unsigned short* verts, const int bs, - rcHeightPatch& hp, rcIntArray& stack) -{ - // Floodfill the heightfield to get 2D height data, - // starting at vertex locations as seeds. - - // Note: Reads to the compact heightfield are offset by border size (bs) - // since border size offset is already removed from the polymesh vertices. - - memset(hp.data, 0, sizeof(unsigned short)*hp.width*hp.height); - - stack.resize(0); - - static const int offset[9*2] = - { - 0,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1, -1,0, - }; - - // Use poly vertices as seed points for the flood fill. - for (int j = 0; j < npoly; ++j) - { - int cx = 0, cz = 0, ci =-1; - int dmin = RC_UNSET_HEIGHT; - for (int k = 0; k < 9; ++k) - { - const int ax = (int)verts[poly[j]*3+0] + offset[k*2+0]; - const int ay = (int)verts[poly[j]*3+1]; - const int az = (int)verts[poly[j]*3+2] + offset[k*2+1]; - if (ax < hp.xmin || ax >= hp.xmin+hp.width || - az < hp.ymin || az >= hp.ymin+hp.height) - continue; - - const rcCompactCell& c = chf.cells[(ax+bs)+(az+bs)*chf.width]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - int d = rcAbs(ay - (int)s.y); - if (d < dmin) - { - cx = ax; - cz = az; - ci = i; - dmin = d; - } - } - } - if (ci != -1) - { - stack.push(cx); - stack.push(cz); - stack.push(ci); - } - } - - // Find center of the polygon using flood fill. - int pcx = 0, pcz = 0; - for (int j = 0; j < npoly; ++j) - { - pcx += (int)verts[poly[j]*3+0]; - pcz += (int)verts[poly[j]*3+2]; - } - pcx /= npoly; - pcz /= npoly; - - for (int i = 0; i < stack.size(); i += 3) - { - int cx = stack[i+0]; - int cy = stack[i+1]; - int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width; - hp.data[idx] = 1; - } - - while (stack.size() > 0) - { - int ci = stack.pop(); - int cy = stack.pop(); - int cx = stack.pop(); - - // Check if close to center of the polygon. - if (rcAbs(cx-pcx) <= 1 && rcAbs(cy-pcz) <= 1) - { - stack.resize(0); - stack.push(cx); - stack.push(cy); - stack.push(ci); - break; - } - - const rcCompactSpan& cs = chf.spans[ci]; - - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue; - - const int ax = cx + rcGetDirOffsetX(dir); - const int ay = cy + rcGetDirOffsetY(dir); - - if (ax < hp.xmin || ax >= (hp.xmin+hp.width) || - ay < hp.ymin || ay >= (hp.ymin+hp.height)) - continue; - - if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != 0) - continue; - - const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir); - - int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width; - hp.data[idx] = 1; - - stack.push(ax); - stack.push(ay); - stack.push(ai); - } - } - - memset(hp.data, 0xff, sizeof(unsigned short)*hp.width*hp.height); - - // Mark start locations. - for (int i = 0; i < stack.size(); i += 3) - { - int cx = stack[i+0]; - int cy = stack[i+1]; - int ci = stack[i+2]; - int idx = cx-hp.xmin+(cy-hp.ymin)*hp.width; - const rcCompactSpan& cs = chf.spans[ci]; - hp.data[idx] = cs.y; - } - - static const int RETRACT_SIZE = 256; - int head = 0; - - while (head*3 < stack.size()) - { - int cx = stack[head*3+0]; - int cy = stack[head*3+1]; - int ci = stack[head*3+2]; - head++; - if (head >= RETRACT_SIZE) - { - head = 0; - if (stack.size() > RETRACT_SIZE*3) - memmove(&stack[0], &stack[RETRACT_SIZE*3], sizeof(int)*(stack.size()-RETRACT_SIZE*3)); - stack.resize(stack.size()-RETRACT_SIZE*3); - } - - const rcCompactSpan& cs = chf.spans[ci]; - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(cs, dir) == RC_NOT_CONNECTED) continue; - - const int ax = cx + rcGetDirOffsetX(dir); - const int ay = cy + rcGetDirOffsetY(dir); - - if (ax < hp.xmin || ax >= (hp.xmin+hp.width) || - ay < hp.ymin || ay >= (hp.ymin+hp.height)) - continue; - - if (hp.data[ax-hp.xmin+(ay-hp.ymin)*hp.width] != RC_UNSET_HEIGHT) - continue; - - const int ai = (int)chf.cells[(ax+bs)+(ay+bs)*chf.width].index + rcGetCon(cs, dir); - - const rcCompactSpan& as = chf.spans[ai]; - int idx = ax-hp.xmin+(ay-hp.ymin)*hp.width; - hp.data[idx] = as.y; - - stack.push(ax); - stack.push(ay); - stack.push(ai); - } - } - -} - -static unsigned char getEdgeFlags(const float* va, const float* vb, - const float* vpoly, const int npoly) -{ - // Return true if edge (va,vb) is part of the polygon. - static const float thrSqr = rcSqr(0.001f); - for (int i = 0, j = npoly-1; i < npoly; j=i++) - { - if (distancePtSeg2d(va, &vpoly[j*3], &vpoly[i*3]) < thrSqr && - distancePtSeg2d(vb, &vpoly[j*3], &vpoly[i*3]) < thrSqr) - return 1; - } - return 0; -} - -static unsigned char getTriFlags(const float* va, const float* vb, const float* vc, - const float* vpoly, const int npoly) -{ - unsigned char flags = 0; - flags |= getEdgeFlags(va,vb,vpoly,npoly) << 0; - flags |= getEdgeFlags(vb,vc,vpoly,npoly) << 2; - flags |= getEdgeFlags(vc,va,vpoly,npoly) << 4; - return flags; -} - -/// @par -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcAllocPolyMeshDetail, rcPolyMesh, rcCompactHeightfield, rcPolyMeshDetail, rcConfig -bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, - const float sampleDist, const float sampleMaxError, - rcPolyMeshDetail& dmesh) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_BUILD_POLYMESHDETAIL); - - if (mesh.nverts == 0 || mesh.npolys == 0) - return true; - - const int nvp = mesh.nvp; - const float cs = mesh.cs; - const float ch = mesh.ch; - const float* orig = mesh.bmin; - const int borderSize = mesh.borderSize; - - rcIntArray edges(64); - rcIntArray tris(512); - rcIntArray stack(512); - rcIntArray samples(512); - float verts[256*3]; - rcHeightPatch hp; - int nPolyVerts = 0; - int maxhw = 0, maxhh = 0; - - rcScopedDelete bounds = (int*)rcAlloc(sizeof(int)*mesh.npolys*4, RC_ALLOC_TEMP); - if (!bounds) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4); - return false; - } - rcScopedDelete poly = (float*)rcAlloc(sizeof(float)*nvp*3, RC_ALLOC_TEMP); - if (!poly) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3); - return false; - } - - // Find max size for a polygon area. - for (int i = 0; i < mesh.npolys; ++i) - { - const unsigned short* p = &mesh.polys[i*nvp*2]; - int& xmin = bounds[i*4+0]; - int& xmax = bounds[i*4+1]; - int& ymin = bounds[i*4+2]; - int& ymax = bounds[i*4+3]; - xmin = chf.width; - xmax = 0; - ymin = chf.height; - ymax = 0; - for (int j = 0; j < nvp; ++j) - { - if(p[j] == RC_MESH_NULL_IDX) break; - const unsigned short* v = &mesh.verts[p[j]*3]; - xmin = rcMin(xmin, (int)v[0]); - xmax = rcMax(xmax, (int)v[0]); - ymin = rcMin(ymin, (int)v[2]); - ymax = rcMax(ymax, (int)v[2]); - nPolyVerts++; - } - xmin = rcMax(0,xmin-1); - xmax = rcMin(chf.width,xmax+1); - ymin = rcMax(0,ymin-1); - ymax = rcMin(chf.height,ymax+1); - if (xmin >= xmax || ymin >= ymax) continue; - maxhw = rcMax(maxhw, xmax-xmin); - maxhh = rcMax(maxhh, ymax-ymin); - } - - hp.data = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxhw*maxhh, RC_ALLOC_TEMP); - if (!hp.data) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh); - return false; - } - - dmesh.nmeshes = mesh.npolys; - dmesh.nverts = 0; - dmesh.ntris = 0; - dmesh.meshes = (unsigned int*)rcAlloc(sizeof(unsigned int)*dmesh.nmeshes*4, RC_ALLOC_PERM); - if (!dmesh.meshes) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4); - return false; - } - - int vcap = nPolyVerts+nPolyVerts/2; - int tcap = vcap*2; - - dmesh.nverts = 0; - dmesh.verts = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); - if (!dmesh.verts) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", vcap*3); - return false; - } - dmesh.ntris = 0; - dmesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char*)*tcap*4, RC_ALLOC_PERM); - if (!dmesh.tris) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4); - return false; - } - - for (int i = 0; i < mesh.npolys; ++i) - { - const unsigned short* p = &mesh.polys[i*nvp*2]; - - // Store polygon vertices for processing. - int npoly = 0; - for (int j = 0; j < nvp; ++j) - { - if(p[j] == RC_MESH_NULL_IDX) break; - const unsigned short* v = &mesh.verts[p[j]*3]; - poly[j*3+0] = v[0]*cs; - poly[j*3+1] = v[1]*ch; - poly[j*3+2] = v[2]*cs; - npoly++; - } - - // Get the height data from the area of the polygon. - hp.xmin = bounds[i*4+0]; - hp.ymin = bounds[i*4+2]; - hp.width = bounds[i*4+1]-bounds[i*4+0]; - hp.height = bounds[i*4+3]-bounds[i*4+2]; - getHeightData(chf, p, npoly, mesh.verts, borderSize, hp, stack); - - // Build detail mesh. - int nverts = 0; - if (!buildPolyDetail(ctx, poly, npoly, - sampleDist, sampleMaxError, - chf, hp, verts, nverts, tris, - edges, samples)) - { - return false; - } - - // Move detail verts to world space. - for (int j = 0; j < nverts; ++j) - { - verts[j*3+0] += orig[0]; - verts[j*3+1] += orig[1] + chf.ch; // Is this offset necessary? - verts[j*3+2] += orig[2]; - } - // Offset poly too, will be used to flag checking. - for (int j = 0; j < npoly; ++j) - { - poly[j*3+0] += orig[0]; - poly[j*3+1] += orig[1]; - poly[j*3+2] += orig[2]; - } - - // Store detail submesh. - const int ntris = tris.size()/4; - - dmesh.meshes[i*4+0] = (unsigned int)dmesh.nverts; - dmesh.meshes[i*4+1] = (unsigned int)nverts; - dmesh.meshes[i*4+2] = (unsigned int)dmesh.ntris; - dmesh.meshes[i*4+3] = (unsigned int)ntris; - - // Store vertices, allocate more memory if necessary. - if (dmesh.nverts+nverts > vcap) - { - while (dmesh.nverts+nverts > vcap) - vcap += 256; - - float* newv = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM); - if (!newv) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newv' (%d).", vcap*3); - return false; - } - if (dmesh.nverts) - memcpy(newv, dmesh.verts, sizeof(float)*3*dmesh.nverts); - rcFree(dmesh.verts); - dmesh.verts = newv; - } - for (int j = 0; j < nverts; ++j) - { - dmesh.verts[dmesh.nverts*3+0] = verts[j*3+0]; - dmesh.verts[dmesh.nverts*3+1] = verts[j*3+1]; - dmesh.verts[dmesh.nverts*3+2] = verts[j*3+2]; - dmesh.nverts++; - } - - // Store triangles, allocate more memory if necessary. - if (dmesh.ntris+ntris > tcap) - { - while (dmesh.ntris+ntris > tcap) - tcap += 256; - unsigned char* newt = (unsigned char*)rcAlloc(sizeof(unsigned char)*tcap*4, RC_ALLOC_PERM); - if (!newt) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newt' (%d).", tcap*4); - return false; - } - if (dmesh.ntris) - memcpy(newt, dmesh.tris, sizeof(unsigned char)*4*dmesh.ntris); - rcFree(dmesh.tris); - dmesh.tris = newt; - } - for (int j = 0; j < ntris; ++j) - { - const int* t = &tris[j*4]; - dmesh.tris[dmesh.ntris*4+0] = (unsigned char)t[0]; - dmesh.tris[dmesh.ntris*4+1] = (unsigned char)t[1]; - dmesh.tris[dmesh.ntris*4+2] = (unsigned char)t[2]; - dmesh.tris[dmesh.ntris*4+3] = getTriFlags(&verts[t[0]*3], &verts[t[1]*3], &verts[t[2]*3], poly, npoly); - dmesh.ntris++; - } - } - - ctx->stopTimer(RC_TIMER_BUILD_POLYMESHDETAIL); - - return true; -} - -/// @see rcAllocPolyMeshDetail, rcPolyMeshDetail -bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_MERGE_POLYMESHDETAIL); - - int maxVerts = 0; - int maxTris = 0; - int maxMeshes = 0; - - for (int i = 0; i < nmeshes; ++i) - { - if (!meshes[i]) continue; - maxVerts += meshes[i]->nverts; - maxTris += meshes[i]->ntris; - maxMeshes += meshes[i]->nmeshes; - } - - mesh.nmeshes = 0; - mesh.meshes = (unsigned int*)rcAlloc(sizeof(unsigned int)*maxMeshes*4, RC_ALLOC_PERM); - if (!mesh.meshes) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'pmdtl.meshes' (%d).", maxMeshes*4); - return false; - } - - mesh.ntris = 0; - mesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char)*maxTris*4, RC_ALLOC_PERM); - if (!mesh.tris) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", maxTris*4); - return false; - } - - mesh.nverts = 0; - mesh.verts = (float*)rcAlloc(sizeof(float)*maxVerts*3, RC_ALLOC_PERM); - if (!mesh.verts) - { - ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", maxVerts*3); - return false; - } - - // Merge datas. - for (int i = 0; i < nmeshes; ++i) - { - rcPolyMeshDetail* dm = meshes[i]; - if (!dm) continue; - for (int j = 0; j < dm->nmeshes; ++j) - { - unsigned int* dst = &mesh.meshes[mesh.nmeshes*4]; - unsigned int* src = &dm->meshes[j*4]; - dst[0] = (unsigned int)mesh.nverts+src[0]; - dst[1] = src[1]; - dst[2] = (unsigned int)mesh.ntris+src[2]; - dst[3] = src[3]; - mesh.nmeshes++; - } - - for (int k = 0; k < dm->nverts; ++k) - { - rcVcopy(&mesh.verts[mesh.nverts*3], &dm->verts[k*3]); - mesh.nverts++; - } - for (int k = 0; k < dm->ntris; ++k) - { - mesh.tris[mesh.ntris*4+0] = dm->tris[k*4+0]; - mesh.tris[mesh.ntris*4+1] = dm->tris[k*4+1]; - mesh.tris[mesh.ntris*4+2] = dm->tris[k*4+2]; - mesh.tris[mesh.ntris*4+3] = dm->tris[k*4+3]; - mesh.ntris++; - } - } - - ctx->stopTimer(RC_TIMER_MERGE_POLYMESHDETAIL); - - return true; -} - diff --git a/critterai/.svn/pristine/89/89b9dc928dd850cff4c66a9e88a9ca17bf3fd352.svn-base b/critterai/.svn/pristine/89/89b9dc928dd850cff4c66a9e88a9ca17bf3fd352.svn-base deleted file mode 100644 index 1d8ce025..00000000 --- a/critterai/.svn/pristine/89/89b9dc928dd850cff4c66a9e88a9ca17bf3fd352.svn-base +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nav.u3d -{ - /// - /// Represents the core configuration values used during the build of a object. - /// - /// - /// - /// This information is used when doing a partial rebuild of the mesh. - /// - /// - /// This is a class with public fields in order to support Unity serialization. - /// - /// - [System.Serializable] - public sealed class NavmeshBuildInfo - { - /// - /// Tile size. - /// - public int tileSize; - - /// - /// XZ-plane cell size. - /// - public float xzCellSize; - - /// - /// Y-axis cell size. - /// - public float yCellSize; - - /// - /// Walkable height. - /// - public int walkableHeight; - - /// - /// Walkable step. - /// - public int walkableStep; - - /// - /// Walkable radius. - /// - public int walkableRadius; - - /// - /// Border size. - /// - public int borderSize; - - /// - /// The full path to the scene used to build the mesh. - /// - public string inputScene; - - /// - /// Clones the object. - /// - /// A clone of the object. - public NavmeshBuildInfo Clone() - { - NavmeshBuildInfo result = new NavmeshBuildInfo(); - result.tileSize = tileSize; - result.borderSize = borderSize; - result.walkableHeight = walkableHeight; - result.walkableRadius = walkableRadius; - result.walkableStep = walkableStep; - result.xzCellSize = xzCellSize; - result.yCellSize = yCellSize; - result.inputScene = inputScene; - return result; - } - } -} diff --git a/critterai/.svn/pristine/89/89dc41b40fccb3d98b7786b179e4b0d15b9f3dd9.svn-base b/critterai/.svn/pristine/89/89dc41b40fccb3d98b7786b179e4b0d15b9f3dd9.svn-base deleted file mode 100644 index 890e3788..00000000 Binary files a/critterai/.svn/pristine/89/89dc41b40fccb3d98b7786b179e4b0d15b9f3dd9.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/8a/8a4b0bea073b116f6660a513e08adf343db729ca.svn-base b/critterai/.svn/pristine/8a/8a4b0bea073b116f6660a513e08adf343db729ca.svn-base deleted file mode 100644 index 1fa915cc..00000000 --- a/critterai/.svn/pristine/8a/8a4b0bea073b116f6660a513e08adf343db729ca.svn-base +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// A set of objects used in an NMGen build. - /// - /// - /// - /// The processor set groups a set of processors for use in an NMGen build. If all - /// contained processors are thread-safe, then the process set can be used in a threaded build. - /// - /// - /// To create an empty processor set, call with no - /// options set. - /// - /// - /// - /// - public sealed class ProcessorSet - { - /// - /// The build options that most builds will require. - /// - public const NMGenBuildFlag StandardOptions = NMGenBuildFlag.ApplyPolyFlags - | NMGenBuildFlag.LowHeightSpansNotWalkable - | NMGenBuildFlag.LowObstaclesWalkable; - - private readonly bool mIsThreadSafe; - private readonly INMGenProcessor[] mProcessors; - private readonly NMGenAssetFlag mPreserveAssets; - - private ProcessorSet(INMGenProcessor[] processors) - { - mProcessors = processors; - - PriorityComparer comp = - new PriorityComparer(true); - - System.Array.Sort(mProcessors, comp); - - mIsThreadSafe = true; // This is correct. - - foreach (INMGenProcessor p in mProcessors) - { - mPreserveAssets |= p.PreserveAssets; - - if (!p.IsThreadSafe) - mIsThreadSafe = false; - } - } - - /// - /// The build assets that should be preserved past their normal disposal point. - /// - /// - /// - /// This is an aggregate of the for - /// all contained processors. - /// - /// - public NMGenAssetFlag PreserveAssets { get { return mPreserveAssets; } } - - /// - /// True if all contained processors are threadsafe. - /// - public bool IsThreadSafe { get { return mIsThreadSafe; } } - - /// - /// The number of processors in the set. - /// - public int Count { get { return mProcessors.Length; } } - - /// - /// Runs all the processors in order of priority. (Ascending) - /// - /// - /// - /// A return value of false indicates the build should be aborted. - /// - /// - /// The current state of the build. - /// The build context. - /// False if the build should abort. - public bool Process(NMGenContext context, NMGenState state) - { - foreach (INMGenProcessor p in mProcessors) - { - if (!p.ProcessBuild(context, state)) - return false; - } - return true; - } - - /// - /// Logs processor information to the context for debug purposes. - /// - /// The build context. - public void LogProcessors(NMGenContext context) - { - foreach (INMGenProcessor p in mProcessors) - { - context.Log(string.Format("Processor: {0} ({1})", p.Name, p.GetType().Name) - , this); - } - } - - /// - /// Gets standard processors based on the provided options. - /// - /// The processors to include. - /// - /// The standard processors, or a zero length array if no processors selected. - /// - public static INMGenProcessor[] GetStandard(NMGenBuildFlag options) - { - List ps = new List(); - - if ((options & NMGenBuildFlag.ApplyPolyFlags) != 0) - { - ps.Add(new ApplyPolygonFlags("ApplyDefaultPolyFlag" - , NMBuild.MinPriority, NMBuild.DefaultFlag)); - } - - if ((options & NMGenBuildFlag.LedgeSpansNotWalkable) != 0) - ps.Add(FilterLedgeSpans.Instance); - - if ((options & NMGenBuildFlag.LowHeightSpansNotWalkable) != 0) - ps.Add(FilterLowHeightSpans.Instance); - - if ((options & NMGenBuildFlag.LowObstaclesWalkable) != 0) - ps.Add(LowObstaclesWalkable.Instance); - - return ps.ToArray(); - } - - /// - /// Creates a processor set based on the provided options. - /// - /// - /// - /// An empty processor set will be created if is zero. - /// - /// - /// The processors to include. - /// A processor set with the standard processors. - public static ProcessorSet CreateStandard(NMGenBuildFlag options) - { - return Create(GetStandard(options)); - } - - /// - /// Creates a processor set loaded with the provided processors. - /// - /// - /// - /// An empty processor set will be created if is null - /// or contains no processors. - /// - /// - /// The processors to include in the set. - /// The processor set - public static ProcessorSet Create(INMGenProcessor[] processors) - { - INMGenProcessor[] lprocessors = ArrayUtil.Compress(processors); - - if (lprocessors == null) - lprocessors = new INMGenProcessor[0]; - else if (lprocessors == processors) - lprocessors = (INMGenProcessor[])processors.Clone(); - - return new ProcessorSet(lprocessors); - } - } -} diff --git a/critterai/.svn/pristine/8a/8a9d275e96be8766e7f1640857bb82629719f78c.svn-base b/critterai/.svn/pristine/8a/8a9d275e96be8766e7f1640857bb82629719f78c.svn-base deleted file mode 100644 index aad661ab..00000000 --- a/critterai/.svn/pristine/8a/8a9d275e96be8766e7f1640857bb82629719f78c.svn-base +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using org.critterai.geom; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// A builder for the class. - /// - /// - /// - /// The standard use case is as follows: - /// - ///
        - ///
      1. Create the builder using
      2. - ///
      3. Call until it returns true.
      4. - ///
      5. Get the result from .
      6. - ///
      - /// - /// A builder object cannot be re-used. (Single use.) - /// - /// - /// The builder is safe to run on a separate thread as long as the objects used to create - /// the builder are not mutated while the build is in-progress. - /// - ///
      - public sealed class ChunkyTriMeshBuilder - { - private enum BuildState - { - PreProcessing, - Running, - Complete, - } - - private struct BoundsItem - { - public float xmin; - public float zmin; - public float xmax; - public float zmax; - public int i; - } - - private class BoundsItemCompareX - : IComparer - { - public int Compare(BoundsItem x, BoundsItem y) - { - if (x.xmin < y.xmin) - return -1; - if (x.xmin > y.xmin) - return 1; - return 0; - } - } - - private class BoundsItemCompareZ - : IComparer - { - public int Compare(BoundsItem x, BoundsItem y) - { - if (x.zmin < y.zmin) - return -1; - if (x.zmin > y.zmin) - return 1; - return 0; - } - } - - private class BuildContext - { - private readonly Stack mPool = new Stack(); - - public int[] tris; - public byte[] areas; - public ChunkyTriMeshNode[] nodes; - public BoundsItem[] items; - public int[] inTris; - public byte[] inAreas; - public int curNode; - public int curTri; - public int trisPerChunk; - - public Subdivide Get(int imin, int imax) - { - if (mPool.Count == 0) - return new Subdivide(imin, imax); - - Subdivide result = mPool.Pop(); - result.Reset(imin, imax); - return result; - } - - public void Return(Subdivide item) - { - mPool.Push(item); - } - - public void Reset() - { - mPool.Clear(); - tris = null; - areas = null; - nodes = null; - items = null; - inTris = null; - inAreas = null; - } - } - - private class Subdivide - { - private enum State - { - None, - Right, - Finalize, - Complete - } - - private State state = State.None; - private int icur; - private int imin; - private int imax; - private int isplit; // Yes, this is necessary. - private int inode; - - public Subdivide(int imin, int imax) - { - this.imin = imin; - this.imax = imax; - } - - public void Reset(int imin, int imax) - { - state = State.None; - icur = 0; - this.imin = imin; - this.imax = imax; - isplit = 0; - inode = 0; - } - - public Subdivide Build(BuildContext data) - { - switch (state) - { - case State.None: - - Subdivide c = Initialize(data); - - state = (c == null) ? State.Complete : State.Right; - - return c; - - case State.Right: - - state = State.Finalize; - - return (data.Get(isplit, imax)); - - case State.Finalize: - - int iescape = data.curNode - icur; - - // Negative index means escape. - data.nodes[inode].i = -iescape; - - state = State.Complete; - - break; - } - - return null; - } - - private Subdivide Initialize(BuildContext data) - { - int inum = imax - imin; - icur = data.curNode; - - ChunkyTriMeshNode[] nodes = data.nodes; - BoundsItem[] items = data.items; - - if (data.curNode > nodes.Length) - return null; - - inode = data.curNode++; - - if (inum <= data.trisPerChunk) - { - // Leaf - DeriveExtents(items - , imin - , imax - , ref nodes[inode]); - - // Copy triangles. - nodes[inode].i = data.curTri; - nodes[inode].count = inum; - - for (int i = imin; i < imax; ++i) - { - int pi = items[i].i * 3; - int pd = data.curTri * 3; - - data.tris[pd + 0] = data.inTris[pi + 0]; - data.tris[pd + 1] = data.inTris[pi + 1]; - data.tris[pd + 2] = data.inTris[pi + 2]; - - data.areas[data.curTri] = data.inAreas[items[i].i]; - - data.curTri++; - } - } - else - { - // Split - DeriveExtents(items, imin, imax, ref nodes[inode]); - - int axis = - (nodes[inode].zmax - nodes[inode].zmin - > nodes[inode].xmax - nodes[inode].xmin) - ? 1 : 0; - - if (axis == 0) - { - // Sort along x-axis - Array.Sort(items, imin, inum, mCompareX); - } - else if (axis == 1) - { - // Sort along y-axis - Array.Sort(items, imin, inum, mCompareZ); - } - - isplit = imin + inum / 2; - - // Left - return data.Get(imin, isplit); - } - - return null; - } - } - - /// - /// The minimum allowed triangles per chunk. - /// - public const int MinAllowedTrisPerChunk = 64; - - private static readonly BoundsItemCompareX mCompareX = new BoundsItemCompareX(); - private static readonly BoundsItemCompareZ mCompareZ = new BoundsItemCompareZ(); - - private static int mTriangleIterations = 100000; - private static int mNodeIterations = 100; - - /// - /// The number of nodes the build will process in a single build step. [>= 1] - /// - /// - /// - /// Used for tuning responsiveness. - /// - /// - public static int ChunkTuneValue - { - get { return mNodeIterations; } - set { mNodeIterations = Math.Max(1, value); } - } - - /// - /// The number of triangles the build will process in a single build step. [>= 1] - /// - /// - /// - /// Used for tuning responsiveness. - /// - /// - public static int PreprocessTuneValue - { - get { return mTriangleIterations; } - set { mTriangleIterations = Math.Max(1, value); } - } - - private readonly int mTriCount; - private readonly Vector3[] mVerts; - private readonly int mVertCount; - private ChunkyTriMesh mMesh; - - private int mIter = 0; - private BuildState mState; - - private readonly BuildContext buildData = new BuildContext(); - private readonly Stack mStack = new Stack(); - - /// - /// The mesh created by the build. (Only available on successful completion.) - /// - public ChunkyTriMesh Result { get { return mMesh; } } - - /// - /// True if the build is finished. - /// - public bool IsFinished { get { return (mMesh != null); } } - - private ChunkyTriMeshBuilder(Vector3[] verts - , int vertCount - , int[] tris - , byte[] areas - , int triCount - , int trisPerChunk) - { - mVerts = verts; - mVertCount = vertCount; - - buildData.inTris = tris; - buildData.inAreas = areas; - - buildData.items = new BoundsItem[triCount]; - buildData.tris = new int[triCount * 3]; - buildData.areas = new byte[triCount]; - - int nchunks = (triCount + trisPerChunk - 1) / trisPerChunk; - buildData.nodes = new ChunkyTriMeshNode[nchunks * 4]; - - buildData.trisPerChunk = trisPerChunk; - mTriCount = triCount; - } - - /// - /// Performs a single build step. - /// - /// - /// - /// This method must be called repeatedly until it resturns false in order - /// to complete the build. (Useful in GUI environments.) - /// - /// - /// - /// True if the build is still underway and another call is required. False if the build - /// is finished. - /// - public bool Build() - { - switch (mState) - { - case BuildState.PreProcessing: - - UpdateInitialize(); - return true; - - case BuildState.Running: - - UpdateSubdivide(); - return true; - } - - return false; - } - - /// - /// Performs the build in a single step. - /// - public void BuildAll() - { - while (Build()) { } - } - - private void UpdateSubdivide() - { - mIter = 0; - while (mStack.Count > 0 && mIter < mNodeIterations) - { - Subdivide c = mStack.Peek().Build(buildData); - - if (c == null) - // Finished. - buildData.Return(mStack.Pop()); - else - // New sub-divide. - mStack.Push(c); - - mIter++; - } - - if (mStack.Count == 0) - { - mMesh = new ChunkyTriMesh(mVerts - , mVertCount - , buildData.tris - , buildData.areas - , mTriCount - , buildData.nodes - , buildData.curNode); - - buildData.Reset(); // Release references. - - mState = BuildState.Complete; - } - } - - private void UpdateInitialize() - { - BoundsItem[] items = buildData.items; - int[] tris = buildData.inTris; - - int target = Math.Min(mTriCount, mIter + mTriangleIterations); - - for (; mIter < target; mIter++) - { - int pi = mIter * 3; - items[mIter].i = mIter; - - // Calc triangle XZ bounds. - items[mIter].xmin = - items[mIter].xmax = mVerts[tris[pi]].x; - items[mIter].zmin = - items[mIter].zmax = mVerts[tris[pi]].z; - - for (int j = 1; j < 3; j++) - { - // const float* v = &verts[t[j] * 3]; - - float val = mVerts[tris[pi + j]].x; - - if (val < items[mIter].xmin) - items[mIter].xmin = val; - - if (val > items[mIter].xmax) - items[mIter].xmax = val; - - val = mVerts[tris[pi + j]].z; - - if (val < items[mIter].zmin) - items[mIter].zmin = val; - - if (val > items[mIter].zmax) - items[mIter].zmax = val; - } - } - - if (target < mTriCount) - // Still more to do. - return; - - buildData.curNode = 0; - buildData.curTri = 0; - - mStack.Push(new Subdivide(0, mTriCount)); - - mState = BuildState.Running; - } - - private static void DeriveExtents(BoundsItem[] items, - int imin, int imax, - ref ChunkyTriMeshNode node) - { - node.xmin = items[imin].xmin; - node.zmin = items[imin].zmin; - - node.xmax = items[imin].xmax; - node.zmax = items[imin].zmax; - - for (int i = imin + 1; i < imax; ++i) - { - if (items[i].xmin < node.xmin) - node.xmin = items[i].xmin; - - if (items[i].zmin < node.zmin) - node.zmin = items[i].zmin; - - if (items[i].xmax > node.xmax) - node.xmax = items[i].xmax; - - if (items[i].zmax > node.zmax) - node.zmax = items[i].zmax; - } - } - - /// - /// Creates a single use builder. - /// - /// - /// - /// Will return null on parameter errors, an input mesh with zero triangles, - /// and structural issues in the mesh object or area array. Does not perform a validation - /// of the mesh or area content. (E.g. Does not check for invalid mesh indices.) - /// - /// - /// The triangle mesh to chunk. - /// The areas for each triangle in the mesh. (Null not allowed.) - /// - /// The maximum number of triangles per chunk. - /// [Limit: >= ] - /// - /// A builder, or null on error. - public static ChunkyTriMeshBuilder Create(TriangleMesh mesh - , byte[] areas - , int trisPerChunk) - { - if (mesh == null - || areas == null - || mesh.triCount == 0 - || !TriangleMesh.IsValid(mesh, false) - || areas.Length < mesh.triCount) - { - return null; - } - - trisPerChunk = Math.Max(MinAllowedTrisPerChunk, trisPerChunk); - - return new ChunkyTriMeshBuilder(mesh.verts, mesh.vertCount - , mesh.tris, areas, mesh.triCount - , trisPerChunk); - } - } -} diff --git a/critterai/.svn/pristine/8a/8ac146bfa4b6dba1b82102aa0f645ce1da18db40.svn-base b/critterai/.svn/pristine/8a/8ac146bfa4b6dba1b82102aa0f645ce1da18db40.svn-base deleted file mode 100644 index 05ee41ec..00000000 --- a/critterai/.svn/pristine/8a/8ac146bfa4b6dba1b82102aa0f645ce1da18db40.svn-base +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.*; -import static org.critterai.math.geom.Triangle3.*; -import static org.critterai.math.MathUtil.*; -import static org.critterai.math.Vector3.*; - -import org.critterai.math.Vector3; -import org.critterai.math.geom.Triangle3; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Triangle3} class. - */ -public class Triangle3Tests { - - // Clockwise wrapped - private static final float AX = 3; - private static final float AY = 2; - private static final float AZ = -1; - private static final float BX = 2; - private static final float BY = -1; - private static final float BZ = 1; - private static final float CX = 0; - private static final float CY = -1; - private static final float CZ = 0; - - @Before - public void setUp() - throws Exception - { - } - - @Test - public void testGetArea() - { - float expected = getHeronArea(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ); - float actual = getArea(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ); - assertTrue(sloppyEquals(actual, expected, 0.0001f)); - } - - @Test - public void testGetAreaComp() - { - float expected = getHeronArea(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ); - float actual = (float)Math.sqrt(getAreaComp(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ))/2; - assertTrue(sloppyEquals(actual, expected, 0.0001f)); - } - - @Test - public void testGetNormalFloatVector3() - { - Vector3 v = new Vector3(); - assertTrue(v == getNormal(AX, AY, 0, BX, BY, 0, CX, CY, 0, v)); - assertTrue(v.sloppyEquals(0, 0, -1, 0.0001f)); - assertTrue(v == getNormal(AX, AY, 0, CX, CY, 0, BX, BY, 0, v)); - assertTrue(v.sloppyEquals(0, 0, 1, 0.0001f)); - assertTrue(v == getNormal(AX, 0, AZ, BX, 0, BZ, CX, 0, CZ, v)); - assertTrue(v.sloppyEquals(0, -1, 0, 0.0001f)); - assertTrue(v == getNormal(0, AY, AZ, 0, BY, BZ, 0, CY, CZ, v)); - assertTrue(v.sloppyEquals(1, 0, 0, 0.0001f)); - } - - @Test - public void testGetNormalArrayVector3() - { - float[] vertices = { - 5, 5, 5 - , AX, 0, AZ - , BX, 0, BZ - , CX, 0, CZ - , 9, 9, 9 - }; - Vector3 v = new Vector3(); - assertTrue(v == getNormal(vertices, 1, v)); - assertTrue(v.sloppyEquals(0, -1, 0, 0.0001f)); - } - - private float getHeronArea(float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz) - { - double a = Math.sqrt(getDistanceSq(AX, AY, AZ, BX, BY, BZ)); - double b = Math.sqrt(getDistanceSq(AX, AY, AZ, CX, CY, CZ)); - double c = Math.sqrt(getDistanceSq(CX, CY, CZ, BX, BY, BZ)); - double s = (a + b + c)/2; - return (float)Math.sqrt(s * (s - a) * (s - b) * (s - c)); - } - -} diff --git a/critterai/.svn/pristine/8b/8babca12bd2b7be4a14ca803dec4932badf6f158.svn-base b/critterai/.svn/pristine/8b/8babca12bd2b7be4a14ca803dec4932badf6f158.svn-base deleted file mode 100644 index 0a580266..00000000 --- a/critterai/.svn/pristine/8b/8babca12bd2b7be4a14ca803dec4932badf6f158.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-util-u3d")] -[assembly: AssemblyDescription("Shared utilities for CAI Unity products.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAI")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2010-2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.5.0.0")] -[assembly: AssemblyFileVersion("0.5.0.0")] diff --git a/critterai/.svn/pristine/8c/8c6c8b5bc04be5e3381b9366d9f568fba7065fba.svn-base b/critterai/.svn/pristine/8c/8c6c8b5bc04be5e3381b9366d9f568fba7065fba.svn-base deleted file mode 100644 index 171a8a2e..00000000 --- a/critterai/.svn/pristine/8c/8c6c8b5bc04be5e3381b9366d9f568fba7065fba.svn-base +++ /dev/null @@ -1,917 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.u3d -{ - /// - /// Provides various GL-based drawing methods suitable for debug views. - /// - /// - /// - /// Append methods require the caller to handle all GL setup and teardown. Unless otherwise - /// noted they expect GL to be in GL.Lines mode. - /// - /// - /// // Example: Using append methods: - /// - /// Vector3 startPos = new Vector3(1, 0, 0); - /// Vector3 endPos = new Vector3(10, 15, 20); - /// float scale = 1; - /// float height = 5; - /// - /// DebugDraw.SimpleMaterial.SetPass(0); - /// - /// GL.Begin(GL.LINES); - /// - /// GL.Color(Color.green); - /// DebugDraw.AppendXMarker(startPos, scale); - /// DebugDraw.AppendArc(startPos, endPos, height, scale * 0, scale * 0.1f); - /// - /// GL.Color(Color.red) - /// DebugDraw.AppendXMarker(endPos, scale); - /// - /// GL.End(); - /// - /// - public static class DebugDraw - { - private const float DarkenFactor = 2; - - private const int CircleSegments = 40; - private const float Epsilon = 0.001f; - - private static float[] mDir; - - private static float[] Dir - { - get - { - if (mDir == null) - { - mDir = new float[CircleSegments * 2]; - for (int i = 0; i < CircleSegments; i++) - { - float a = - (float)i / (float)CircleSegments * Mathf.PI * 2; - mDir[i * 2] = Mathf.Cos(a); - mDir[i * 2 + 1] = Mathf.Sin(a); - } - } - return mDir; - } - } - - private static Material mSimpleMaterial = null; - - /// - /// A shared material suitable for simple drawing operations. - /// - public static Material SimpleMaterial - { - get - { - if (!mSimpleMaterial) - { - mSimpleMaterial = new Material( - "Shader \"Lines/Colored Blended\" {" - + "SubShader { Pass { " - + " BindChannels { Bind \"Color\",color } " - + " Blend SrcAlpha OneMinusSrcAlpha " - + " ZWrite Off Cull Off Fog { Mode Off } " - + "} } }"); - mSimpleMaterial.hideFlags = HideFlags.HideAndDontSave; - mSimpleMaterial.shader.hideFlags = HideFlags.HideAndDontSave; - } - return mSimpleMaterial; - } - } - - /// - /// Draw a diamond shape at the specified position. - /// - /// - /// - /// A of 1.0 will result in a diamond with a width and height of - /// 2.0. (Each diamond point will be 1.0 units from the position.) - /// - /// - /// The position. - /// The scale of the diamond. - /// The surface color of the diamond. - public static void DiamondMarker(Vector3 position, float scale, Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - Vector3 u = position + Vector3.up * scale; - Vector3 d = position + Vector3.down * scale; - Vector3 r = position + Vector3.right * scale; - Vector3 l = position + Vector3.left * scale; - Vector3 f = position + Vector3.forward * scale; - Vector3 b = position + Vector3.back * scale; - - GL.Begin(GL.TRIANGLES); - - GL.Color(color); - - // Top - - GL.Vertex(u); - GL.Vertex(r); - GL.Vertex(f); - - GL.Vertex(u); - GL.Vertex(f); - GL.Vertex(l); - - GL.Vertex(u); - GL.Vertex(l); - GL.Vertex(b); - - GL.Vertex(u); - GL.Vertex(b); - GL.Vertex(r); - - // Bottom - - GL.Vertex(d); - GL.Vertex(f); - GL.Vertex(r); - - GL.Vertex(d); - GL.Vertex(r); - GL.Vertex(b); - - GL.Vertex(d); - GL.Vertex(b); - GL.Vertex(l); - - GL.Vertex(d); - GL.Vertex(l); - GL.Vertex(f); - - GL.End(); - - GL.Begin(GL.LINES); - - color.a *= DarkenFactor; - GL.Color(color); - - // Top - - GL.Vertex(u); - GL.Vertex(f); - - GL.Vertex(u); - GL.Vertex(b); - - GL.Vertex(u); - GL.Vertex(r); - - GL.Vertex(u); - GL.Vertex(l); - - // Bottom - - GL.Vertex(u); - GL.Vertex(f); - - GL.Vertex(u); - GL.Vertex(b); - - GL.Vertex(u); - GL.Vertex(r); - - GL.Vertex(u); - GL.Vertex(l); - - // Center - - GL.Vertex(r); - GL.Vertex(f); - - GL.Vertex(r); - GL.Vertex(b); - - GL.Vertex(l); - GL.Vertex(f); - - GL.Vertex(l); - GL.Vertex(b); - - GL.End(); - } - - /// - /// Draw an X-marker at the specified position. - /// - /// - /// - /// A of 1.0 will result in a marker with a width and height of - /// 2.0. (Each point of the x-marker will be 1.0 from the position.) - /// - /// - /// The position. - /// The scale of the marker. - /// The color of the marker. - public static void XMarker(Vector3 position - , float scale - , Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - AppendXMarker(position, scale); - - GL.End(); - } - - /// - /// Draw an X-marker at the specified position. - /// - /// - /// - /// A of 1.0 will result in a marker with a width and height of - /// 2.0. (Each point of the x-marker will be 1.0 from the position.) - /// - /// - /// The position. - /// The scale of the marker. - public static void AppendXMarker(Vector3 position, float scale) - { - GL.Vertex(position + Vector3.right * scale); - GL.Vertex(position + Vector3.left * scale); - GL.Vertex(position + Vector3.forward * scale); - GL.Vertex(position + Vector3.back * scale); - GL.Vertex(position + Vector3.up * scale * 2); - GL.Vertex(position + Vector3.down * scale * 2); - } - - /// - /// Append a filled convex polygon. - /// - /// - /// The polygon vertices. [Length: >= ] - /// - /// The number of vertices. - /// The color of the polygon surface. - public static void ConvexPoly(Vector3[] verts, int vertCount, Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.TRIANGLES); - - GL.Color(color); - - for (int i = 2; i < vertCount; i++) - { - int pB = i - 1; - int pC = i + 0; - - GL.Vertex(verts[0]); - GL.Vertex(verts[pB]); - GL.Vertex(verts[pC]); - } - - GL.End(); - - GL.Begin(GL.LINES); - - color.a *= DarkenFactor; - GL.Color(color); - - for (int i = 1; i < vertCount; i++) - { - int pA = i - 1; - int pB = i + 0; - - GL.Vertex(verts[pA]); - GL.Vertex(verts[pB]); - } - - GL.End(); - } - - - /// - /// Draw a wireframe axis-aligned bounding box. - /// - /// The minimum bounds. - /// The maximum bounds. - /// The wireframe color - public static void Bounds(Vector3 boundsMin, Vector3 boundsMax, Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - AppendBounds(boundsMin, boundsMax); - - GL.End(); - } - - /// - /// Append a wireframe axis-aligned bounding box. - /// - /// The minimum bounds. - /// The maximum bounds. - public static void AppendBounds(Vector3 boundsMin, Vector3 boundsMax) - { - Vector3 ua = boundsMax; - Vector3 ub = boundsMax; - Vector3 uc = boundsMax; - Vector3 ud = boundsMax; - ub.x = boundsMin.x; - uc.x = boundsMin.x; - uc.z = boundsMin.z; - ud.z = boundsMin.z; - - Vector3 la = boundsMin; - Vector3 lb = boundsMin; - Vector3 lc = boundsMin; - Vector3 ld = boundsMin; - - la.x = boundsMax.x; - la.z = boundsMax.z; - lb.z = boundsMax.z; - ld.x = boundsMax.x; - - // Top - GL.Vertex(ua); - GL.Vertex(ub); - GL.Vertex(ub); - GL.Vertex(uc); - GL.Vertex(uc); - GL.Vertex(ud); - GL.Vertex(ud); - GL.Vertex(ua); - - // Bottom - GL.Vertex(la); - GL.Vertex(lb); - GL.Vertex(lb); - GL.Vertex(lc); - GL.Vertex(lc); - GL.Vertex(ld); - GL.Vertex(ld); - GL.Vertex(la); - - // Risers - GL.Vertex(ua); - GL.Vertex(la); - GL.Vertex(ub); - GL.Vertex(lb); - GL.Vertex(uc); - GL.Vertex(lc); - GL.Vertex(ud); - GL.Vertex(ld); - } - - /// - /// Draw a wireframe axis-aligned bounding box representing the extents. - /// - /// The center of the bounding box. - /// The extents of the bounding box. (Half-lengths.) - /// The wireframe color. - public static void Extents(Vector3 position, Vector3 extents, Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - AppendExtents(position, extents); - - GL.End(); - } - - /// - /// Append a wireframe axis-aligned bounding box representing the extents. - /// - /// The center of the bounding box. - /// The extents of the bounding box. (Half-lengths.) - public static void AppendExtents(Vector3 position, Vector3 extents) - { - Vector3 ua = position + extents; - Vector3 ub = new Vector3( - position.x - extents.x - , position.y + extents.y - , position.z + extents.z); - Vector3 uc = new Vector3( - position.x - extents.x - , position.y + extents.y - , position.z - extents.z); - Vector3 ud = new Vector3( - position.x + extents.x - , position.y + extents.y - , position.z - extents.z); - - Vector3 la = new Vector3( - position.x + extents.x - , position.y - extents.y - , position.z + extents.z); - Vector3 lb = new Vector3( - position.x - extents.x - , position.y - extents.y - , position.z + extents.z); - Vector3 lc = position - extents; - Vector3 ld = new Vector3( - position.x + extents.x - , position.y - extents.y - , position.z - extents.z); - - // Top - GL.Vertex(ua); - GL.Vertex(ub); - GL.Vertex(ub); - GL.Vertex(uc); - GL.Vertex(uc); - GL.Vertex(ud); - GL.Vertex(ud); - GL.Vertex(ua); - - // Bottom - GL.Vertex(la); - GL.Vertex(lb); - GL.Vertex(lb); - GL.Vertex(lc); - GL.Vertex(lc); - GL.Vertex(ld); - GL.Vertex(ld); - GL.Vertex(la); - - // Risers - GL.Vertex(ua); - GL.Vertex(la); - GL.Vertex(ub); - GL.Vertex(lb); - GL.Vertex(uc); - GL.Vertex(lc); - GL.Vertex(ud); - GL.Vertex(ld); - } - - /// - /// Draw a simple wireframe cylinder with four risers. - /// - /// The center point of the cylinder base. - /// The radius. - /// The cylinder height, relative to the base. - /// - /// True if a circle should be drawn halfway from the base to the top of the cyclinder. - /// - /// The wireframe color. - public static void Cylinder(Vector3 position, float radius, float height - , bool includeHalf - , Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - AppendCylinder(position, radius, height, includeHalf); - - GL.End(); - } - - /// - /// Append a simple wireframe cylinder with four risers. - /// - /// The center point of the cylinder base. - /// The radius. - /// The cylinder height, relative to the base. - /// - /// True if a circle should be drawn halfway from the base to the top of the cyclinder. - /// - public static void AppendCylinder(Vector3 position, float radius, float height - , bool includeHalf) - { - AppendCircle(position, radius); - AppendCircle(position + Vector3.up * height, radius); - - if (includeHalf) - AppendCircle(position + Vector3.up * height * 0.5f, radius); - - float[] dir = Dir; - - for (int i = 0, j = CircleSegments - 1; i < CircleSegments; j = i += 5) - { - float x = position.x + dir[j * 2 + 0] * radius; - float z = position.z + dir[j * 2 + 1] * radius; - GL.Vertex3(x, position.y, z); - GL.Vertex3(x, position.y + height, z); - } - } - - /// - /// Draw an unfilled circle on the xz-plane. - /// - /// The center position. - /// The radius. - /// The color. - public static void Circle(Vector3 position, float radius, Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - AppendCircle(position, radius); - - GL.End(); - } - - /// - /// Append an unfilled circle on the xz-plane. - /// - /// The center position. - /// The radius. - public static void AppendCircle(Vector3 position, float radius) - { - float[] dir = Dir; - - for (int i = 0, j = CircleSegments - 1; i < CircleSegments; j = i++) - { - GL.Vertex3(position.x + dir[j * 2 + 0] * radius - , position.y - , position.z + dir[j * 2 + 1] * radius); - GL.Vertex3(position.x + dir[i * 2 + 0] * radius - , position.y - , position.z + dir[i * 2 + 1] * radius); - } - } - - /// - /// Draw an arrow. - /// - /// Endpoint A. - /// Endpoint B. - /// - /// The scale of endpoint A arrow head. (Or zero for no head.) - /// - /// - /// The scale of the endpoint B arrow head.(Or zero for no head.) - /// - /// The color. - public static void Arrow(Vector3 pointA, Vector3 pointB - , float headScaleA, float headScaleB - , Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - AppendArrow(pointA, pointB, headScaleA, headScaleB); - - GL.End(); - } - - /// - /// Append an arrow. - /// - /// Endpoint A. - /// Endpoint B. - /// - /// The scale of endpoint A arrow head. (Or zero for no head.) - /// - /// - /// The scale of the endpoint B arrow head.(Or zero for no head.) - /// - public static void AppendArrow(Vector3 pointA, Vector3 pointB - , float headScaleA, float headScaleB) - { - GL.Vertex(pointA); - GL.Vertex(pointB); - - if (headScaleA > Epsilon) - AppendArrowHead(pointA, pointB, headScaleA); - if (headScaleB > Epsilon) - AppendArrowHead(pointB, pointA, headScaleB); - } - - private static void AppendArrowHead(Vector3 start - , Vector3 end - , float headScale) - { - if (Vector3.SqrMagnitude(end - start) < Epsilon * Epsilon) - return; - - Vector3 az = (end - start).normalized; - //Vector3 ax = Vector3.Cross(Vector3.up, az); - //// Vector3 ay = Vector3.Cross(az, ax).normalized; - - Vector3 vbase = start + az * headScale; - Vector3 offset = Vector3.Cross(Vector3.up, az) * headScale * 0.333f; - - GL.Vertex(start); - GL.Vertex(vbase + offset); - - GL.Vertex(start); - GL.Vertex(vbase - offset); - } - - /// - /// Draw a triangle mesh. - /// - /// The vertices. - /// - /// The triangle indices. - /// [(vertAIndex, vertBIndex, vertCIndex) * ] - /// - /// The number of triangles. - /// True if the triangle edges should be drawn. - /// The surface color. - public static void TriangleMesh(Vector3[] verts, int[] tris, int triCount - , bool includeEdges - , Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - int length = triCount * 3; - - GL.Begin(GL.TRIANGLES); - GL.Color(color); - - for (int p = 0; p < length; p += 3) - { - for (int i = 0; i < 3; i++) - { - GL.Vertex(verts[tris[p + i]]); - } - } - GL.End(); - - if (!includeEdges) - return; - - color.a *= DarkenFactor; - GL.Begin(GL.LINES); - GL.Color(color); - - for (int p = 0; p < length; p += 3) - { - for (int i = 0; i < 3; i++) - { - GL.Vertex(verts[tris[p + i]]); - } - GL.Vertex(verts[tris[p]]); - } - - GL.End(); - } - - /// - /// Draw a triangle mesh, colored per triangle. - /// - /// The vertices. - /// - /// The triangle indices. - /// [(vertAIndex, vertBIndex, vertCIndex) * ] - /// - /// The color area assigned to the triangle. - /// The number of triangles. - /// True if the triangle edges should be drawn. - /// The surface alpha. - public static void TriangleMesh(Vector3[] verts - , int[] tris, byte[] areas, int triCount - , bool includeEdges - , float surfaceAlpha) - { - DebugDraw.SimpleMaterial.SetPass(0); - GL.Begin(GL.TRIANGLES); - - for (int i = 0; i < triCount; i++) - { - GL.Color(ColorUtil.IntToColor(areas[i], surfaceAlpha)); - for (int j = 0; j < 3; j++) - { - GL.Vertex(verts[tris[i * 3 + j]]); - } - } - - GL.End(); - GL.Begin(GL.LINES); - - Color c = Color.gray; - c.a = surfaceAlpha * DarkenFactor; - - for (int i = 0; i < triCount; i++) - { - for (int j = 0; j < 3; j++) - { - GL.Vertex(verts[tris[i * 3 + j]]); - } - - GL.Vertex(verts[tris[i * 3]]); - } - - GL.End(); - } - - /// - /// Draw an axis aligned rectangle on the xz-plane. - /// - /// The mimimum origin. - /// The width along the x-axis. - /// The depth along the z-axis. - /// The color. - /// True if the rectangle should be filled. - public static void Rect(Vector3 origin, float width, float depth, Color color, bool fill) - { - DebugDraw.SimpleMaterial.SetPass(0); - - Vector3 a = origin; - Vector3 b = origin; - Vector3 c = origin; - Vector3 d = origin; - - b.x += width; - c.x += width; - c.z += depth; - d.z += depth; - - if (fill) - { - GL.Begin(GL.TRIANGLES); - GL.Color(color); - - GL.Vertex(a); - GL.Vertex(b); - GL.Vertex(c); - - GL.Vertex(a); - GL.Vertex(c); - GL.Vertex(d); - - GL.End(); - - color.a *= DarkenFactor; - } - - GL.Begin(GL.LINES); - GL.Color(color); - - GL.Vertex(a); - GL.Vertex(b); - GL.Vertex(b); - GL.Vertex(c); - GL.Vertex(c); - GL.Vertex(d); - GL.Vertex(d); - GL.Vertex(a); - - GL.End(); - } - - /// - /// Draws a simple arc. - /// - /// Endpoint A. - /// Endpoint B. - /// The relative height of the arc. - /// - /// The scale endpoint A arrow head. (Or zero for no head.) - /// - /// - /// The scale of endpoint B arrow head.(Or zero for no head.) - /// - /// The color. - public static void Arc(Vector3 pointA, Vector3 pointB, float height - , float headScaleA, float headScaleB - , Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - AppendArc(pointA, pointB, height, headScaleA, headScaleB); - - GL.End(); - } - - /// - /// Appends a simple arc. - /// - /// Endpoint A. - /// Endpoint B. - /// The relative height of the arc. - /// - /// The scale of the arrow head for point A. (Or zero for no head.) - /// - /// - /// The scale of the arrow head for point B.(Or zero for no head.) - /// - public static void AppendArc(Vector3 pointA, Vector3 pointB, float height - , float headScaleA, float headScaleB) - { - const int ArcPointCount = 8; - const float Pad = 0.05f; - const float ArcPointsScale = (1.0f - Pad *2) / ArcPointCount; - - Vector3 delta = pointB - pointA; - float len = delta.magnitude; - - Vector3 prev = EvalArc(pointA, delta, len*height, Pad); - - for (int i = 1; i <= ArcPointCount; ++i) - { - float u = Pad + i * ArcPointsScale; - - Vector3 pt = EvalArc(pointA, delta, len*height, u); - - GL.Vertex(prev); - GL.Vertex(pt); - - prev = pt; - } - - // End arrows - if (headScaleA > 0.001f) - { - Vector3 p = EvalArc(pointA, delta, len * height, Pad); - Vector3 q = EvalArc(pointA, delta, len * height, Pad + 0.05f); - AppendArrowHead(p, q, headScaleA); - } - - if (headScaleB > 0.001f) - { - Vector3 p = EvalArc(pointA, delta, len * height, 1 - Pad); - Vector3 q = EvalArc(pointA, delta, len * height, 1 - (Pad + 0.05f)); - AppendArrowHead(p, q, headScaleB); - } - } - - private static Vector3 EvalArc(Vector3 point, Vector3 delta, float h, float u) - { - return new Vector3(point.x + delta.x * u - , point.y + delta.y * u + h * (1 - (u * 2 - 1) * (u * 2 - 1)) - , point.z + delta.z * u); - - } - - /// - /// Draw a simple wireframe grid on the xz-plane. - /// - /// The origin of the grid. - /// The grid cell size. [Limit: > 0] - /// The number of cells along the x-axis. - /// The number of cells along the z-axis. - /// The color. - public static void Grid(Vector3 origin, float gridSize, int width, int depth, Color color) - { - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - GL.Color(color); - - for (int x = 0; x < width + 1; x++) - { - Vector3 a = origin; - - a.x += x * gridSize; - GL.Vertex(a); - - a.z += depth * gridSize; - GL.Vertex(a); - } - - for (int z = 0; z < depth + 1; z++) - { - Vector3 a = origin; - - a.z += z * gridSize; - GL.Vertex(a); - - a.x += width * gridSize; - GL.Vertex(a); - } - - GL.End(); - } - } -} diff --git a/critterai/.svn/pristine/8c/8cc494ffa69840dbbdbeb856caf213fa164b9739.svn-base b/critterai/.svn/pristine/8c/8cc494ffa69840dbbdbeb856caf213fa164b9739.svn-base deleted file mode 100644 index 7b1d223c..00000000 --- a/critterai/.svn/pristine/8c/8cc494ffa69840dbbdbeb856caf213fa164b9739.svn-base +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; - -namespace org.critterai.nav -{ - /// - /// Configuration parameters that define steering behaviors for agents managed by a crowd - /// manager. - /// - /// - /// - /// Minimal available documentation. - /// - /// - /// Implemented as a class with public fields in order to support Unity serialization. Care - /// must be taken not to set the fields to invalid values. - /// - /// - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public sealed class CrowdAvoidanceParams - { - - /* - * Source: DetourCrowdAvoidance dtObstacleAvoidanceParams (struct) - * - * Design note: - * - * Class vs Structure - * - * In this case I've decided to go with a class over a structure. - * I expect this data will be mostly set at design time and remain - * static at runtime. So no need to optimize interop calls, and - * support for Unity serialization is more important. - * - * The default values are the same as those in dtCrowd.init(). - * - */ - - /// - /// Velocity bias. - /// - public float velocityBias = 0.4f; - - /// - /// Desired velocity weight. - /// - public float weightDesiredVelocity = 2.0f; - - /// - /// Current velocity weight. - /// - public float weightCurrentVelocity = 0.75f; - - /// - /// Size weight. - /// - public float weightSide = 0.75f; - - /// - /// Weight TOI. - /// - public float weightToi = 2.5f; - - /// - /// Horizontal time. - /// - public float horizontalTime = 2.5f; - - /// - /// Sample grid size. - /// - public byte gridSize = 33; - - /// - /// Adaptive divisions. - /// - public byte adaptiveDivisions = 7; - - /// - /// Adaptive rings. - /// - public byte adaptiveRings = 2; - - /// - /// Adaptive depth. - /// - public byte adaptiveDepth = 5; - - /// - /// Default constructor. - /// - public CrowdAvoidanceParams() { } - - /// - /// Clones the current object. (Usually more appropriate than sharing references.) - /// - /// A clone of the object. - public CrowdAvoidanceParams Clone() - { - CrowdAvoidanceParams result = new CrowdAvoidanceParams(); - result.velocityBias = velocityBias; - result.weightDesiredVelocity = weightDesiredVelocity; - result.weightCurrentVelocity = weightCurrentVelocity; - result.weightSide = weightSide; - result.weightToi = weightToi; - result.horizontalTime = horizontalTime; - result.gridSize = gridSize; - result.adaptiveDivisions = adaptiveDivisions; - result.adaptiveRings = adaptiveRings; - result.adaptiveDepth = adaptiveDepth; - return result; - } - - /// - /// Creates a standard low quality configuration. - /// - /// A high quality configuration. - public static CrowdAvoidanceParams CreateStandardLow() - { - CrowdAvoidanceParams result = new CrowdAvoidanceParams(); - - result.velocityBias = 0.5f; - result.adaptiveDivisions = 5; - result.adaptiveRings = 2; - result.adaptiveDepth = 1; - - return result; - } - - /// - /// Creates a standard medium quality configuration. - /// - /// A high quality configuration. - public static CrowdAvoidanceParams CreateStandardMedium() - { - CrowdAvoidanceParams result = new CrowdAvoidanceParams(); - - result.velocityBias = 0.5f; - result.adaptiveDivisions = 5; - result.adaptiveRings = 2; - result.adaptiveDepth = 2; - - return result; - } - - /// - /// Creates a standard good quality configuration. - /// - /// A high quality configuration. - public static CrowdAvoidanceParams CreateStandardGood() - { - CrowdAvoidanceParams result = new CrowdAvoidanceParams(); - - result.velocityBias = 0.5f; - result.adaptiveDivisions = 7; - result.adaptiveRings = 2; - result.adaptiveDepth = 3; - - return result; - } - - /// - /// Creates a standard high quality configuration. - /// - /// A high quality configuration. - public static CrowdAvoidanceParams CreateStandardHigh() - { - CrowdAvoidanceParams result = new CrowdAvoidanceParams(); - - result.velocityBias = 0.5f; - result.adaptiveDivisions = 7; - result.adaptiveRings = 3; - result.adaptiveDepth = 3; - - return result; - } - } -} diff --git a/critterai/.svn/pristine/8d/8d01de4ea1eae10e6c3b715b6002fb31b999b4b1.svn-base b/critterai/.svn/pristine/8d/8d01de4ea1eae10e6c3b715b6002fb31b999b4b1.svn-base deleted file mode 100644 index 2b90a3ea..00000000 --- a/critterai/.svn/pristine/8d/8d01de4ea1eae10e6c3b715b6002fb31b999b4b1.svn-base +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.geom; -using System.Collections.Generic; -using org.critterai.nmgen; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Builds an object. - /// - public sealed class InputGeometryBuilder - { - private ChunkyTriMeshBuilder mBuilder; - private readonly Vector3 mBoundsMin; - private readonly Vector3 mBoundsMax; - private readonly bool mIsThreadSafe; - private InputGeometry mGeom; - - private InputGeometryBuilder(ChunkyTriMeshBuilder builder - , Vector3 boundsMin - , Vector3 boundsMax - , bool isThreadSafe) - { - mBuilder = builder; - mBoundsMin = boundsMin; - mBoundsMax = boundsMax; - mIsThreadSafe = isThreadSafe; - } - - /// - /// True if the builder is safe to run on its own thread. - /// - public bool IsThreadSafe { get { return mIsThreadSafe; } } - - /// - /// The input geometry created by the builder. (Null until finished.) - /// - public InputGeometry Result { get { return mGeom; } } - - /// - /// True if the builder is finished and the input geometry is avaiable. - /// - public bool IsFinished { get { return mGeom != null; } } - - /// - /// Performs a single build step. - /// - /// - /// - /// This method must be called repeatedly until it resturns false in order - /// to complete the build. (Useful in GUI environments.) - /// - /// - /// - /// True if the build is still underway and another call is required. False - /// if the build is finished. - /// - public bool Build() - { - if (mBuilder == null) - return false; - - if (mBuilder.Build()) - return true; - - mGeom = new InputGeometry(mBuilder.Result, mBoundsMin, mBoundsMax); - mBuilder = null; - - return false; - } - - /// - /// Performs the build in a single step. - /// - public void BuildAll() - { - if (mBuilder == null) - return; - - mBuilder.BuildAll(); - - mGeom = new InputGeometry(mBuilder.Result, mBoundsMin, mBoundsMax); - mBuilder = null; - } - - /// - /// Creates a thread-safe, fully validated builder. - /// - /// - /// - /// The input mesh and area parameters are fully validated. - /// - /// - /// Will return null if there are zero triangles. - /// - /// - /// All triangleswill default to if the - /// parameter is null. - /// - /// - /// If walkable slope if greather than zero then the builder will apply - /// to the areas. - /// - /// - /// The triangle mesh to use for the build. - /// The triangle areas. (Null permitted.) - /// The walkable slope. - /// (See ) - /// A thread-safe, fully validated builder. Or null on error. - public static InputGeometryBuilder Create(TriangleMesh mesh - , byte[] areas - , float walkableSlope) - { - if (!IsValid(mesh, areas)) - return null; - - TriangleMesh lmesh = new TriangleMesh(mesh.vertCount, mesh.triCount); - lmesh.triCount = mesh.triCount; - lmesh.vertCount = mesh.vertCount; - - System.Array.Copy(mesh.verts, 0, lmesh.verts, 0, lmesh.verts.Length); - System.Array.Copy(mesh.tris, 0, lmesh.tris, 0, lmesh.tris.Length); - - byte[] lareas; - if (areas == null) - lareas = NMGen.CreateDefaultAreaBuffer(mesh.triCount); - else - { - lareas = new byte[mesh.triCount]; - System.Array.Copy(areas, 0, lareas, 0, lareas.Length); - } - - return UnsafeCreate(lmesh, lareas, walkableSlope, true); - } - - /// - /// Creates a builder. - /// - /// - /// - /// No validation is performed and the builder will use the parameters directly - /// during the build. - /// - /// - /// Builders created using this method are not guarenteed to produce a usable result. - /// - /// - /// It is the responsibility of the caller to ensure thread safely if - /// is set to true. - /// - /// - /// Warning: If walkable slope if greather than zero then the builder will - /// apply directly to the areas parameter. - /// - /// - /// The triangle mesh to use for the build. - /// The triangle areas. (Null not permitted.) - /// The walkable slope. - /// (See ) - /// True if the builder can run safely on its own thread. - /// A builder, or null on error. - public static InputGeometryBuilder UnsafeCreate(TriangleMesh mesh - , byte[] areas - , float walkableSlope - , bool isThreadSafe) - { - if (mesh == null || areas == null || mesh.triCount < 0) - return null; - - walkableSlope = System.Math.Min(NMGen.MaxAllowedSlope, walkableSlope); - - if (walkableSlope > 0) - { - BuildContext context = new BuildContext(); - if (!NMGen.ClearUnwalkableTriangles(context, mesh, walkableSlope, areas)) - return null; - } - - ChunkyTriMeshBuilder builder = ChunkyTriMeshBuilder.Create(mesh, areas, 32768); - - if (builder == null) - return null; - - Vector3 bmin; - Vector3 bmax; - mesh.GetBounds(out bmin, out bmax); - - return new InputGeometryBuilder(builder, bmin, bmax, isThreadSafe); - } - - /// - /// Validates the mesh and areas. - /// - /// - /// - /// The parameter is validated only if it is non-null. - /// - /// - /// The mesh to validate. - /// The area to validate. (If non-null.) - /// True if the structure and content of the parameters are considered valid. - /// - public static bool IsValid(TriangleMesh mesh, byte[] areas) - { - if (mesh == null || mesh.triCount == 0 || !TriangleMesh.IsValid(mesh, true)) - { - return false; - } - - if (areas != null && (areas.Length != mesh.triCount - || !NMGen.IsValidAreaBuffer(areas, mesh.triCount))) - { - return false; - } - - return true; - } - - } -} diff --git a/critterai/.svn/pristine/8d/8dd27a1d2440f64e1317d4e798aa7c60fbbaf8b7.svn-base b/critterai/.svn/pristine/8d/8dd27a1d2440f64e1317d4e798aa7c60fbbaf8b7.svn-base deleted file mode 100644 index 9835b41a..00000000 --- a/critterai/.svn/pristine/8d/8dd27a1d2440f64e1317d4e798aa7c60fbbaf8b7.svn-base +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.nav.rcn -{ - internal static class NavmeshQueryFilterEx - { - /* - * Design note: In order to stay compatible with Unity iOS, all - * extern methods must be unique and match DLL entry point. - * (Can't use EntryPoint.) - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr dtqfAlloc(); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtqfFree(IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtqfSetAreaCost(IntPtr filter - , int index - , float cost); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern float dtqfGetAreaCost(IntPtr filter - , int index); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtqfSetIncludeFlags(IntPtr filter - , ushort flags); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern ushort dtqfGetIncludeFlags(IntPtr filter); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void dtqfSetExcludeFlags(IntPtr filter - , ushort flags); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern ushort dtqfGetExcludeFlags(IntPtr filter); - } -} diff --git a/critterai/.svn/pristine/8d/8de658f0aa9ae63a639569481b2997f9e6a8faa6.svn-base b/critterai/.svn/pristine/8d/8de658f0aa9ae63a639569481b2997f9e6a8faa6.svn-base deleted file mode 100644 index 59d8e97a..00000000 --- a/critterai/.svn/pristine/8d/8de658f0aa9ae63a639569481b2997f9e6a8faa6.svn-base +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Provides core data for agents managed by a object. - /// - /// - /// - /// This structure is useful for marshalling information from the - /// back to the actual agent implementation. - /// - /// - [StructLayout(LayoutKind.Sequential)] - internal struct CrowdAgentCoreState - { - /* - * Design notes: - * - * This is a structure because it must be passed - * in an array during interop. - * - * Duplicate of: rcnCrowdAgentCoreData - */ - - /// - /// The state of the agent. - /// - public CrowdAgentState state; - - /// - /// The reference of the polygon that contains the position. - /// - public uint positionPoly; - - /// - /// The reference of the polygon that contains the target. - /// - public uint targetPoly; - - /// - /// The reference of the polygon the contains the next corner. - /// (Or zero if the next corner is the target.) - /// - public uint nextCornerPoly; - - /// - /// The number of neighbors. - /// - public int neighborCount; - - /// - /// The desired speed of the agent. - /// - public float desiredSpeed; - - /// - /// The position of the agent. - /// - public Vector3 position; - - /// - /// disp-value. (Not documented.) - /// - private Vector3 disp; - - /// - /// The desired velocity of the agent. - /// - public Vector3 desiredVelocity; - - /// - /// nvel-value. (Not documented.) - /// - private Vector3 nvel; - - /// - /// The velocity of the agent. - /// - public Vector3 velocity; - - /// - /// The target of the agent. - /// - /// - /// - /// This is the same as the corridor target. - /// - /// - public Vector3 target; - - /// - /// The next corner in the path corridor. - /// - public Vector3 nextCorner; - } -} diff --git a/critterai/.svn/pristine/8e/8ebe9dae82d5549759ddde1e6de87736eb663676.svn-base b/critterai/.svn/pristine/8e/8ebe9dae82d5549759ddde1e6de87736eb663676.svn-base deleted file mode 100644 index cbb01bba..00000000 --- a/critterai/.svn/pristine/8e/8ebe9dae82d5549759ddde1e6de87736eb663676.svn-base +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Tile configuration parameters. - /// - /// - /// - /// These values are derived during the build process. - /// - /// - /// Implemented as a class with public fields in order to support Unity serialization. Care - /// must be taken not to set the fields to invalid values. - /// - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class NMGenTileParams - { - /// - /// The x-index of the tile. - /// - public int tileX; - - /// - /// The z-index of the tile. - /// - public int tileZ; - - /// - /// The minimum bounds of the tile. - /// - public Vector3 boundsMin; - - /// - /// The maximum bounds of the tile. - /// - public Vector3 boundsMax; - - /// - /// The z-index of the tile within the tile grid. [Limit: >= 0] - /// - /// - /// - /// This value is a zero based tile index representing the position of the tile along the - /// depth of the tile grid. - /// - /// - /// The value is auto-clamped to a valid value. - /// - /// - public int TileZ - { - get { return tileZ; } - set { tileZ = Math.Max(0, value); } - } - - /// - /// The x-index of the tile within the tile grid. [Limit: >= 0] - /// - /// - /// - /// This value is a zero based tile index representing the position of the tile along the - /// width of the tile grid. - /// - /// - /// The value is auto-clamped to a valid value. - /// - /// - public int TileX - { - get { return tileX; } - set { tileX = Math.Max(0, value); } - } - - /// - /// The minimum bounds of the tile's AABB. [Units: World] - /// - public Vector3 BoundsMin - { - get { return boundsMin; } - set { boundsMin = value; } - } - - /// - /// The maximum bounds of the tile's AABB. [Units: World] - /// - public Vector3 BoundsMax - { - get { return boundsMax; } - set { boundsMax = value; } - } - - /// - /// Constructor. - /// - /// The x-index of the tile within the tile grid. [Limit: >= 0] - /// The z-index of the tile within the tile grid. [Limit: >= 0] - /// The minimum bounds of the tile. - /// The maximum bounds of the tile. - public NMGenTileParams(int tx, int tz, Vector3 boundsMin, Vector3 boundsMax) - { - // Note: Use properties for auto-clamping. - TileX = tx; - TileZ = tz; - BoundsMin = boundsMin; - BoundsMax = boundsMax; - } - } -} diff --git a/critterai/.svn/pristine/8f/8fde802b5731dc3c66becb53e0fbd12713e0e3ee.svn-base b/critterai/.svn/pristine/8f/8fde802b5731dc3c66becb53e0fbd12713e0e3ee.svn-base deleted file mode 100644 index 551a00a5..00000000 Binary files a/critterai/.svn/pristine/8f/8fde802b5731dc3c66becb53e0fbd12713e0e3ee.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/8f/8ffa582c1651f1eb658fbbee74fc6e5b9f47e944.svn-base b/critterai/.svn/pristine/8f/8ffa582c1651f1eb658fbbee74fc6e5b9f47e944.svn-base deleted file mode 100644 index 52335d57..00000000 --- a/critterai/.svn/pristine/8f/8ffa582c1651f1eb658fbbee74fc6e5b9f47e944.svn-base +++ /dev/null @@ -1,716 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Removes and merges small regions within a height field. - *

      Applies two algorithms:

      - *
        - *
      • Searches for island regions (regions only connected to the null region) - * and removes the ones that are smaller than the chosen threshold.
      • - *
      • If a region is below a threshold size, attempts to merge the region - * into the most appropriate larger neighbor region.
      • - *
      - * - * - * @see Region Generation - */ -public final class FilterOutSmallRegions - implements IOpenHeightFieldAlgorithm -{ - - /* - * Recast Reference: filerSmallRegions() in RecastRegion.cpp - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private final int mMinUnconnectedRegionSize; - private final int mMergeRegionSize; - - /** - * Constructor - * @param minUnconnectedRegionSize The minimum region size for - * unconnected (island) regions. (Voxels) - *

      Any generated regions that are not connected to any other region - * and are smaller than this size will be culled before final navmesh - * generation. I.e. No longer considered traversable.

      - *

      Constraints: > 0

      - * - * @param mergeRegionSize Any regions smaller than this size will, - * if possible, be merged with larger regions. (Voxels) - *

      Helps reduce the number of unnecessarily small regions that can - * be formed. This is especially an issue in diagonal path regions - * where inherent faults in the region generation algorithm can result in - * unnecessarily small regions.

      - *

      If a region cannot be legally merged with a neighbor region, then - * it will be left alone.

      - *

      Constraints: >= 0

      - * - * @see Detailed parameter information. - */ - public FilterOutSmallRegions(int minUnconnectedRegionSize - , int mergeRegionSize) - { - mMinUnconnectedRegionSize = Math.max(1, minUnconnectedRegionSize); - mMergeRegionSize = Math.max(0, mergeRegionSize); - } - - /** - * {@inheritDoc} - *

      The height field must contain valid region information in order - * for this algorithm to be effective.

      - */ - @Override - public void apply(OpenHeightfield field) - { - - if (field.regionCount() < 2) - // No spans or all spans are in the null region. - return; - - /* - * Over the life of the region array, the ids of region objects - * contained within the array may be changed as follows: - * - To the null region. This indicates the region has been - * abandoned. All spans assigned to it will be merged into - * the null region. - * - To another region id. This indicates that the spans - * assigned to the region will be re-assigned to the new - * region. (This occurs when region merging occurs.) - * So the index of the array indicates the original region id. The - * region objects within the array contain the current target - * region id. - */ - final Region[] regions = new Region[field.regionCount()]; - - for (int i = 0; i < field.regionCount(); i++) - { - regions[i] = new Region(i); - } - - final OpenHeightFieldIterator iter = field.dataIterator(); - - /* - * Region object initialization. - * For all non-null regions: - * - Tally the number of spans that belong to the region. - * - Record connections to other regions. (Including connections - * to the null region.) - * - Record regions that lie above (overlap) the region. - * (Only non-null regions.) - */ - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - - if (span.regionID() <= NULL_REGION) - // Span is in the null region. So skip it. - continue; - - // Get current span's region object and increment its membership - // count. - Region region = regions[span.regionID()]; - region.spanCount++; - - // Step up the list of spans above the current span. - for (OpenHeightSpan nextHigherSpan = span.next() - ; nextHigherSpan != null - ; nextHigherSpan = nextHigherSpan.next()) - { - if (nextHigherSpan.regionID() <= NULL_REGION) - // Span is in the null region. So ignore it. - continue; - if (!region.overlappingRegions.contains( - nextHigherSpan.regionID())) - // This is a previously undetected region above the - // current region. - region.overlappingRegions.add(nextHigherSpan.regionID()); - } - - if (region.connections.size() > 0) - // Have already found the connections for this span's region. - // So move to the next span. - continue; - - // Is this span on the edge of the its region? - int edgeDirection = getRegionEdgeDirection(span); - if (edgeDirection != -1) - // This is the first span detected that lies on the edge of - // its region. Can generate this region's the connection - // information. - findRegionConnections(span, edgeDirection, region.connections); - } - - /* - * Region information has been gathered. - * - * Find unconnected (island) regions that are below the allowed - * minimum size and convert them to null regions. - * - * This will result in all spans assigned to these regions being - * re-assigned to the null region. - * - * Starting at region 1 since zero is the null region. - */ - for (int regionID = 1; regionID < field.regionCount(); regionID++) - { - Region region = regions[regionID]; - if (region.spanCount == 0) - // Skip empty regions. - continue; - if (region.connections.size() == 1 - && region.connections.get(NULL_REGION) == NULL_REGION) - { - // This region is only connected to the null region. - // (It is an island region.) - if (region.spanCount < mMinUnconnectedRegionSize) - { - // This region is too small to be allowed as an - // island region. Make it a null region. - region.resetWithID(0); - } - } - } - - /* - * Search for small regions to merge with other regions. - * - * This is accomplished by searching for regions that are allowed to - * be merged with other regions, then searching through the region's - * connections for regions to be merged with. - * - * A region only looks for a single other region to merge with - * during each iteration of the loop. The loop will continue until - * no successful merges are detected. - * - * At the end of this process, regions that have been merged into - * other regions will have had their IDs replaced by the region's - * they were merged into. - * - * Example: - * - * Region 11 is at array index 11. It is merged with region 18 - * at index 18. After the merge, the region OBJECT at index 11 - * and will have an id of 18. - */ - int mergeCount; - do - { - mergeCount = 0; - // Loop through all regions. - for (Region region : regions) - { - if (region.id <= NULL_REGION || region.spanCount == 0) - // Skip null and empty regions. - continue; - - if (region.spanCount > mMergeRegionSize) - // Region is not a candidate for being merged into - // another region. - continue; - - // Region is either a small region, or a large region - // not connected to a null region. - // Find its smallest neighbor region. - Region targetMergeRegion = null; - int smallestSizeFound = Integer.MAX_VALUE; - // Loop through all region's neighbor (connections). - for (Integer nRegionID : region.connections) - { - if (nRegionID <= 0) - // This neighbor is the null region. So skip it. - continue; - final Region nRegion = regions[nRegionID]; - if (nRegion.spanCount < smallestSizeFound - && canMerge(region, nRegion)) - { - // This neighbor region is the smallest merge-able - // region found so far. - targetMergeRegion = nRegion; - smallestSizeFound = nRegion.spanCount; - } - } - // If a target was found, try to merge. - if (targetMergeRegion != null - && mergeRegions(targetMergeRegion, region)) - { - // A successful merge took place. - // Discard the old region and replace it with the region - // it was merged into. - final int oldRegionID = region.id; - region.resetWithID(targetMergeRegion.id); - // Update region ID in all regions which reference the - // discarded region. - for (Region r : regions) - { - if (r.id <= 0) - // Ignore null region. - continue; - if (r.id == oldRegionID) - // This region was merged into the old - // outdated region. Re-point its id to the new - // target region. - r.id = targetMergeRegion.id; - else - // Fix connection and overlap information. - replaceNeighborRegionID(r - , oldRegionID - , targetMergeRegion.id); - - } - mergeCount++; - } - } - // Continue looping as long as there were merges in the last iteration. - } while (mergeCount > 0); - - /* - * At this point the region ids may no longer be sequential. - * This next section re-maps the region ids so they are again - * sequential. - * - * Flag regions that need to be considered for id re-mapping. - * This flagging is necessary since multiple regions may be sharing - * the same id. Only want to consider a single id for mapping at - * a time. - */ - for (Region region : regions) - { - if (region.id > 0) - // This is not a null region. So it needs to be considered - // for remapping. - region.remap = true; - } - - // Next variable will be incremented to 1 the first iteration - // of the loop. - int currRegionID = 0; - for (Region region : regions) - { - if (!region.remap) - // Region already considered for re-mapping. - continue; - // Will re-assign all regions that use the current region ID to - // the next available sequential region ID. - currRegionID++; - final int oldID = region.id; - // Search all regions for ones using the old region ID. - for (Region r : regions) - { - if (r.id == oldID) - { - // This region uses the old ID. - // Re-assign it to the new ID. - r.id = currRegionID; - r.remap = false; // Don't consider this region again. - } - } - } - // Update the number of regions in the field. - // Add one to account for null region. - field.setRegionCount(currRegionID+1); - - // Finally, update the span region ID's to their final values. - iter.reset(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - if (span.regionID() == 0) - // Leave null regions alone. - continue; - else - // Re-map by getting the region object at the old index - // and assigning its current region id to the span. - span.setRegionID(regions[span.regionID()].id); - } - - } - - /** - * Determines if two regions can be legally merged. - *

      Regions cannot be merged if:

      - *
        - *
      • They do not connect.
      • - *
      • They connect at more than one point.
      • - *
      • They overlap vertically.
      • - *
      - *

      Behavior is undefined if either region is a null region.

      - * @param regionA A region connected with regionB. - * @param regionB A region connected with regionA. - * @return TRUE if the two regions can be merged. Otherwise FALSE. - */ - private static boolean canMerge(Region regionA, Region regionB) - { - // Only checking connections from A to B since checking B to A would - // be redundant. - int connectionsAB = 0; - for (Integer connectionID : regionA.connections) - { - if (connectionID == regionB.id) - // Connection detected. - connectionsAB++; - } - if (connectionsAB != 1) - /* - * Either the regions are not connected or there is a connection - * in more than one location. So a valid simple polygon can't - * be formed if the regions are merged. - */ - return false; - - // Can't merge regions that overlap vertically. - // This check needs to be checked in both directions due to the way - // the data is built. - if (regionA.overlappingRegions.contains(regionB.id)) - // Region B overlaps region A. Can't merge. - return false; - if (regionB.overlappingRegions.contains(regionA.id)) - // Region A overlaps region B. Can't merge. - return false; - - // OK to merge. - return true; - } - - /** - * Walks the edge of a region adding all neighbor region connections to - * a connection array. - *

      WARNING: Only run this operation on spans that are already known - * to be on a region edge. The direction must also be pointing to - * a valid edge.

      - * @param startSpan A span that is known to be on the edge of a region. - * @param startDirection The direction of the edge of the span that is - * known to point across the region edge. - * @param outConnections A reference to the region's connection object. - * This object will be filled with connection data. - */ - private static void findRegionConnections(OpenHeightSpan startSpan - , int startDirection - , ArrayList outConnections) - { - - /* - * Traversing the contour: A good way to visualize it is to think - * of a robot sitting on the floor facing a known wall. It then - * does the following to skirt the wall: - * 1. If there is a wall in front of it, turn clockwise in 90 degrees - * increments until it finds the wall is gone. - * 2. Move forward one step. - * 3. Turn counter-clockwise by 90 degrees. - * 4. Repeat from step 1 until it finds itself at its original - * location facing its original direction. - * - * See also: http://www.critterai.org/nmgen_contourgen#robotwalk - */ - - OpenHeightSpan span = startSpan; - int dir = startDirection; - // Default in case no neighbor exists. - int lastEdgeRegionID = NULL_REGION; - - // Add the first known connection. - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null) - // Found a neighbor in this direction. Use it's region ID. - lastEdgeRegionID = nSpan.regionID(); - // Add the first region ID to the list. - outConnections.add(lastEdgeRegionID); - - int loopCount = 0; - /* - * The loop limit is arbitrary. It exists only to guarantee that bad - * input data doesn't result in an infinite loop. The only down side - * of this loop limit is that it limits the number of detectable - * region connections. (The longer the region edge and the higher - * the number of "turns" in a region's edge, the less connections - * can be detected for that region.) - */ - while (++loopCount < 65534) - { - - // NOTE: The design of this loop is such that the span variable - // will always reference a span from the same region as the - // start span. - - nSpan = span.getNeighbor(dir); - // Default in case no neighbor exists. - int currEdgeRegionID = NULL_REGION; - if (nSpan == null || nSpan.regionID() != span.regionID()) - { - // The current direction points across a region edge. - if (nSpan != null) - // There is a span in this direciton. Get its region ID. - currEdgeRegionID = nSpan.regionID(); - if (currEdgeRegionID != lastEdgeRegionID) - { - // The region across this edge is different from - // the last edge region detected. (Is a transition to a - // new region connection.) Add it to the list. - outConnections.add(currEdgeRegionID); - lastEdgeRegionID = currEdgeRegionID; - } - - dir = (dir+1) & 0x3; // Rotate in clockwise direction. - - } - else - { - /* - * The current direction points to a neighbor in the same - * region as the current span. (And therefore in the same - * region as the start span.) - * Move to the neighbor and swing the search direction back - * one increment (counterclockwise). By moving the direction - * back one increment we guarantee we don't miss any edges. - */ - span = nSpan; - dir = (dir+3) & 0x3; // Rotate counterclockwise direction. - } - - if (startSpan == span && startDirection == dir) - // Have returned to the original span and direction. - // The search is complete. - break; - } - - // Make sure the first and last regions are not the same. This is - // the only type of connection adjacency that has the possibility - // of existing. - if (outConnections.size() > 1 - && outConnections.get(0) - .equals(outConnections.get(outConnections.size() - 1))) - // The fist and last connection is the same. - // Remove the last connection. - outConnections.remove(outConnections.size() - 1); - - } - - /** - * Checks to see if a span is on a region edge. If so, returns the - * direction of the neighbor region. - *

      This is an axis-neighbor search. Diagonal neighbors are not - * considered.

      - *

      The direction of the first detected neighbor region is - * returned.

      - * @param span The span to check. - * @return The direction of span edge that lies along a neighbor region, - * or -1 if the span is not on a region edge. - */ - private static int getRegionEdgeDirection(OpenHeightSpan span) - { - // Search axis-neighbors. - for (int dir = 0; dir < 4; ++dir) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null || nSpan.regionID() != span.regionID()) - // Doesn't have a neighbor or its neighbor is in a - // different region. - return dir; - } - // All neighbors are in the same region. - return -1; - } - - - /** - * Merges the candidate region into the target region. - *

      Only the target region is updated. The candidate is not altered. - * So if the candidate is to be discarded, it should be cleaned up after - * this operation successfully completes.

      - *

      IMPORTANT: The provided regions should already have been checked - * to ensure they are valid for merging. E.g. Using - * {@link #canMerge(Region, Region)}. Otherwise, behavior will be undefined. - * The only time this operation will detect a failure and abort - * (return false) is if the failure check is inherent to the merge - * process.

      - * @param target The region to merge the candidate into. - * @param candidate The region to merge into the target. - * @return TRUE if the spans in the candidate region were successfully - * added to the target region. - */ - private static boolean mergeRegions(Region target, Region candidate) - { - - // Get connection indices for target and candidate. - // (Where the two regions connect.) - final int connectionPointOnTarget = - target.connections.indexOf(candidate.id); - if (connectionPointOnTarget == -1) - // The target knows of no connection between the regions. - return false; - final int connectionPointOnCandidate = - candidate.connections.indexOf(target.id); - if (connectionPointOnCandidate == -1) - // The candidate knows of no connection between the regions. - return false; - - // Merging candidate into target. So need to save original target - // connections prior to the rebuilding them. - final ArrayList targetConns = - new ArrayList(target.connections); - - /* - * Merge connection information. - * - * Step 1: Rebuild the target connections. - * - * Start from the point just past where the candidate connection - * exists and loop back until just before the candidate connection. - * Scenario: - * Original target connections are 0, 2, 3, 4, 5 - * Merging with region 2. - * Then: - * Rebuild starting at index 2 and stop building at - * index 0 to get: 3, 4, 5, 0. - */ - target.connections.clear(); - int workingSize = targetConns.size(); - for (int i = 0; i < workingSize - 1; i++) - { - // The modulus calculation is what results in the wrapping. - target.connections.add(targetConns.get( - (connectionPointOnTarget + 1 + i) % workingSize)); - } - /* - * Step 2: Insert candidate connections into target connections at - * their mutual connection point. - * - * Same extraction process as for step one, but inserting data - * into target connection data. - * - * Scenario: - * Target connections after step 1 are 3, 4, 5, 0 - * Candidate connections are 3, 1, 0 - * Target region id is 1. - * Then: - * The loop will insert 0, 3 from the candidate at the end of - * the target connections. - * The final target connections: 3, 4, 5, 0, 0, 3 - * Note that this process can result in adjacent duplicate - * connections which will be fixed later. - */ - workingSize = candidate.connections.size(); - for (int i = 0; i < workingSize - 1; i++) - { - target.connections.add(candidate.connections.get( - (connectionPointOnCandidate + 1 + i) % workingSize)); - } - /* - * Step 3: Get rid of any adjacent duplicate connections that may - * have been created. - */ - removeAdjacentDuplicateConnections(target); - - // Add overlap data from the candidate to the target. - for (Integer i : candidate.overlappingRegions) - { - if (!target.overlappingRegions.contains(i)) - // This is a new overlap. Add it to the target. - target.overlappingRegions.add(i); - } - - // Merge span counts. - target.spanCount += candidate.spanCount; - - return true; - - } - - /** - * If a regions connection list contains adjacent duplicate connections, - * this operation removes them. Example of a cleanup: - * 3, 4, 5, 0, 0, 3 -> 4, 5, 0, 3 - * @param region The region to cleanup. - */ - private static void removeAdjacentDuplicateConnections(Region region) - { - int iConnection = 0; - // Loop through all adjacent connections. - while (iConnection < region.connections.size() - && region.connections.size() > 1) - { - int iNextConnection = iConnection+1; - if (iNextConnection >= region.connections.size()) - // Need to loop back to zero. - iNextConnection = 0; - if (region.connections.get(iConnection) - .equals(region.connections.get(iNextConnection))) - { - // Found duplicate. - // Remove duplicate and stay at current index. - region.connections.remove(iNextConnection); - } - else - // Move to next connection. - iConnection++; - } - } - - /** - * Searches through a region's connection and overlap information - * for any references to an old region ID and replaces with the new ID. - * @param region The region to perform the search and replace on. - * @param oldID The old region ID to replace. - * @param newID The ID to replace the old ID with. - */ - private static void replaceNeighborRegionID(Region region - , int oldID - , int newID) - { - boolean connectionsChanged = false; - // Perform the search and replace on the region connections. - for (int i = 0; i < region.connections.size(); i++) - { - if (region.connections.get(i) == oldID) - { - // Found a match. Replace it. - region.connections.set(i, newID); - connectionsChanged = true; - } - } - // Perform a search and replace on the overlap regions. - for (int i = 0; i < region.overlappingRegions.size(); i++) - { - if (region.overlappingRegions.get(i) == oldID) - // Found a match. Replace it. - region.overlappingRegions.set(i, newID); - } - if (connectionsChanged) - // Connections changed. This might have resulted in - // two connections being merged into one. Search for and - // fix as needed. - removeAdjacentDuplicateConnections(region); - } - -} diff --git a/critterai/.svn/pristine/90/90ce3386ce16d132a0a9923c2f131f8144964ecd.svn-base b/critterai/.svn/pristine/90/90ce3386ce16d132a0a9923c2f131f8144964ecd.svn-base deleted file mode 100644 index 3d1da54e..00000000 --- a/critterai/.svn/pristine/90/90ce3386ce16d132a0a9923c2f131f8144964ecd.svn-base +++ /dev/null @@ -1,36 +0,0 @@ ->>>>>> NMGen-0.2.0 <<<<<< - -Includes breaking API changes. - -Improved robustness when dealing with extreme configuration settings. -(Including bug fixes and changes to algorithms.) - -Improved robustness when dealing with outdoor/uneven terrain. -(Including bug fixes and changes to algorithms.) - -Resolved issue 4: Contour Generation Fails Due to Unexpected Internal Null -Region - -Resolved issue 5: Seams Form Between Triangles within a Region - -The smoothingThreshold parameter is now restricted to 0 <= value <= 4. - -The maxTraversableSlope parameter is now restricted to 0 <= value <= 85. - -Merged LogResults functionality into the IntermediateData class. - -New class: CleanNullRegionBorders - -Merged the functionality from the CleanNullRegionCorners class into the -cleanNullRegionBorders class. - -Retired the BaseHeightfield class. - -Retired the IHeightfieldIterator interface. - -General code reformatting: Cleaned white space, sorted class members, -reformatted all files to 80 character width. - ->>>>>> NMGen-0.1.2 <<<<<< - -Initial full release. \ No newline at end of file diff --git a/critterai/.svn/pristine/91/918ccf6c0b22f77161e2d38c2f25448a20e6d8ca.svn-base b/critterai/.svn/pristine/91/918ccf6c0b22f77161e2d38c2f25448a20e6d8ca.svn-base deleted file mode 100644 index 0fa7d7e5..00000000 Binary files a/critterai/.svn/pristine/91/918ccf6c0b22f77161e2d38c2f25448a20e6d8ca.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/92/92296d2ef487124b646cf0d644d0152d67603f61.svn-base b/critterai/.svn/pristine/92/92296d2ef487124b646cf0d644d0152d67603f61.svn-base deleted file mode 100644 index f2903c6e..00000000 --- a/critterai/.svn/pristine/92/92296d2ef487124b646cf0d644d0152d67603f61.svn-base +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.u3d; - -/// -/// Provides data useful for marking an area using a box shaped convex polygon. -/// -/// -/// -/// The data is in a format compatible with the CompactHeightfield.MarkConvexPolyArea() method. -/// -/// -/// The box is projected onto the xz-plane. Y-axis rotation will behave as expected. -/// Compining non-zero x- and z-rotations will skew the box into a parallelogram shape. -/// -/// -[ExecuteInEditMode] -public sealed class BoxAreaMarker - : NMGenAreaMarker -{ - /// - /// Convex marker data. - /// - public struct MarkerData - { - /// - /// The convex polygon vertices. [Length: 4] - /// - public Vector3[] verts; - - /// - /// The world y-maximum. - /// - public float ymin; - - /// - /// The world y-minimum. - /// - public float ymax; - - /// - /// The area to apply. - /// - public byte area; - - /// - /// The priority of the marker. - /// - public int priority; - } - - /// - /// Gets the marker data. - /// - /// The marker data. - public MarkerData GetMarkerData() - { - Transform trans = transform; - Vector3 pos = trans.position; - Vector3 scale = trans.localScale; - - Vector3 fwd = trans.forward * scale.z; - Vector3 right = trans.right * scale.x; - - Vector3[] verts = new Vector3[4]; - verts[0] = pos + fwd + right; - verts[1] = pos + fwd - right; - verts[2] = pos - fwd - right; - verts[3] = pos - fwd + right; - - MarkerData result = new MarkerData(); - - result.verts = verts; - result.ymin = pos.y -trans.localScale.y; - result.ymax = pos.y + trans.localScale.y; - result.area = Area; - result.priority = Priority; - - return result; - } - - void OnRenderObject() - { - if (!debugEnabled && !debugEnabledLocal) - return; - - // The color for area zero is hard to see. So using black. - Color color = (Area == 0 ? new Color(0, 0, 0, 0.8f) : ColorUtil.IntToColor(Area, 0.8f)); - - Transform trans = transform; - Vector3 pos = trans.position; - Vector3 scale = trans.localScale; - - Vector3 fwd = trans.forward * scale.z; - Vector3 right = trans.right * scale.x; - Vector3 up = Vector3.up * scale.y; - - Vector3 a = pos + fwd + right; - Vector3 b = pos + fwd - right; - Vector3 c = pos - fwd - right; - Vector3 d = pos - fwd + right; - - // Flatten. - a.y = pos.y - up.y; - b.y = pos.y - up.y; - c.y = pos.y - up.y; - d.y = pos.y - up.y; - - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - - GL.Color(color); - - GL.Vertex(a); - GL.Vertex(b); - GL.Vertex(b); - GL.Vertex(c); - GL.Vertex(c); - GL.Vertex(d); - GL.Vertex(d); - GL.Vertex(a); - - GL.Vertex(a + up * 2); - GL.Vertex(b + up * 2); - GL.Vertex(b + up * 2); - GL.Vertex(c + up * 2); - GL.Vertex(c + up * 2); - GL.Vertex(d + up * 2); - GL.Vertex(d + up * 2); - GL.Vertex(a + up * 2); - - GL.Vertex(a); - GL.Vertex(a + up * 2); - GL.Vertex(b); - GL.Vertex(b + up * 2); - GL.Vertex(c); - GL.Vertex(c + up * 2); - GL.Vertex(d); - GL.Vertex(d + up * 2); - - GL.End(); - } -} diff --git a/critterai/.svn/pristine/95/953c63514c4ef27158f7a9c6f52d77c47658d428.svn-base b/critterai/.svn/pristine/95/953c63514c4ef27158f7a9c6f52d77c47658d428.svn-base deleted file mode 100644 index af822c4a..00000000 --- a/critterai/.svn/pristine/95/953c63514c4ef27158f7a9c6f52d77c47658d428.svn-base +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURSTATUS_H -#define DETOURSTATUS_H - -typedef unsigned int dtStatus; - -// High level status. -static const unsigned int DT_FAILURE = 1u << 31; // Operation failed. -static const unsigned int DT_SUCCESS = 1u << 30; // Operation succeed. -static const unsigned int DT_IN_PROGRESS = 1u << 29; // Operation still in progress. - -// Detail information for status. -static const unsigned int DT_STATUS_DETAIL_MASK = 0x0ffffff; -static const unsigned int DT_WRONG_MAGIC = 1 << 0; // Input data is not recognized. -static const unsigned int DT_WRONG_VERSION = 1 << 1; // Input data is in wrong version. -static const unsigned int DT_OUT_OF_MEMORY = 1 << 2; // Operation ran out of memory. -static const unsigned int DT_INVALID_PARAM = 1 << 3; // An input parameter was invalid. -static const unsigned int DT_BUFFER_TOO_SMALL = 1 << 4; // Result buffer for the query was too small to store all results. -static const unsigned int DT_OUT_OF_NODES = 1 << 5; // Query ran out of nodes during search. -static const unsigned int DT_PARTIAL_RESULT = 1 << 6; // Query did not reach the end location, returning best guess. - - -// Returns true of status is success. -inline bool dtStatusSucceed(dtStatus status) -{ - return (status & DT_SUCCESS) != 0; -} - -// Returns true of status is failure. -inline bool dtStatusFailed(dtStatus status) -{ - return (status & DT_FAILURE) != 0; -} - -// Returns true of status is in progress. -inline bool dtStatusInProgress(dtStatus status) -{ - return (status & DT_IN_PROGRESS) != 0; -} - -// Returns true if specific detail is set. -inline bool dtStatusDetail(dtStatus status, unsigned int detail) -{ - return (status & detail) != 0; -} - -#endif // DETOURSTATUS_H diff --git a/critterai/.svn/pristine/95/95bc6ca60a2ef8c0e6d31d14ef8740577933975e.svn-base b/critterai/.svn/pristine/95/95bc6ca60a2ef8c0e6d31d14ef8740577933975e.svn-base deleted file mode 100644 index a330f1f3..00000000 --- a/critterai/.svn/pristine/95/95bc6ca60a2ef8c0e6d31d14ef8740577933975e.svn-base +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Represents data for a object. - /// - /// - /// - /// Warning: The serializable attributewill be removed in v0.5. Use - /// instead of serializing this object. - /// - /// - /// The detail mesh is made up of triangle sub-meshes which provide extra height detail for - /// each polygon in its assoicated polygon mesh. - /// - /// - /// See the individual field definitions for details related to the structure of the mesh. - /// - /// - /// Implemented as a class with public fields in order to support Unity serialization. Care - /// must be taken not to set the fields to invalid values. - /// - /// - /// - [Serializable] - public sealed class PolyMeshDetailData - { - /// - /// The sub-mesh data. - /// [(baseVertIndex, vertCount, baseTriIndex, triCount) * meshCount] - /// [Size: >= 4 * meshCount] - /// - /// - /// - /// Maximum number of vertices per sub-mesh: 127
      - /// Maximum number of triangles per sub-mesh: 255 - ///
      - ///
      - /// - /// - /// An example of iterating the triangles in a sub-mesh. - /// - /// - /// // Where iMesh is the index for the sub-mesh within detailMesh - /// int pMesh = iMesh * 4; - /// int pVertBase = meshes[pMesh + 0] * 3; - /// int pTriBase = meshes[pMesh + 2] * 4; - /// int tCount = meshes[pMesh + 3]; - /// int vertX, vertY, vertZ; - /// - /// for (int iTri = 0; iTri < tCount; iTri++) - /// { - /// for (int iVert = 0; iVert < 3; iVert++) - /// { - /// int pVert = pVertBase - /// + (tris[pTriBase + (iTri * 4 + iVert)] * 3); - /// vertX = verts[pVert + 0]; - /// vertY = verts[pVert + 1]; - /// vertZ = verts[pVert + 2]; - /// // Do something with the vertex. - /// } - /// } - /// - /// - public uint[] meshes; - - /// - /// The mesh vertices. - /// [Length: >= vertCount] - /// - /// - /// - /// The vertices are grouped by sub-mesh and will contain duplicates since each sub-mesh is independently defined. - /// - /// - /// The first group of vertices for each sub-mesh are in the same rder as the vertices for - /// the sub-mesh's associated polygon. These vertices are followed - /// by any additional detail vertices. So it the associated polygon has 5 vertices, the - /// sub-mesh will have a minimum of 5 vertices and the first 5 vertices will be equivalent - /// to the 5 polygon vertices. - /// - /// - public Vector3[] verts; - - /// - /// The mesh triangles. - /// [vertIndexA, vertIndexB, vertIndexC, flag) * triCount] - /// [Size: >= 4 * triCount] - /// - /// - /// - /// The triangles are grouped by sub-mesh. - /// - /// - /// Vertices - /// - /// - /// The vertex indices in the triangle array are local to the sub-mesh, not global. To - /// translate into an global index in the vertices array, the values must be offset by - /// the sub-mesh's base vertex index. - /// - /// - /// Example: If the baseVertexIndex for the sub-mesh is 5 and the triangle entry - /// is (4, 8, 7, 0), then the actual indices for the vertices are - /// (4 + 5, 8 + 5, 7 + 5). - /// - /// - /// Flags - /// - /// - /// The flags entry indicates which edges are internal and which are external to the - /// sub-mesh. - /// - /// - /// Internal edges connect to other triangles within the same sub-mesh. - /// External edges represent portals to other sub-meshes or the null region. - /// - /// - /// Each flag is stored in a 2-bit position. Where position 0 is the lowest 2-bits and - /// position 4 is the highest 2-bits: - /// - /// - /// Position 0: Edge AB (>> 0)
      - /// Position 1: Edge BC (>> 2)
      - /// Position 2: Edge CA (>> 4)
      - /// Position 4: Unused - ///
      - /// - /// Testing can be performed as follows: - /// - /// - /// if (((flag >> 2) & 0x3) == 0) - /// { - /// // Edge BC is an external edge. - /// } - /// - ///
      - public byte[] tris; - - /// - /// The sub-mesh count. [Limit: > 0] - /// - public int meshCount; - - /// - /// The vertex count. [Limit: >= 3] - /// - public int vertCount; - - /// - /// The triangle count. [Limit > 0] - /// - public int triCount; - - /// - /// Constructor. - /// - /// - /// The maximum vertices the vertex buffer will hold. [Limit: >= 3] - /// - /// - /// The maximum triangles the triangle buffer will hold. [Limit: > 0] - /// - /// - /// The maximum sub-meshes the mesh buffer will hold. [Limit: > 0] - /// - public PolyMeshDetailData(int maxVerts - , int maxTris - , int maxMeshes) - { - if (maxVerts < 3 - || maxTris < 1 - || maxMeshes < 1) - { - return; - } - - meshes = new uint[maxMeshes * 4]; - tris = new byte[maxTris * 4]; - verts = new Vector3[maxVerts]; - } - - /// - /// Clears all object data and resizes the buffers. - /// - /// - /// The maximum vertices the vertex buffer will hold. [Limit: >= 3] - /// - /// - /// The maximum triangles the triangle buffer will hold. [Limit: > 0] - /// - /// - /// The maximum sub-meshes the mesh buffer will hold. [Limit: > 0] - /// - public void Reset(int maxVerts - , int maxTris - , int maxMeshes) - { - Reset(); - - meshes = new uint[maxMeshes * 4]; - tris = new byte[maxTris * 4]; - verts = new Vector3[maxVerts]; - } - - private void Reset() - { - vertCount = 0; - triCount = 0; - meshCount = 0; - meshes = null; - tris = null; - verts = null; - } - - /// - /// Checks the size of the buffers to see if they are large enough to hold the specified - /// data. - /// - /// The maximum vertices the object needs to hold. - /// The maximum triangles the object needs to hold. - /// The maximum sub-meshes the object needs to hold. - /// True if all buffers are large enough to fit the data. - public bool CanFit(int vertCount - , int triCount - , int meshCount) - { - if (verts == null || verts.Length < vertCount - || tris == null || tris.Length < triCount * 4 - || meshes == null || meshes.Length < meshCount * 4) - { - return false; - } - return true; - } - } -} diff --git a/critterai/.svn/pristine/95/95fb8fe90569bdb1327924f59d2be96f989f6aea.svn-base b/critterai/.svn/pristine/95/95fb8fe90569bdb1327924f59d2be96f989f6aea.svn-base deleted file mode 100644 index ec85a40c..00000000 --- a/critterai/.svn/pristine/95/95fb8fe90569bdb1327924f59d2be96f989f6aea.svn-base +++ /dev/null @@ -1,68 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8} - Library - Properties - org.critterai - cai-nmbuild-extras-u3d - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - ..\bin\Release\cai-nmbuild-extras-u3d.xml - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - Properties\AssemblyInfo.cs - - - - - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336} - cai-nmbuild - - - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE} - cai-util-u3d - - - {C4B32B85-13F0-42B8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/96/96f61d248887357f7ea436920e06d80fd1cb2a35.svn-base b/critterai/.svn/pristine/96/96f61d248887357f7ea436920e06d80fd1cb2a35.svn-base deleted file mode 100644 index 46f40225..00000000 --- a/critterai/.svn/pristine/96/96f61d248887357f7ea436920e06d80fd1cb2a35.svn-base +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Match behavior type. (Editor Only) - /// - public enum MatchType - { - /// - /// The compared object references must be equal. (source == target) - /// - Strict = 0, - - /// - /// The target object's name must match the instance pattern of the source. - /// - /// - /// - /// The instance pattern is the source name, followed by a space, and containing the - /// word "instance". The check is lazy. If the source name is "SwampMesh", then - /// both "SwampMesh Instance" and "SwampMesh NotReallyAnInstance" will match. - /// - /// - AnyInstance, - - /// - /// The target object's name begins with the same string as the entire name of the source. - /// - /// - /// Example: If the source object is "Column", then "ColumnWooden" and "Column Iron" will - /// match. - /// - NameBeginsWith - } -} diff --git a/critterai/.svn/pristine/97/9708a116540f6dbf87ae7ee36689c4132dfea7dc.svn-base b/critterai/.svn/pristine/97/9708a116540f6dbf87ae7ee36689c4132dfea7dc.svn-base deleted file mode 100644 index bbc7918e..00000000 Binary files a/critterai/.svn/pristine/97/9708a116540f6dbf87ae7ee36689c4132dfea7dc.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/97/9754d856ae86a5795646c6073d03d60f5444c6b2.svn-base b/critterai/.svn/pristine/97/9754d856ae86a5795646c6073d03d60f5444c6b2.svn-base deleted file mode 100644 index 309db5eb..00000000 --- a/critterai/.svn/pristine/97/9754d856ae86a5795646c6073d03d60f5444c6b2.svn-base +++ /dev/null @@ -1,755 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.nmgen -{ - /// - /// Common configuration parameters used during the NMGen build process. - /// - /// - /// - /// This class represents an aggregation of parameters used at different stages in the - /// build process. Not all parameters are used in all builds. - /// - /// - /// There is no such thing as a 'one size fits all' configuration. The default constructor - /// initializes all values for a normal human sized agent. You will usually discover - /// configurations that work well for categories of source geometry. E.g. A configuration - /// for interior environments and another for outdoor environments. - /// - /// In general, derive and set parameter values as follows: - ///
        - ///
      1. Determine the agent values in world units. (Agent height, step, radius.)
      2. - ///
      3. - /// Derive and from the agent values. - ///
      4. - ///
      5. Derive and set the agent based parameters in cell units.
      6. - ///
      7. Derive and set the and parameters.
      8. - ///
      9. Set the rest of the parameters.
      10. - ///
      - /// - /// All properties and methods will auto-clamp fields to valid values. For example, - /// if the property is set to -1, the value will be clamped to 0. - /// - /// - /// Fields are minimally documented. See the property documentation for details. - /// - /// - /// Implemented as a class with public fields in order to support Unity serialization. - /// Care must be taken not to set the fields to invalid values. - /// - ///
      - /// - [StructLayout(LayoutKind.Sequential)] - [Serializable] - public sealed class NMGenParams - { - /// - /// Tile size. - /// - public int tileSize = 0; - - /// - /// Border size. - /// - public int borderSize = 0; - - /// - /// XZ-plane cell size. - /// - public float xzCellSize = 0.2f; - - /// - /// Y-axis cell size. - /// - public float yCellSize = 0.1f; - - /// - /// Maximum walkable slope. - /// - public float walkableSlope = 45.5f; - - /// - /// Walkable height. - /// - public int walkableHeight = 19; - - /// - /// Walkable step. - /// - public int walkableStep = 3; - - /// - /// Walkable radius. - /// - public int walkableRadius = 2; - - /// - /// Maximum edge length. - /// - public int maxEdgeLength = 0; - - /// - /// Maximum edge deviation. - /// - public float edgeMaxDeviation = 3; - - /// - /// Minimum region area. - /// - public int minRegionArea = 400; - - /// - /// Merge region area. - /// - public int mergeRegionArea = 75; - - /// - /// Maximum vertices per polygon. - /// - public int maxVertsPerPoly = 6; - - /// - /// Detail sample distance. - /// - public float detailSampleDistance = 6; - - /// - /// Detail maximum deviation. - /// - public float detailMaxDeviation = 1; - - /// - /// Options to use when building the contour set. - /// - public ContourBuildFlags contourOptions = - ContourBuildFlags.TessellateAreaEdges | ContourBuildFlags.TessellateWallEdges; - - /// - /// If true, use monotone region generation. - /// - public bool useMonotone = false; - - /// - /// The xz-plane voxel size to use when sampling the source geometry. - /// [Limit: >= ] - /// [Units: World] - /// - /// - /// - /// Also known as the 'grid size' and 'voxel size'. - /// - /// - /// This parameter effects how accurately the final navigation mesh can conform to the - /// source geometry on the xz-plane. E.g. How close it can follow the edges of - /// obstructions. It has side effects on most parameters that apply to the xz-plane. - /// - /// - /// The primary governing factor for choosing this value is the value of the agent radius. - /// Start with (maxAgentRadius / 2) for outdoor environments. For indoor - /// environments or when more accuracy is needed, start with (maxAgentRadius / 3). - /// - /// - /// This parameter has a large impact on memmory useage. The smaller the value, the higher - /// the memory cost during the build. So there are special considerations when the source - /// geometry covers a large area. The best solution is use multiple polygon meshes built - /// for use in a multi-tile navigation mesh. Otherwise it may be necessary to lower - /// the resolution. If this is the case, set the cell size based on the source geometry's - /// longest xz-axis. Start with a value of (longestAxis / 1000), then reduce the - /// value as performance and memory allows. - /// - /// - public float XZCellSize - { - get { return xzCellSize; } - set { xzCellSize = Math.Max(NMGen.MinCellSize, value); } - } - - /// - /// The y-axis voxel size to use when sampling the source geometry. - /// [Limit >= ] - /// - /// - /// - /// Also known at the the 'voxel size' for the y-axis. - /// - /// - /// Effects how accurately the height of the final navigation mesh can conform to the - /// source geometry. It has side effects on most parameters that apply to the y-axis. - /// - /// - /// This parameter is based primarily on how far up/down the agent can step. - /// Start with (maxAgentStep / 2.5) and decrease as needed. Note that - /// 'game world' geometry is usually designed for a maximum agent step that is larger than - /// in the real world. Maximum agent step can sometimes be as high as - /// (maxAgentHeight / 2) - /// - /// - /// Smaller values can result in a moderate increase in build times. The effect - /// on memory is minimal. - /// - /// - public float YCellSize - { - get { return yCellSize; } - set { yCellSize = Math.Max(NMGen.MinCellSize, value); } - } - - /// - /// The width/depth size of the tile on the xz-plane. - /// [Limit: >=0] - /// [Units: XZCellSize] - /// - /// - /// A value of zero indicates non-tiled. - /// - /// The tile size should usually be between 500 and 1000. A tile size that is too small - /// can result in extra, unnecessary polygons and less than optimal pathfinding. A value - /// that is too large can be result in memory and performance issues during the build - /// process. In general, pick the largest size that also results in a good tile layout - /// along the x and z axes. (You want to avoid creation of thin tiles along the upper bounds - /// of the navigation mesh.) - /// - /// - public int TileSize - { - get { return tileSize; } - set { tileSize = Math.Max(0, value); } - } - - /// - /// The tile size in world units. - /// - public float TileWorldSize - { - get { return tileSize * xzCellSize; } - } - - /// - /// The closest the mesh should come to the xz-plane AABB of the source geometry. - /// [Limit: >=0] - /// [Units: XZCellSize] - /// - /// - /// - /// The border size exists primarily to support multi-tile meshes and is usually set to - /// zero for single-tile meshes. - /// - /// - /// Determining the exact value to use for multi-tile meshes can be tricky. It is best to - /// set all the other parameters, then use to get an - /// initial value. - /// - /// - public int BorderSize - { - get { return borderSize; } - set { borderSize = Math.Max(0, value); } - } - - /// - /// Derives the recommended border size for tiled mesh builds. - /// - /// - /// - /// The tile size and agent parameters should be set before deriving the border size. - /// - /// - /// The configuration to derive the border size from. - /// The recommended border size. - public static int DeriveBorderSize(NMGenParams config) - { - if (config.TileSize > 0) - { - return config.WalkableRadius + 3; - } - return 0; - } - - /// - /// The maximum slope that is considered walkable. - /// [Limits: 0 <= value <= ] - /// [Units: Degrees] - /// - /// - /// - /// This parameter is used early in the build process to filter out source triangles that - /// have a high slope. The choice of the value is entirely dependant - /// on the maximum slope the agent's locomotion can handle. A good value to start with is - /// slightly over 45 degrees. - /// - /// - public float WalkableSlope - { - get { return walkableSlope; } - set - { - walkableSlope = - Math.Max(0, Math.Min(NMGen.MaxAllowedSlope, value)); - } - } - - /// - /// Minimum floor to 'ceiling' height that will still allow the floor area to be - /// considered walkable. - /// [Limit: >= ] - /// [Units: YCellSize] - /// - /// - /// - /// Permits detection of overhangs in the source geometry that make the geometry - /// below un-walkable. - /// - /// - /// Usually set to the maximum agent height. - /// - /// - /// Example: Consider a table located on a floor. With this parameter set correctly, - /// the floor area under the table will not be considered walkable. - /// - /// Value: Walkable Height - /// - public int WalkableHeight - { - get { return walkableHeight; } - set { walkableHeight = Math.Max(NMGen.MinWalkableHeight, value); } - } - - /// - /// The walkable height in world units. - /// - public float WorldWalkableHeight - { - get { return walkableHeight * yCellSize; } - } - - /// - /// Derives from a world units value. - /// - /// - /// The value will be snapped to the base unit type. (Cell size.) - /// The must be set before using this method. - /// - /// The walkable height in world units. - public void SetWalkableHeight(float worldHeight) - { - WalkableHeight = (int)Math.Ceiling(worldHeight / yCellSize); - } - - /// - /// Maximum ledge height that is considered to be traversable. - /// [Limit: >=0] - /// [Units: YCellSize] - /// - /// - /// - /// Determines when a ledge in the source geometry can be traversed, rather than acting as - /// an obstruction. Allows the mesh to flow over low lying obstructions such as curbs and - /// up/down stairways. - /// - /// - /// This parameter is normally based on how far up/down the agent can step, though often - /// it needs to be set higher because of the way the source geometry is designed. Start - /// with ceil(maxAgentStep / ) and adjust from there. - /// - /// Value: Waklable Step - /// - public int WalkableStep - { - get { return walkableStep; } - set { walkableStep = Math.Max(0, value); } - } - - /// - /// The walkable set in world units. - /// - public float WorldWalkableStep - { - get { return walkableStep * yCellSize; } - } - - /// - /// Derives the from a world units value. - /// - /// - /// The value will be snapped to the base unit type. (Cell size.) - /// The must be set before using this method. - /// - /// The walkable step in world units. - public void SetWalkableStep(float worldStep) - { - WalkableStep = (int)Math.Floor(worldStep / yCellSize); - } - - /// - /// Represents the closest any part of a mesh should get to an obstruction in the source - /// geometry. - /// [Limit: >=0] - /// [Units: XZCellSize] - /// - /// - /// - /// Effects the size of the border around obstacles. Many path planners (including CAINav) - /// treat agents as a point on the navigation mesh. So the navigation mesh needs to be - /// eroded by the agent's radius so the planner won't plan a path that comes too close - /// to obstructions, or passes through areas that are too thin for the agent to fit. - /// - /// - /// Start with a value of ceil(maxAgentRadius / ). - /// A value of zero is not recommended. - /// - /// Value: Waklable Radius - /// - public int WalkableRadius - { - get { return walkableRadius; } - set { walkableRadius = Math.Max(0, value); } - } - - /// - /// The walkable radius in world units. - /// - public float WorldWalkableRadius - { - get { return walkableRadius * xzCellSize; } - } - - /// - /// Derives the from a world units value. - /// - /// - /// The value will be snapped to the base unit type. (Cell size.) - /// The must be set before using this method. - /// - /// The walkable radius in world units. - public void SetWalkableRadius(float worldRadius) - { - WalkableRadius = (int)Math.Ceiling(worldRadius / xzCellSize); - } - - /// - /// If true, use monotone region generation. Otherwise use watershed partitioning. - /// - /// - /// - public bool UseMonotone - { - get { return useMonotone; } - set { useMonotone = value; } - } - - /// - /// The minimum number of cells allowed to form isolated island meshes. - /// [Limit: >=0] - /// [Units: XZCellSize] - /// - /// - /// Prevents the formation of meshes that are too small to be of use. - /// - /// If you really don't want or expect any island regions, then set this parameter to a - /// high value. Otherwise the value will depend entirely on your needs. - /// - /// - /// In the example below, the value has been set too low, allowing the formation of - /// small meshes on the top of obstructions. - /// - /// Value: MinRegionArea - /// - public int MinRegionArea - { - get { return minRegionArea; } - set { minRegionArea = Math.Max(0, value); } - } - - /// - /// The minimum region area in world units. - /// - public float WorldMinRegionArea - { - get { return minRegionArea * xzCellSize * xzCellSize; } - } - - /// - /// Derives the from a world units value. - /// - /// - /// The value will be snapped to the base unit type. (Cell size.) - /// The must be set before using this method. - /// - /// The minimum region area in world units. - public void SetMinRegionArea(float worldArea) - { - MinRegionArea = (int)Math.Ceiling(worldArea / (xzCellSize * xzCellSize)); - } - - /// - /// Any regions with an cell count smaller than this value will, if possible, be merged - /// with larger regions. - /// [Limit: >=0] - /// [Units: XZCellSize] - /// - public int MergeRegionArea - { - get { return mergeRegionArea; } - set { mergeRegionArea = Math.Max(0, value); } - } - - /// - /// The merge region area in world units. - /// - public float WorldMergeRegionArea - { - get { return mergeRegionArea * xzCellSize * xzCellSize; } - } - - /// - /// Derives the from a world units value. - /// - /// - /// The value will be snapped to the base unit type. (Cell size.) - /// The must be set before using this method. - /// - /// The merge region area in world units. - public void SetMergeRegionArea(float worldArea) - { - MergeRegionArea = (int)Math.Ceiling(worldArea / (xzCellSize * xzCellSize)); - } - - /// - /// The maximum allowed length for edges on the border of the mesh. - /// [Limit: >=0] - /// [Units: XZCellSize] - /// - /// - /// - /// Sometimes the build process can result in long thin triangles along the the mesh border. - /// This parameters is used during the contour build process to add extra border vertices - /// to prevent this from happening. - /// - /// - /// Start with a maximum edge length of zero (disabled). If you see a problem, then start - /// with ( * 8) and adjust from there. - /// - /// - public int MaxEdgeLength - { - get { return maxEdgeLength; } - set { maxEdgeLength = Math.Max(0, value); } - } - - /// - /// The maximum edge length in world units. - /// - public float WorldMaxEdgeLength - { - get { return maxEdgeLength * xzCellSize; } - } - - /// - /// Derives the from a world units value. - /// - /// - /// The value will be snapped to the base unit type. (Cell size.) - /// The must be set before using this method. - /// - /// The walkable radius in world units. - public void SetMaxEdgeLength(float worldLength) - { - MaxEdgeLength = (int)Math.Ceiling(worldLength / xzCellSize); - } - - /// - /// The maximum distance the edges of the mesh should deviate from the source geometry. - /// [Limit: >=0] - /// [Units: World] - /// - /// - /// - /// The - /// - /// Douglas–Peucker algorithm is used when simplifying the borders of the mesh. - /// This parameter effects how much simplification occurs. A higher number will result in - /// more lost detail, but also fewer unnecessary polygons around the border. A good place - /// to start is between 1.1 and 1.5. Low values, especially zero (no simplification), are - /// not recommended since they can result in a large number of small triangles around the - /// border. - /// - /// Applies only to the xz-plane. - /// - public float EdgeMaxDeviation - { - get { return edgeMaxDeviation; } - set { edgeMaxDeviation = Math.Max(0, value); } - } - - /// - /// Options to use when building the contour set. - /// - /// - public ContourBuildFlags ContourOptions - { - get { return contourOptions; } - set { contourOptions = value; } - } - - /// - /// Sets the sample distance to use when matching the detail mesh surface to the source - /// geometry. (Height detail only.) - /// [Limits: 0 or >= 0.9] - /// [Units: World] - /// - /// - /// - /// This parameter is used in conjunction with - /// to control how much extra height detail a object will - /// contain. - /// - /// - /// The sample distance is used to lay out sample points along the edges and across the - /// surface of the source object's polygons. The height distance - /// from the polygon edge/surface is tested. If the maximum deviation is exceeded, then the - /// sample point is added as a vertex to the detail mesh. - /// - /// - /// The sample distance and deviation should be set as high as possible while still - /// getting the desired height detail. Setting the sample distance to less than 0.9 will - /// effectively disable sampling. Setting the maximum deviation to zero is not recommended - /// since it will result in a large number of detail triangles. - /// - /// - /// Start with a sample distance of (longestXZAxis / 100), where 'longestXZAxis' is - /// based on the bounds of the source geometry. Start with a maximum deviation of - /// ( * 20). - /// - /// - public float DetailSampleDistance - { - get { return detailSampleDistance; } - set { detailSampleDistance = value < 0.9f ? 0 : value; } - } - - /// - /// The maximum distance the mesh surface should deviate from the surface of the source - /// geometry. (For height detail only.) [Limit: >=0] [Units: World] - /// - /// - /// - /// See for information on this parameter. - /// - /// - public float DetailMaxDeviation - { - get { return detailMaxDeviation; } - set { detailMaxDeviation = Math.Max(0, value); } - } - - /// - /// The maximum number of vertices allowed for polygons generated during the contour - /// to polygon conversion process. - /// [Limits: 3 <= value < ] - /// - public int MaxVertsPerPoly - { - get { return maxVertsPerPoly; } - set { maxVertsPerPoly = Math.Max(3, Math.Min(NMGen.MaxAllowedVertsPerPoly, value)); } - } - - /// - /// Validates the parameter values. - /// - /// True if the parameter values meet the manditory limits. - public bool IsValid() - { - return !(tileSize < 0 - || xzCellSize < NMGen.MinCellSize - || yCellSize < NMGen.MinCellSize - || walkableHeight < NMGen.MinWalkableHeight - || walkableRadius < 0 - || walkableRadius < 0 - || walkableSlope < 0 - || walkableSlope > NMGen.MaxAllowedSlope - || walkableStep < 0 - || borderSize < 0 - || maxEdgeLength < 0 - || edgeMaxDeviation < 0 - || (detailSampleDistance != 0 && detailSampleDistance < 0.9f) - || detailMaxDeviation < 0 - || minRegionArea < 0 - || mergeRegionArea < 0 - || maxVertsPerPoly > NMGen.MaxAllowedVertsPerPoly); - } - - /// - /// Clones the object. - /// - /// A clone. - public NMGenParams Clone() - { - NMGenParams result = new NMGenParams(); - result.xzCellSize = xzCellSize; - result.yCellSize = yCellSize; - result.detailMaxDeviation = detailMaxDeviation; - result.detailSampleDistance = detailSampleDistance; - result.edgeMaxDeviation = edgeMaxDeviation; - result.borderSize = borderSize; - result.walkableSlope = walkableSlope; - result.walkableStep = walkableStep; - result.maxVertsPerPoly = maxVertsPerPoly; - result.walkableRadius = walkableRadius; - result.maxEdgeLength = maxEdgeLength; - result.walkableHeight = walkableHeight; - result.mergeRegionArea = mergeRegionArea; - result.minRegionArea = minRegionArea; - result.tileSize = tileSize; - result.contourOptions = contourOptions; - result.useMonotone = useMonotone; - - return result; - } - - /// - /// Clamps all parameters to the mandatory limits. - /// - public void Clean() - { - XZCellSize = xzCellSize; - WalkableHeight = walkableHeight; - YCellSize = yCellSize; - - DetailMaxDeviation = detailMaxDeviation; - DetailSampleDistance = detailSampleDistance; - EdgeMaxDeviation = edgeMaxDeviation; - BorderSize = borderSize; - MaxEdgeLength = maxEdgeLength; - MaxVertsPerPoly = MaxVertsPerPoly; - MergeRegionArea = mergeRegionArea; - MinRegionArea = minRegionArea; - WalkableRadius = walkableRadius; - WalkableSlope = walkableSlope; - WalkableStep = walkableStep; - - TileSize = tileSize; - } - } -} diff --git a/critterai/.svn/pristine/97/97fcce5d28f794697861e8ca921068477b368eb9.svn-base b/critterai/.svn/pristine/97/97fcce5d28f794697861e8ca921068477b368eb9.svn-base deleted file mode 100644 index 91d284bd..00000000 --- a/critterai/.svn/pristine/97/97fcce5d28f794697861e8ca921068477b368eb9.svn-base +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav.u3d; -using org.critterai.nmbuild.u3d.editor; -using org.critterai.u3d.editor; -using UnityEditor; -using UnityEngine; -using System.Collections.Generic; -using org.critterai.nav.u3d.editor; -using org.critterai.geom; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(NavmeshBuild))] -public sealed class NavmeshBuildEditor - : Editor -{ - private const string ShowInputKey = "org.critterai.nmbuild.ShowInputConfig"; - private const string ShowNMGenKey = "org.critterai.nmbuild.ShowNMGenConfig"; - private const string ShowNMGenPriKey = "org.critterai.nmbuild.ShowNMGenPri"; - private const string ShowNMGenAdvKey = "org.critterai.nmbuild.ShowNMGenAdv"; - - // Foldout controls. - private static bool mShowInputConfig = false; - private static bool mShowNMGenConfig = false; - private static bool mShowPrimaryConfig = true; - private static bool mShowAdvancedConfig = false; - - void OnEnable() - { - UnityBuildContext.TraceEnabled = EditorPrefs.GetBool(UnityBuildContext.TraceKey); - - mShowInputConfig = EditorPrefs.GetBool(ShowInputKey); - - mShowNMGenConfig = EditorPrefs.GetBool(ShowNMGenKey); - mShowPrimaryConfig = EditorPrefs.GetBool(ShowNMGenPriKey); - mShowAdvancedConfig = EditorPrefs.GetBool(ShowNMGenAdvKey); - } - - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - NavmeshBuild targ = (NavmeshBuild)target; - - EditorGUIUtility.LookLikeControls(100); - - OnGUIState(targ); - - GUI.enabled = !targ.HasBuildData; - - EditorGUILayout.Separator(); - - targ.BuildTarget = NavEditorUtil.OnGUINavmeshDataField("Bake Target", targ.BuildTarget); - - EditorGUILayout.Separator(); - - NavmeshBuildType buildType = (NavmeshBuildType) - EditorGUILayout.EnumPopup("Build Type", targ.BuildType); - - if (buildType != targ.BuildType) - { - targ.BuildType = buildType; - if (buildType == NavmeshBuildType.Advanced) - BuildSelector.Instance.Select(targ); - } - - EditorGUILayout.Separator(); - - TileBuildData tdata = targ.BuildData; - - GUI.enabled = (tdata == null && targ.TargetHasNavmesh); - - if (GUILayout.Button("Log Mesh State")) - Debug.Log(targ.BuildTarget.GetMeshReport()); - - GUI.enabled = true; - - switch (targ.BuildType) - { - case NavmeshBuildType.Standard: - OnGUIStandard(targ); - break; - case NavmeshBuildType.Advanced: - OnGUIAdvanced(targ); - break; - } - - EditorGUILayout.Separator(); - - bool orig = mShowInputConfig; - mShowInputConfig = EditorGUILayout.Foldout(mShowInputConfig, "Input Configuration"); - if (orig != mShowInputConfig) - EditorPrefs.SetBool(ShowInputKey, mShowInputConfig); - - EditorGUIUtility.LookLikeControls(); - - if (mShowInputConfig) - { - GUI.enabled = !targ.HasBuildData; - - EditorGUILayout.Separator(); - - targ.AutoCleanGeometry = EditorGUILayout.Toggle("Auto-Clean", targ.AutoCleanGeometry); - - EditorGUILayout.Separator(); - - ScriptableObject so = (ScriptableObject)targ.SceneQuery; - ScriptableObject nso = (ScriptableObject)EditorGUILayout.ObjectField( - "Scene Query" - , so - , typeof(ScriptableObject) - , false); - - if (nso != so) - { - if (!nso || nso is ISceneQuery) - targ.SceneQuery = (ISceneQuery)nso; - else - { - Debug.LogError(string.Format("{0} does not implement {1}." - , nso.name, typeof(ISceneQuery).Name)); - } - } - - EditorGUILayout.Separator(); - - if (OnGUIManageProcessorList(targ.inputProcessors)) - targ.IsDirty = true; - - GUI.enabled = true; - } - - EditorGUILayout.Separator(); - - if (targ.IsDirty) - { - EditorUtility.SetDirty(target); - targ.IsDirty = false; - } - } - - private static bool OnGUIManageProcessorList(List items) - { - bool origChanged = GUI.changed; - GUI.changed = false; - - // Never allow nulls. So get rid of them first. - // Can happen it target assets have been deleted. - for (int i = items.Count - 1; i >= 0; i--) - { - if (!items[i]) - { - items.RemoveAt(i); - GUI.changed = true; - } - } - - GUILayout.Label("Processors"); - - if (items.Count > 0) - { - int delChoice = -1; - - for (int i = 0; i < items.Count; i++) - { - EditorGUILayout.BeginHorizontal(); - - ScriptableObject currItem = (ScriptableObject)items[i]; - ScriptableObject item = (ScriptableObject) - EditorGUILayout.ObjectField(currItem, typeof(ScriptableObject), false); - - if (!item || GUILayout.Button("X", GUILayout.Width(30))) - delChoice = i; - else if (item != currItem && OkToAdd(items, item)) - items[i] = item; - - EditorGUILayout.EndHorizontal(); - } - - if (delChoice >= 0) - { - GUI.changed = true; - items.RemoveAt(delChoice); - } - } - - EditorGUILayout.Separator(); - - ScriptableObject nitem = (ScriptableObject) - EditorGUILayout.ObjectField("Add", null, typeof(ScriptableObject), false); - - if (nitem && OkToAdd(items, nitem)) - items.Add(nitem); - - bool result = GUI.changed; - GUI.changed = GUI.changed || origChanged; - - return result; - } - - private static bool OkToAdd(List items, ScriptableObject item) - { - if (!item) - { - Debug.LogError("Can't set item to none."); - return false; - } - - if (!(item is IInputBuildProcessor)) - { - Debug.LogError(string.Format("{0} does not implement {1}." - , item.name, typeof(IInputBuildProcessor).Name)); - return false; - } - - if (items.Contains(item)) - { - Debug.LogError(item.name + " already in the processor list."); - return false; - } - - IInputBuildProcessor pa = (IInputBuildProcessor)item; - - if (pa.DuplicatesAllowed) - return true; - - foreach (ScriptableObject itemB in items) - { - IInputBuildProcessor pb = (IInputBuildProcessor)itemB; - - if (pb.DuplicatesAllowed) - continue; - - System.Type ta = pb.GetType(); - System.Type tb = pa.GetType(); - - if (ta.IsAssignableFrom(tb) || tb.IsAssignableFrom(ta)) - { - Debug.LogError(string.Format( - "Disallowed dulicate detected. {0} and {1} are same type." - , pa.Name, pb.Name)); - return false; - } - } - - return true; - } - - private static void OnGUIAdvanced(NavmeshBuild build) - { - EditorGUILayout.Separator(); - - if (GUILayout.Button("Manage Build")) - NavmeshBuildManager.OpenWindow(); - - //// Only allow a reset when not in the buildable state. - if (build.BuildState != NavmeshBuildState.Inactive) - { - GUI.enabled = true; - EditorGUILayout.Separator(); - if (GUILayout.Button("Reset Build")) - build.ResetBuild(); - } - } - - private static void OnGUIStandard(NavmeshBuild build) - { - EditorGUILayout.Separator(); - - GUI.enabled = (build.BuildState != NavmeshBuildState.Invalid); - - if (GUILayout.Button("Build & Bake")) - { - NavmeshBuildHelper helper = new NavmeshBuildHelper(build); - helper.Build(); - } - - EditorGUILayout.Separator(); - - bool origChanged = GUI.changed; - - UnityBuildContext.TraceEnabled = - EditorGUILayout.Toggle("Trace", UnityBuildContext.TraceEnabled); - - GUI.changed = origChanged; - - EditorGUILayout.Separator(); - - GUI.enabled = true; - - bool orig = mShowNMGenConfig; - mShowNMGenConfig = EditorGUILayout.Foldout(mShowNMGenConfig, "NMGen Configuration"); - if (orig != mShowNMGenConfig) - EditorPrefs.SetBool(ShowNMGenKey, mShowNMGenConfig); - - if (mShowNMGenConfig) - { - EditorGUILayout.Separator(); - - NMGenConfig config = build.Config; - - EditorGUILayout.Separator(); - - NMGenConfigControl.OnGUIButtons(build, config, true); - - GUI.enabled = (build.BuildState != NavmeshBuildState.Invalid); - - if (GUILayout.Button("Derive")) - { - NavmeshBuildHelper helper = new NavmeshBuildHelper(build); - - InputAssets assets = helper.BuildInput(); - - if (assets.geometry != null) - { - TriangleMesh m = assets.geometry; - - Vector3 bmin; - Vector3 bmax; - - m.GetBounds(out bmin, out bmax); - - config.Derive(bmin, bmax); - config.ApplyDecimalLimits(); - - GUI.changed = true; - } - } - - GUI.enabled = true; - - EditorGUILayout.Separator(); - - orig = mShowPrimaryConfig; - mShowPrimaryConfig = EditorGUILayout.Foldout(mShowPrimaryConfig, "Primary"); - if (orig != mShowPrimaryConfig) - EditorPrefs.SetBool(ShowNMGenPriKey, mShowPrimaryConfig); - - if (mShowPrimaryConfig) - NMGenConfigControl.OnGUIPrimary(build, config, true); - - EditorGUILayout.Separator(); - - orig = mShowAdvancedConfig; - mShowAdvancedConfig = - EditorGUILayout.Foldout(mShowAdvancedConfig, "Advanced"); - if (orig != mShowAdvancedConfig) - EditorPrefs.SetBool(ShowNMGenAdvKey, mShowAdvancedConfig); - - if (mShowAdvancedConfig) - NMGenConfigControl.OnGUIAdvanced(config, true); - - if (GUI.changed) - build.IsDirty = true; - } - } - - private static void OnGUIState(NavmeshBuild build) - { - INavmeshData btarget = build.BuildTarget; - NavmeshBuildInfo binfo = (btarget == null ? null : btarget.BuildInfo); - - EditorGUILayout.Separator(); - - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - - if (build.BuildState == NavmeshBuildState.Invalid) - { - - if (!(ScriptableObject)btarget) - sb.AppendLine("No build target."); - - if (build.inputProcessors.Count == 0) - sb.AppendLine("No input processors."); - - GUILayout.Label(sb.ToString().Trim() - , EditorUtil.ErrorStyle, GUILayout.ExpandWidth(true)); - - return; - } - - sb.AppendLine("Input Scene: " + NavEditorUtil.SceneDisplayName(binfo)); - - if (build.SceneQuery == null) - sb.AppendLine("Search scope: Entire scene"); - - if (build.TargetHasNavmesh) - sb.AppendLine("Target has existing navmesh."); - else - sb.AppendLine("Target does not have a navmesh."); - - if (build.BuildType == NavmeshBuildType.Advanced) - { - TileBuildData tdata = build.BuildData; - sb.AppendLine("Build state: " + build.BuildState); - sb.AppendLine("Active builds: " - + (tdata == null ? 0 : build.BuildData.GetActive())); - } - - GUILayout.Label(sb.ToString().Trim() - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - - if (NavEditorUtil.SceneMismatch(binfo)) - { - GUILayout.Box("Current scene does not match last input scene." - , EditorUtil.WarningStyle - , GUILayout.ExpandWidth(true)); - } - - EditorGUILayout.Separator(); - - GUI.enabled = (btarget != null); - - NavmeshSceneDraw.Instance.OnGUI(build.BuildTarget, "Show Mesh", true, true); - - GUI.enabled = true; - - return; - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Navmesh Build : Empty" - , false - , NMBEditorUtil.BuildGroup)] - static void CreateEmptyAsset() - { - NavmeshBuild item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Navmesh Build : Standard" - , false, NMBEditorUtil.BuildGroup)] - static void CreateLoadedAsset() - { - NavmeshBuild item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - - ScriptableObject child; - - child = EditorUtil.CreateAsset(item, NMBEditorUtil.AssetLabel); - item.inputProcessors.Add(child); - - CAIBakedNavmesh nm = - EditorUtil.CreateAsset(item, NMBEditorUtil.AssetLabel); - item.BuildTarget = nm; - - EditorUtility.SetDirty(item); - - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/98/984bd6d2358ef27fc3c12bf11ab453bf17a42299.svn-base b/critterai/.svn/pristine/98/984bd6d2358ef27fc3c12bf11ab453bf17a42299.svn-base deleted file mode 100644 index d6b194a3..00000000 --- a/critterai/.svn/pristine/98/984bd6d2358ef27fc3c12bf11ab453bf17a42299.svn-base +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using System.Collections.Generic; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(TagInputFilter))] -public sealed class TagInputFilterEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - TagInputFilter targ = (TagInputFilter)target; - - // Has someone done something naughty? - - if (targ.tags == null) - { - Debug.LogError(targ.name + "Data null reference. Resetting component."); - targ.tags = new List(); - } - - EditorGUILayout.Separator(); - - targ.Priority = EditorGUILayout.IntField("Priority", targ.Priority); - - EditorGUILayout.Separator(); - - targ.recursive = EditorGUILayout.Toggle("Recursive", targ.recursive); - - EditorGUILayout.Separator(); - - EditorUtil.OnGUIManageStringList(targ.tags, true); - - EditorGUILayout.Separator(); - - string msg = "Input Build Processor\n\nFilters out components with the specified tags."; - - if (targ.recursive) - { - msg += - "\n\nRecursive: A component will be filtered out if any of its parents" - + " have one of the tags."; - } - - GUILayout.Box(msg, EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Component Filter : Tag", false, NMBEditorUtil.FilterGroup)] - static void CreateAsset() - { - TagInputFilter item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/98/98a4249ecd14c201807f152f262ef014c275004c.svn-base b/critterai/.svn/pristine/98/98a4249ecd14c201807f152f262ef014c275004c.svn-base deleted file mode 100644 index b2da087c..00000000 --- a/critterai/.svn/pristine/98/98a4249ecd14c201807f152f262ef014c275004c.svn-base +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - internal enum TileBuildState - { - /// - /// Tile has no state. (Not built, not baked, not queued for build.) - /// - NotBuilt = 0, - - /// - /// Tile is in the build queue. - /// - Queued, - - /// - /// The build is underway. - /// - InProgress, - - /// - /// Working tile has been created. (Ready for baking.) - /// - Built, - - /// - /// There is no tile at this location. (Build did not produce a result.) - /// - Empty, - - /// - /// The tile has been baked. (Exists in the navmesh.) - /// - Baked, - - /// - /// An error occured during the build. - /// - Error - } -} diff --git a/critterai/.svn/pristine/99/9944923fd728babdbd73f0c1342466dcba62e0c4.svn-base b/critterai/.svn/pristine/99/9944923fd728babdbd73f0c1342466dcba62e0c4.svn-base deleted file mode 100644 index ccce88e5..00000000 --- a/critterai/.svn/pristine/99/9944923fd728babdbd73f0c1342466dcba62e0c4.svn-base +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.nav.rcn; -using org.critterai.interop; -using System.Collections.Generic; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Provides local steering behaviors for a group of agents. - /// - /// - /// - /// This is the core class for all crowd features. - /// - /// - /// The standard method for setting up the crowd is as follows: - /// - ///
        - ///
      1. Construct the crowd object.
      2. - ///
      3. Set the avoidance configurations using .
      4. - ///
      5. Add agents using and make an initial movement request using - /// .
      6. - ///
      - /// - /// The standard process for managing the crowd is as follows: - /// - ///
        - ///
      1. Call to allow the crowd to manage its agents.
      2. - ///
      3. Use the objects to retreive state, such as position.
      4. - ///
      5. Make movement requests using and - /// .
      6. - ///
      7. Repeat every frame.
      8. - ///
      - /// - /// Some agent configuration settings can be updated using . - /// But the crowd owns the agent position and velocity. If agent position must be fed back - /// into the crowd, the agent must be removed and re-added. - /// - /// - /// Notes: - /// - ///
        - ///
      • Path related information is available for newly added agents only after an - /// has been performed.
      • - ///
      • This class is meant to provide 'local' movement. There is a limit of 256 polygons in - /// the path corridor. So the crowd can't provide pathfinding services over long distances.
      • - ///
      - /// - /// Behavior is undefined if used after disposal. - /// - ///
      - public sealed class CrowdManager - : ManagedObject - { - /* - * Warning: The current design is based on not allowing - * re-initialization of the native class after it is constructed. - * Re-evaluate this class if re-initailization is added. - */ - - /// - /// The maximum number of avoidance configurations that can be associated with the manager. - /// - public const int MaxAvoidanceParams = 8; - - /// - /// An instance of a dtCrowd object. - /// - internal IntPtr root; - - private NavmeshQueryFilter mFilter = null; - private CrowdProximityGrid mGrid = null; - private NavmeshQuery mQuery = null; - - private float mMaxAgentRadius; - private Navmesh mNavmesh; - - internal CrowdAgent[] mAgents; - // Needs to be a separate array since it is used as an argument - // for an interop call. - internal CrowdAgentCoreState[] agentStates; - - /// - /// The maximum number agents that can be managed by the object. - /// - public int MaxAgents { get { return mAgents.Length; } } - - /// - /// The maximum allowed agent radius supported by the object. - /// - public float MaxAgentRadius { get { return mMaxAgentRadius; } } - - /// - /// The navigation mesh used by the object. - /// - public Navmesh Navmesh { get { return mNavmesh; } } - - /// - /// The query filter used by the manager. - /// - /// - /// - /// Updating the state of this filter will alter the steering behaviors of all agents. - /// All agents share the same filter. - /// - /// - public NavmeshQueryFilter QueryFilter { get { return mFilter; } } - - /// - /// The number of agents being managed. - /// - public int AgentCount - { - get - { - int result = 0; - for (int i = 0; i < mAgents.Length; i++) - { - result += (mAgents[i] == null) ? 0 : 1; - } - return result; - } - } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public override bool IsDisposed - { - get { return (root == IntPtr.Zero || mNavmesh.IsDisposed); } - } - - /// - /// The agent from the agent buffer. - /// - /// - /// The buffer index. [Limit: 0 <= value < ] - /// - /// The agent from the buffer, or null no agent at the index. - public CrowdAgent this[int index] - { - get { return (IsDisposed ? null : mAgents[index]); } - } - - private CrowdManager(IntPtr crowd, Navmesh navmesh, int maxAgents, float maxAgentRadius) - : base(AllocType.External) - { - mMaxAgentRadius = maxAgentRadius; - mNavmesh = navmesh; - - root = crowd; - - mAgents = new CrowdAgent[maxAgents]; - agentStates = new CrowdAgentCoreState[maxAgents]; - - IntPtr ptr = CrowdManagerEx.dtcGetFilter(root); - mFilter = new NavmeshQueryFilter(ptr, AllocType.ExternallyManaged); - - ptr = CrowdManagerEx.dtcGetGrid(root); - mGrid = new CrowdProximityGrid(ptr); - - ptr = CrowdManagerEx.dtcGetNavMeshQuery(root); - mQuery = new NavmeshQuery(ptr, true, AllocType.ExternallyManaged); - } - - /// - /// Destructor - /// - ~CrowdManager() - { - RequestDisposal(); - } - - /// - /// Creates a new crowd manager. - /// - /// - /// The maximum number of agents that can be added to the manager. - /// - /// The maximum allowed agent radius. - /// - /// The navigation mesh to use for path planning and steering related queries. - /// - /// A new crowd manager, or null on error. - public static CrowdManager Create(int maxAgents, float maxAgentRadius, Navmesh navmesh) - { - if (navmesh == null || navmesh.IsDisposed) - return null; - - maxAgents = Math.Max(1, maxAgents); - maxAgentRadius = Math.Max(0, maxAgentRadius); - - IntPtr root = - CrowdManagerEx.dtcDetourCrowdAlloc(maxAgents, maxAgentRadius, navmesh.root); - - if (root == IntPtr.Zero) - return null; - - return new CrowdManager(root, navmesh, maxAgents, maxAgentRadius); - } - - /// - /// Immediately frees all unmanaged resources allocated by the object. - /// - public override void RequestDisposal() - { - // There are no managed or local allocations. - if (root != IntPtr.Zero) - { - mFilter.RequestDisposal(); - mFilter = null; - mGrid.Dispose(); - mGrid = null; - mQuery.RequestDisposal(); - mQuery = null; - mNavmesh = null; - mMaxAgentRadius = -1; - agentStates = null; - - for (int i = 0; i < mAgents.Length; i++) - { - if (mAgents[i] == null) - continue; - mAgents[i].Dispose(); - mAgents[i] = null; - } - - CrowdManagerEx.dtcDetourCrowdFree(root); - root = IntPtr.Zero; - } - } - - /// - /// Sets the shared avoidance configuration for a specified index. - /// - /// - /// - /// Multiple avoidance configurations can be set for the manager with agents assigned to - /// different avoidance behaviors via the object. - /// - /// - /// - /// The index. [Limits: 0 <= value < ]. - /// - /// The avoidance configuration. - /// True if the configuration is successfully set. - public bool SetAvoidanceConfig(int index - , CrowdAvoidanceParams config) - { - if (IsDisposed || index < 0 || index >= MaxAvoidanceParams) - return false; - - CrowdManagerEx.dtcSetObstacleAvoidanceParams(root, index, config); - - return true; - } - - /// - /// Gets the shared avoidance configuration for a specified index. - /// - /// - /// - /// Getting a configuration for an index that has not been set will return a configuration - /// in an undefined state. - /// - /// - /// - /// The index. [Limits: 0 <= value < ] - /// - /// An avoidance configuration. - public CrowdAvoidanceParams GetAvoidanceConfig(int index) - { - if (!IsDisposed && index >= 0 && index < MaxAvoidanceParams) - { - CrowdAvoidanceParams result = new CrowdAvoidanceParams(); - CrowdManagerEx.dtcGetObstacleAvoidanceParams(root - , index - , result); - - return result; - } - return null; - } - - /// - /// Adds an agent to the manager. - /// - /// - /// The current position of the agent within the navigation mesh. - /// - /// The agent configuration. - /// - /// A reference to the agent object created by the manager, or null on error. - /// - public CrowdAgent AddAgent(Vector3 position - , CrowdAgentParams agentParams) - { - if (IsDisposed) - return null; - - IntPtr ptr = IntPtr.Zero; - CrowdAgentCoreState initialState = new CrowdAgentCoreState(); - - int index = CrowdManagerEx.dtcAddAgent(root - , ref position - , ref agentParams - , ref ptr - , ref initialState); - - if (index == -1) - return null; - - mAgents[index] = new CrowdAgent(this, ptr, index); - agentStates[index] = initialState; - - return mAgents[index]; - } - - /// - /// Removes an agent from the manager. - /// - /// - /// - /// The object will be immediately disposed. Continued use will - /// result in undefined behavior. - /// - /// - /// The agent to remove. - public void RemoveAgent(CrowdAgent agent) - { - for (int i = 0; i < mAgents.Length; i++) - { - if (mAgents[i] == agent) - { - CrowdManagerEx.dtcRemoveAgent(root, agent.managerIndex); - agent.Dispose(); - mAgents[i] = null; - // Don't need to do anything about the core data array. - } - } - } - - /// - /// Updates the steering and positions for all agents. - /// - /// The time in seconds to update the simulation. - public void Update(float deltaTime) - { - if (IsDisposed) - return; - - CrowdManagerEx.dtcUpdate(root, deltaTime, agentStates); - } - - /// - /// The extents used by the manager when it performs queries against the navigation mesh. - /// - /// - /// - /// All agents and targets should remain within these distances of the navigation mesh - /// surface. For example, if the y-axis extent is 1.0, then the agent should remain - /// between 1.0 above and 1.0 below the surface of the mesh. - /// - /// - /// The extents remains constant over the life of the crowd manager. - /// - /// - /// The extents. - public Vector3 GetQueryExtents() - { - if (IsDisposed) - return Vector3Util.Zero; - Vector3 result = Vector3Util.Zero; - CrowdManagerEx.dtcGetQueryExtents(root, ref result); - return result; - } - /// - /// Gets the velocity sample count. - /// - /// The velocity sample count. - public int GetVelocitySampleCount() - { - if (IsDisposed) - return -1; - return CrowdManagerEx.dtcGetVelocitySampleCount(root); - } - - /// - /// Gets the proximity grid. - /// - public CrowdProximityGrid ProximityGrid { get { return mGrid; } } - - /// - /// The navmesh query used by the manager. - /// - /// - /// - /// The configuration of this query makes it useful only for local pathfinding queries. - /// (Its search size is limited.) Also, it is marked as - /// restricted. - /// - /// - public NavmeshQuery Query { get { return mQuery; } } - } -} diff --git a/critterai/.svn/pristine/99/9954dbc9a5f2038ec58ffe8ae6b1acd14e1fe4cd.svn-base b/critterai/.svn/pristine/99/9954dbc9a5f2038ec58ffe8ae6b1acd14e1fe4cd.svn-base deleted file mode 100644 index 947ba683..00000000 --- a/critterai/.svn/pristine/99/9954dbc9a5f2038ec58ffe8ae6b1acd14e1fe4cd.svn-base +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nav -{ - /// - /// Navigation status flags. - /// - [System.Flags] - public enum NavStatus : uint - { - /// - /// The operation has failed. (Completion status.) - /// - Failure = 1u << 31, - - /// - /// The operation has succeeded. (Completion status.) - /// - Sucess = 1u << 30, - - /// - /// The operation is in progress. (Incomplete) - /// - InProgress = 1u << 29, - - /// - /// Input data was not recognized. - /// - WrongMagic = 1 << 0, - - /// - /// Input data was wrong version. - /// - WrongVersion = 1 << 1, - - /// - /// Operation ran out of memory. - /// - OutOfMemory = 1 << 2, - - /// - /// An input parameter was invalid. - /// - InvalidParam = 1 << 3, - - /// - /// Result buffer for the operation was too small to store the entire result. - /// - BufferTooSmall = 1 << 4, - - /// - /// The navigation query ran out of nodes during the search. - /// - OutOfNodes = 1 << 5, - - /// - /// The navigation query did not reach the end location. The result - /// is a best guess. - /// - PartialResult = 1 << 6 - } -} diff --git a/critterai/.svn/pristine/99/998f7e9d8d933054227396259e93743251d954d0.svn-base b/critterai/.svn/pristine/99/998f7e9d8d933054227396259e93743251d954d0.svn-base deleted file mode 100644 index 803daac3..00000000 --- a/critterai/.svn/pristine/99/998f7e9d8d933054227396259e93743251d954d0.svn-base +++ /dev/null @@ -1,493 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" - -float rcSqrt(float x) -{ - return sqrtf(x); -} - -/// @class rcContext -/// @par -/// -/// This class does not provide logging or timer functionality on its -/// own. Both must be provided by a concrete implementation -/// by overriding the protected member functions. Also, this class does not -/// provide an interface for extracting log messages. (Only adding them.) -/// So concrete implementations must provide one. -/// -/// If no logging or timers are required, just pass an instance of this -/// class through the Recast build process. -/// - -/// @par -/// -/// Example: -/// @code -/// // Where ctx is an instance of rcContext and filepath is a char array. -/// ctx->log(RC_LOG_ERROR, "buildTiledNavigation: Could not load '%s'", filepath); -/// @endcode -void rcContext::log(const rcLogCategory category, const char* format, ...) -{ - if (!m_logEnabled) - return; - static const int MSG_SIZE = 512; - char msg[MSG_SIZE]; - va_list ap; - va_start(ap, format); - int len = vsnprintf(msg, MSG_SIZE, format, ap); - if (len >= MSG_SIZE) - { - len = MSG_SIZE-1; - msg[MSG_SIZE-1] = '\0'; - } - va_end(ap); - doLog(category, msg, len); -} - -rcHeightfield* rcAllocHeightfield() -{ - rcHeightfield* hf = (rcHeightfield*)rcAlloc(sizeof(rcHeightfield), RC_ALLOC_PERM); - memset(hf, 0, sizeof(rcHeightfield)); - return hf; -} - -void rcFreeHeightField(rcHeightfield* hf) -{ - if (!hf) return; - // Delete span array. - rcFree(hf->spans); - // Delete span pools. - while (hf->pools) - { - rcSpanPool* next = hf->pools->next; - rcFree(hf->pools); - hf->pools = next; - } - rcFree(hf); -} - -rcCompactHeightfield* rcAllocCompactHeightfield() -{ - rcCompactHeightfield* chf = (rcCompactHeightfield*)rcAlloc(sizeof(rcCompactHeightfield), RC_ALLOC_PERM); - memset(chf, 0, sizeof(rcCompactHeightfield)); - return chf; -} - -void rcFreeCompactHeightfield(rcCompactHeightfield* chf) -{ - if (!chf) return; - rcFree(chf->cells); - rcFree(chf->spans); - rcFree(chf->dist); - rcFree(chf->areas); - rcFree(chf); -} - - -rcHeightfieldLayerSet* rcAllocHeightfieldLayerSet() -{ - rcHeightfieldLayerSet* lset = (rcHeightfieldLayerSet*)rcAlloc(sizeof(rcHeightfieldLayerSet), RC_ALLOC_PERM); - memset(lset, 0, sizeof(rcHeightfieldLayerSet)); - return lset; -} - -void rcFreeHeightfieldLayerSet(rcHeightfieldLayerSet* lset) -{ - if (!lset) return; - for (int i = 0; i < lset->nlayers; ++i) - { - rcFree(lset->layers[i].heights); - rcFree(lset->layers[i].areas); - rcFree(lset->layers[i].cons); - } - rcFree(lset->layers); - rcFree(lset); -} - - -rcContourSet* rcAllocContourSet() -{ - rcContourSet* cset = (rcContourSet*)rcAlloc(sizeof(rcContourSet), RC_ALLOC_PERM); - memset(cset, 0, sizeof(rcContourSet)); - return cset; -} - -void rcFreeContourSet(rcContourSet* cset) -{ - if (!cset) return; - for (int i = 0; i < cset->nconts; ++i) - { - rcFree(cset->conts[i].verts); - rcFree(cset->conts[i].rverts); - } - rcFree(cset->conts); - rcFree(cset); -} - -rcPolyMesh* rcAllocPolyMesh() -{ - rcPolyMesh* pmesh = (rcPolyMesh*)rcAlloc(sizeof(rcPolyMesh), RC_ALLOC_PERM); - memset(pmesh, 0, sizeof(rcPolyMesh)); - return pmesh; -} - -void rcFreePolyMesh(rcPolyMesh* pmesh) -{ - if (!pmesh) return; - rcFree(pmesh->verts); - rcFree(pmesh->polys); - rcFree(pmesh->regs); - rcFree(pmesh->flags); - rcFree(pmesh->areas); - rcFree(pmesh); -} - -rcPolyMeshDetail* rcAllocPolyMeshDetail() -{ - rcPolyMeshDetail* dmesh = (rcPolyMeshDetail*)rcAlloc(sizeof(rcPolyMeshDetail), RC_ALLOC_PERM); - memset(dmesh, 0, sizeof(rcPolyMeshDetail)); - return dmesh; -} - -void rcFreePolyMeshDetail(rcPolyMeshDetail* dmesh) -{ - if (!dmesh) return; - rcFree(dmesh->meshes); - rcFree(dmesh->verts); - rcFree(dmesh->tris); - rcFree(dmesh); -} - -void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax) -{ - // Calculate bounding box. - rcVcopy(bmin, verts); - rcVcopy(bmax, verts); - for (int i = 1; i < nv; ++i) - { - const float* v = &verts[i*3]; - rcVmin(bmin, v); - rcVmax(bmax, v); - } -} - -void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h) -{ - *w = (int)((bmax[0] - bmin[0])/cs+0.5f); - *h = (int)((bmax[2] - bmin[2])/cs+0.5f); -} - -/// @par -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcAllocHeightfield, rcHeightfield -bool rcCreateHeightfield(rcContext* /*ctx*/, rcHeightfield& hf, int width, int height, - const float* bmin, const float* bmax, - float cs, float ch) -{ - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); - - hf.width = width; - hf.height = height; - rcVcopy(hf.bmin, bmin); - rcVcopy(hf.bmax, bmax); - hf.cs = cs; - hf.ch = ch; - hf.spans = (rcSpan**)rcAlloc(sizeof(rcSpan*)*hf.width*hf.height, RC_ALLOC_PERM); - if (!hf.spans) - return false; - memset(hf.spans, 0, sizeof(rcSpan*)*hf.width*hf.height); - return true; -} - -static void calcTriNormal(const float* v0, const float* v1, const float* v2, float* norm) -{ - float e0[3], e1[3]; - rcVsub(e0, v1, v0); - rcVsub(e1, v2, v0); - rcVcross(norm, e0, e1); - rcVnormalize(norm); -} - -/// @par -/// -/// Only sets the aread id's for the walkable triangles. Does not alter the -/// area id's for unwalkable triangles. -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles -void rcMarkWalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle, - const float* verts, int /*nv*/, - const int* tris, int nt, - unsigned char* areas) -{ - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); - - const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI); - - float norm[3]; - - for (int i = 0; i < nt; ++i) - { - const int* tri = &tris[i*3]; - calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm); - // Check if the face is walkable. - if (norm[1] > walkableThr) - areas[i] = RC_WALKABLE_AREA; - } -} - -/// @par -/// -/// Only sets the aread id's for the unwalkable triangles. Does not alter the -/// area id's for walkable triangles. -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcHeightfield, rcClearUnwalkableTriangles, rcRasterizeTriangles -void rcClearUnwalkableTriangles(rcContext* /*ctx*/, const float walkableSlopeAngle, - const float* verts, int /*nv*/, - const int* tris, int nt, - unsigned char* areas) -{ - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); - - const float walkableThr = cosf(walkableSlopeAngle/180.0f*RC_PI); - - float norm[3]; - - for (int i = 0; i < nt; ++i) - { - const int* tri = &tris[i*3]; - calcTriNormal(&verts[tri[0]*3], &verts[tri[1]*3], &verts[tri[2]*3], norm); - // Check if the face is walkable. - if (norm[1] <= walkableThr) - areas[i] = RC_NULL_AREA; - } -} - -int rcGetHeightFieldSpanCount(rcContext* /*ctx*/, rcHeightfield& hf) -{ - // TODO: VC complains about unref formal variable, figure out a way to handle this better. -// rcAssert(ctx); - - const int w = hf.width; - const int h = hf.height; - int spanCount = 0; - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - for (rcSpan* s = hf.spans[x + y*w]; s; s = s->next) - { - if (s->area != RC_NULL_AREA) - spanCount++; - } - } - } - return spanCount; -} - -/// @par -/// -/// This is just the beginning of the process of fully building a compact heightfield. -/// Various filters may be applied applied, then the distance field and regions built. -/// E.g: #rcBuildDistanceField and #rcBuildRegions -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcAllocCompactHeightfield, rcHeightfield, rcCompactHeightfield, rcConfig -bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, - rcHeightfield& hf, rcCompactHeightfield& chf) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD); - - const int w = hf.width; - const int h = hf.height; - const int spanCount = rcGetHeightFieldSpanCount(ctx, hf); - - // Fill in header. - chf.width = w; - chf.height = h; - chf.spanCount = spanCount; - chf.walkableHeight = walkableHeight; - chf.walkableClimb = walkableClimb; - chf.maxRegions = 0; - rcVcopy(chf.bmin, hf.bmin); - rcVcopy(chf.bmax, hf.bmax); - chf.bmax[1] += walkableHeight*hf.ch; - chf.cs = hf.cs; - chf.ch = hf.ch; - chf.cells = (rcCompactCell*)rcAlloc(sizeof(rcCompactCell)*w*h, RC_ALLOC_PERM); - if (!chf.cells) - { - ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.cells' (%d)", w*h); - return false; - } - memset(chf.cells, 0, sizeof(rcCompactCell)*w*h); - chf.spans = (rcCompactSpan*)rcAlloc(sizeof(rcCompactSpan)*spanCount, RC_ALLOC_PERM); - if (!chf.spans) - { - ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.spans' (%d)", spanCount); - return false; - } - memset(chf.spans, 0, sizeof(rcCompactSpan)*spanCount); - chf.areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*spanCount, RC_ALLOC_PERM); - if (!chf.areas) - { - ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Out of memory 'chf.areas' (%d)", spanCount); - return false; - } - memset(chf.areas, RC_NULL_AREA, sizeof(unsigned char)*spanCount); - - const int MAX_HEIGHT = 0xffff; - - // Fill in cells and spans. - int idx = 0; - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcSpan* s = hf.spans[x + y*w]; - // If there are no spans at this cell, just leave the data to index=0, count=0. - if (!s) continue; - rcCompactCell& c = chf.cells[x+y*w]; - c.index = idx; - c.count = 0; - while (s) - { - if (s->area != RC_NULL_AREA) - { - const int bot = (int)s->smax; - const int top = s->next ? (int)s->next->smin : MAX_HEIGHT; - chf.spans[idx].y = (unsigned short)rcClamp(bot, 0, 0xffff); - chf.spans[idx].h = (unsigned char)rcClamp(top - bot, 0, 0xff); - chf.areas[idx] = s->area; - idx++; - c.count++; - } - s = s->next; - } - } - } - - // Find neighbour connections. - const int MAX_LAYERS = RC_NOT_CONNECTED-1; - int tooHighNeighbour = 0; - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - rcCompactSpan& s = chf.spans[i]; - - for (int dir = 0; dir < 4; ++dir) - { - rcSetCon(s, dir, RC_NOT_CONNECTED); - const int nx = x + rcGetDirOffsetX(dir); - const int ny = y + rcGetDirOffsetY(dir); - // First check that the neighbour cell is in bounds. - if (nx < 0 || ny < 0 || nx >= w || ny >= h) - continue; - - // Iterate over all neighbour spans and check if any of the is - // accessible from current cell. - const rcCompactCell& nc = chf.cells[nx+ny*w]; - for (int k = (int)nc.index, nk = (int)(nc.index+nc.count); k < nk; ++k) - { - const rcCompactSpan& ns = chf.spans[k]; - const int bot = rcMax(s.y, ns.y); - const int top = rcMin(s.y+s.h, ns.y+ns.h); - - // Check that the gap between the spans is walkable, - // and that the climb height between the gaps is not too high. - if ((top - bot) >= walkableHeight && rcAbs((int)ns.y - (int)s.y) <= walkableClimb) - { - // Mark direction as walkable. - const int lidx = k - (int)nc.index; - if (lidx < 0 || lidx > MAX_LAYERS) - { - tooHighNeighbour = rcMax(tooHighNeighbour, lidx); - continue; - } - rcSetCon(s, dir, lidx); - break; - } - } - - } - } - } - } - - if (tooHighNeighbour > MAX_LAYERS) - { - ctx->log(RC_LOG_ERROR, "rcBuildCompactHeightfield: Heightfield has too many layers %d (max: %d)", - tooHighNeighbour, MAX_LAYERS); - } - - ctx->stopTimer(RC_TIMER_BUILD_COMPACTHEIGHTFIELD); - - return true; -} - -/* -static int getHeightfieldMemoryUsage(const rcHeightfield& hf) -{ - int size = 0; - size += sizeof(hf); - size += hf.width * hf.height * sizeof(rcSpan*); - - rcSpanPool* pool = hf.pools; - while (pool) - { - size += (sizeof(rcSpanPool) - sizeof(rcSpan)) + sizeof(rcSpan)*RC_SPANS_PER_POOL; - pool = pool->next; - } - return size; -} - -static int getCompactHeightFieldMemoryusage(const rcCompactHeightfield& chf) -{ - int size = 0; - size += sizeof(rcCompactHeightfield); - size += sizeof(rcCompactSpan) * chf.spanCount; - size += sizeof(rcCompactCell) * chf.width * chf.height; - return size; -} -*/ \ No newline at end of file diff --git a/critterai/.svn/pristine/9a/9a141a8deec1375d666f32a7b7025f18d8dbee2b.svn-base b/critterai/.svn/pristine/9a/9a141a8deec1375d666f32a7b7025f18d8dbee2b.svn-base deleted file mode 100644 index 3eb900e7..00000000 --- a/critterai/.svn/pristine/9a/9a141a8deec1375d666f32a7b7025f18d8dbee2b.svn-base +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * Provides various math related classes and operations. - *

      A high priority is given to performance. In order to achieve the performance goal, the - * following standards have been implemented:

      - *
        - *
      • There is no validation of arguments outside of constructors. - * For example, the {@link org.critterai.math.Vector2#add(float, float, float, Vector2)} - * operation does not validate that the {@link org.critterai.math.Vector2} argument is non-null. - * If the argument is null a runtime error will occur.
      • - *
      • All static operations that return an object require the object be passed in as an "out" argument. - * The out object is updated with the result and its reference returned. This reduces the construction - * costs by allowing clients of the class to re-use the out objects for multiple calls.

        - *
      • - *
      - */ -package org.critterai.math; \ No newline at end of file diff --git a/critterai/.svn/pristine/9a/9aeda9bf5fd414d2d534b8079f76fb37eef3d1a2.svn-base b/critterai/.svn/pristine/9a/9aeda9bf5fd414d2d534b8079f76fb37eef3d1a2.svn-base deleted file mode 100644 index a5bb5336..00000000 --- a/critterai/.svn/pristine/9a/9aeda9bf5fd414d2d534b8079f76fb37eef3d1a2.svn-base +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.nav -{ - /// - /// Configuration parameters for objects. - /// - [StructLayout(LayoutKind.Sequential)] - public struct CrowdAgentParams - { - /* - * Source: DetourCrowd.h dtCrowdAgentParams (struct) - * - * Design notes: - * - * Structure vs Class - * - * I'm still uncertain whether this should be implemented as - * a class or a structure. But I've chosen structure for now. - * - * I will need a structure in order to support passing - * the data as an interop array. An array will be required if I want - * to support more efficent mass updates. (Add/update multiple agents - * at once.) - * - * The significant downside is that a structure doesn't support - * Unity serialization. - * - */ - - /// - /// Agent radius. [Limit: >= 0] - /// - public float radius; - - /// - /// Agent height. [Limit: > 0] - /// - public float height; - - /// - /// Maximum allowed acceleration. [Limit: >= 0] - /// - public float maxAcceleration; - - /// - /// Maximum allowed speed. [Limit: >= 0] - /// - public float maxSpeed; - - /// - /// Defines how close a collision element must be before it is considered in steering - /// behaviors. [Limit: > 0] - /// - /// - /// - /// Collision elements include other agents and navigation mesh boundaries. - /// - /// - /// The value is often based on the agent radius and/or and maximum speed. - /// E.g. (radius * 8) - /// - /// - public float collisionQueryRange; - - /// - /// The path optimization range. [Limit: >= 0] - /// - /// - /// - /// Only applicable if includes the - /// flag. - /// - /// - /// This value is often based on the agent radius. E.g. (radius * 30) - /// - /// - /// - public float pathOptimizationRange; - - /// - /// How aggresive the agent manager should be at avoiding collisions with this agent. - /// [Limit: >= 0] - /// - /// - /// - /// A higher value will result in agents trying to stay farther away from each other at - /// the cost of more difficult steering in tight spaces. - /// - /// - public float separationWeight; - - /// - /// Flags that impact steering behavior. - /// - public CrowdUpdateFlags updateFlags; - - /// - /// The index of the avoidance parameters to use for the agent. - /// [Limits: 0 <= value < - /// - /// - /// - /// The permits agents to use different avoidance configurations. - /// (See .) This value is the index of the - /// configuration to use. - /// - /// - /// - public byte avoidanceType; - - // Must exist for marshalling. Not used on managed side of boundary. - // On the native side this is a void pointer for custom user data. - private IntPtr userData; - - /// - /// Copy constructor. - /// - /// The configuration to copy. - public CrowdAgentParams(CrowdAgentParams config) - { - this.radius = config.radius; - this.height = config.height; - this.maxAcceleration = config.maxAcceleration; - this.maxSpeed = config.maxSpeed; - this.collisionQueryRange = config.collisionQueryRange; - this.pathOptimizationRange = config.pathOptimizationRange; - this.separationWeight = config.separationWeight; - this.updateFlags = config.updateFlags; - this.avoidanceType = config.avoidanceType; - this.userData = config.userData; - } - } -} diff --git a/critterai/.svn/pristine/9b/9b05c663ccd3d2041d74fb7770584aae5c3b8c52.svn-base b/critterai/.svn/pristine/9b/9b05c663ccd3d2041d74fb7770584aae5c3b8c52.svn-base deleted file mode 100644 index 587cdde2..00000000 --- a/critterai/.svn/pristine/9b/9b05c663ccd3d2041d74fb7770584aae5c3b8c52.svn-base +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -namespace org.critterai.nmbuild -{ - /// - /// A standard build task. - /// - public interface IBuildTask - : IPriorityItem - { - /// - /// If true, the task can be safely run on a separate thread from the object(s) monitoring - /// its state. - /// - /// - /// - /// If true, the method will never throw exceptions. - /// - /// - /// The value of this property is immutable after construction. - /// - /// - bool IsThreadSafe { get; } - - /// - /// The task is in a finished state. - /// - bool IsFinished { get; } - - /// - /// Messages available after the task is finished. - /// - /// - /// - /// Will return a zero length array if the task is not finished or there are - /// no messages. Will always provide a message on abort. - /// - /// - string[] Messages { get; } - - /// - /// Requests an abort of the task. - /// - /// - /// - /// There may be a delay in the actual abort for tasks running on a separate thread. - /// - /// - /// The reason for the abort. - void Abort(string reason); - - /// - /// The current state of the task. - /// - BuildTaskState TaskState { get; } - - /// - /// Runs the task through to a finished state. - /// - /// - /// - /// If is true, this method can be run on a separate - /// thread from the object(s) that are monitoring the task state. - /// - /// - void Run(); - } -} diff --git a/critterai/.svn/pristine/9b/9b0722cf92bb4d5a89278a5b7ca77156dc33217a.svn-base b/critterai/.svn/pristine/9b/9b0722cf92bb4d5a89278a5b7ca77156dc33217a.svn-base deleted file mode 100644 index 1a28fb4d..00000000 --- a/critterai/.svn/pristine/9b/9b0722cf92bb4d5a89278a5b7ca77156dc33217a.svn-base +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.nav; - -namespace org.critterai.nav.u3d -{ - /// - /// A ScritableObject that represents navigation data that baked at design time. - /// - /// - /// - /// This interface is only valid when implemented by a ScriptableObject. - /// - /// - public interface INavmeshData - { - /// - /// Information related to the build of the mesh data. - /// - /// - /// - /// This information is used by the build system to perform partial re-builds and provide - /// helpful information to the user. - /// - /// - /// Partial re-build features will not be available if this property is null. - /// - /// - NavmeshBuildInfo BuildInfo { get; } - - /// - /// True if the navigation mesh is available. - /// - /// True if the navigation mesh is available. - bool HasNavmesh { get; } - - /// - /// Creates a new object from the mesh data - /// - /// - /// A new object. Or null if the mesh is not available. - /// - Navmesh GetNavmesh(); - - /// - /// The version of the data. - /// - /// - /// - /// This is used to track changes to the mesh data. It is incremented every time new data is - /// loaded. - /// - /// - int Version { get; } - - /// - /// Loads a single-tile navigation mesh from the provided data. - /// - /// The tile build data. - /// The build information. (Optional) - /// The flags for the operation. - NavStatus Load(NavmeshTileBuildData buildData, NavmeshBuildInfo buildConfig); - - /// - /// Loads a navigation mesh. - /// - /// The mesh configuration. - /// The tiles to add to the mesh. - /// The build information. (Optional) - /// The flags for the operation. - NavStatus Load(NavmeshParams config, NavmeshTileData[] tiles, NavmeshBuildInfo buildConfig); - - /// - /// Load a navigation mesh from data created from the - /// method. - /// - /// The serialized mesh. - /// The build information. (Optional) - /// The flags for the operation. - NavStatus Load(byte[] serializedMesh, NavmeshBuildInfo buildConfig); - - /// - /// Generates a human readable report of the mesh data. - /// - /// A human readable report of the mesh data. - string GetMeshReport(); - } -} diff --git a/critterai/.svn/pristine/9c/9c230fda9cc74d31525f23025b902c398cf7b10b.svn-base b/critterai/.svn/pristine/9c/9c230fda9cc74d31525f23025b902c398cf7b10b.svn-base deleted file mode 100644 index 73d594da..00000000 --- a/critterai/.svn/pristine/9c/9c230fda9cc74d31525f23025b902c398cf7b10b.svn-base +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - internal delegate void BuildDelegate(NavmeshBuild build); -} diff --git a/critterai/.svn/pristine/9d/9dbeddf0067ccb48b25d582f20597bc4c95acc42.svn-base b/critterai/.svn/pristine/9d/9dbeddf0067ccb48b25d582f20597bc4c95acc42.svn-base deleted file mode 100644 index 57b963dc..00000000 --- a/critterai/.svn/pristine/9d/9dbeddf0067ccb48b25d582f20597bc4c95acc42.svn-base +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// A ScriptableObject used to query the scene for components. (Editor Only) - /// - /// - /// - /// This interface is only valid when implemented by a ScriptableObject. - /// - /// - public interface ISceneQuery - { - /// - /// Initializes the object before each use. - /// - /// - /// - /// This method is called by the manager of the object before each use. It allows the - /// object to refresh its internal state. - /// - /// - void Initialize(); - - /// - /// Gets all components of the specified type, based on the object's query restrictions. - /// - /// The type of component to retrieve. - /// - /// All components of the specified type, or a zero length array if there are none. - /// - T[] GetComponents() where T : Component; - } -} diff --git a/critterai/.svn/pristine/9e/9e208f1ba748db0c351c531bf6f050962caa221c.svn-base b/critterai/.svn/pristine/9e/9e208f1ba748db0c351c531bf6f050962caa221c.svn-base deleted file mode 100644 index b051a61f..00000000 --- a/critterai/.svn/pristine/9e/9e208f1ba748db0c351c531bf6f050962caa221c.svn-base +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.u3d.editor; -using UnityEngine; -using UnityEditor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(CylinderAreaMarker))] -public sealed class CylinderAreaMarkerEditor - : AreaMarkerEditor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - OnGUIStandard((CylinderAreaMarker)target); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [DrawGizmo(GizmoType.NotSelected | GizmoType.SelectedOrChild | GizmoType.Pickable)] - static void DrawGizmo(CylinderAreaMarker marker, GizmoType type) - { - DrawStandardGizmo(marker, type); - } - - [MenuItem(EditorUtil.NMGenGameObjectMenu + "Area Marker : Cyl" - , false - , EditorUtil.GameObjectGroup)] - static void CreateGameObject() - { - GameObject go = new GameObject("AreaMarker"); - go.transform.position = EditorUtil.GetCreatePosition(); - - go.AddComponent(); - - Selection.activeGameObject = go; - } -} diff --git a/critterai/.svn/pristine/9e/9ecc03ce0d7879a9c36e9d2892e6af8b9f3813fc.svn-base b/critterai/.svn/pristine/9e/9ecc03ce0d7879a9c36e9d2892e6af8b9f3813fc.svn-base deleted file mode 100644 index 5bd12c71..00000000 Binary files a/critterai/.svn/pristine/9e/9ecc03ce0d7879a9c36e9d2892e6af8b9f3813fc.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/a1/a176c57ccd65b5bf4c8d019d0a199387c82cdf28.svn-base b/critterai/.svn/pristine/a1/a176c57ccd65b5bf4c8d019d0a199387c82cdf28.svn-base deleted file mode 100644 index aab19c95..00000000 --- a/critterai/.svn/pristine/a1/a176c57ccd65b5bf4c8d019d0a199387c82cdf28.svn-base +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.geom; -using org.critterai.nav; -using org.critterai.nav.u3d.editor; -using org.critterai.nav.u3d; -using org.critterai.nmgen; -using org.critterai.u3d; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal class MeshDebugView - { - private class Geom - { - public TriangleMesh mesh; - public byte[] areas; - } - - private bool mEnabled; - private MeshDebugOption mShow; - private bool mNeedsRepaint; - - private System.Object mDebugObject; - - private int mLastVersion; - private InputGeometry mLastGeom; - private int mLastX; - private int mLastZ; - private int mLastSize; - - public bool NeedsRepaint - { - get { return mNeedsRepaint; } - set { mNeedsRepaint = value; } - } - - public bool Enabled - { - get { return mEnabled; } - set - { - if (mEnabled != value) - { - mEnabled = value; - mNeedsRepaint = true; - } - } - } - - public MeshDebugOption Show - { - get { return mShow; } - set - { - if (mShow != value) - { - mShow = value; - mNeedsRepaint = true; - mDebugObject = null; - } - } - } - - private void HandleWorkingNavmesh(TileSelection selection) - { - NavmeshBuild build = selection.Build; - TileBuildData tdata = build.BuildData; - - if (mDebugObject == null) - { - Navmesh navmesh = null; - - if (tdata.BakeableCount() == 0) - // Nothing to display. - return; - - bool success = true; - - TileSetDefinition tdef = build.TileSetDefinition; - - NavmeshParams nconfig; - NavmeshTileData[] tiles; - - if (tdef == null) - { - tiles = new NavmeshTileData[1] { tdata.GetTileData(0, 0) }; - nconfig = NavUtil.DeriveConfig(tiles[0]); - } - else - { - TileZone zone; - - if (selection.HasSelection) - zone = selection.Zone; - else - zone = new TileZone(0, 0, tdef.Width - 1, tdef.Depth - 1); - - success = tdata.GetMeshBuildData(tdef.BoundsMin, tdef.TileWorldSize, zone - , out nconfig, out tiles); - } - - NavStatus status = NavStatus.Sucess; - - if (success) - { - status = Navmesh.Create(nconfig, out navmesh); - - if ((status & NavStatus.Failure) == 0) - { - foreach (NavmeshTileData tile in tiles) - { - uint trash; - status = navmesh.AddTile(tile, Navmesh.NullTile, out trash); - - if ((status & NavStatus.Sucess) == 0) - { - navmesh = null; - break; - } - } - } - } - - if ((status & NavStatus.Sucess) == 0) - { - Show = MeshDebugOption.None; // Use property. - Debug.LogError("Mesh Debug View: Error creating working navigation mesh: " - + status + ". Disabled display.", build); - } - else - mDebugObject = navmesh; - } - - if (mDebugObject != null) - { - Navmesh nm = (Navmesh)mDebugObject; - NavDebug.Draw(nm, NavmeshSceneDraw.Instance.ColorByArea); - } - - } - - private void HandleInputGeom(NavmeshBuild build, int tx, int tz) - { - if (build.InputGeom != mLastGeom) - { - // Input geometry has changed. Clear debug object. - mLastGeom = build.InputGeom; - mDebugObject = null; - } - - if (build.InputGeom == null) - return; - - if (mDebugObject == null) - { - TileSetDefinition tdef = build.TileSetDefinition; - - Vector3 bmin; - Vector3 bmax; - - tdef.GetTileBounds(tx, tz, true, out bmin, out bmax); - - Geom geom = new Geom(); - - geom.mesh = - build.InputGeom.ExtractMesh(bmin.x, bmin.z, bmax.x, bmax.z, out geom.areas); - - mDebugObject = geom; - } - - if (mDebugObject != null) - { - Geom geom = (Geom)mDebugObject; - if (geom.mesh.triCount > 0) - { - DebugDraw.TriangleMesh(geom.mesh.verts - , geom.mesh.tris, geom.areas, geom.mesh.triCount - , true, 0.25f); - } - } - } - - public void HandlePolyMesh(NavmeshBuild build, int tx, int tz) - { - if (!build) - return; - - if (mDebugObject == null) - { - PolyMesh mesh = build.BuildData.GetPolyMesh(tx, tz); - - if (mesh != null) - mDebugObject = mesh.GetData(false); - } - - if (mDebugObject != null) - NMGenDebug.Draw((PolyMeshData)mDebugObject); - } - - public void HandleDetailMesh(NavmeshBuild build, int tx, int tz) - { - if (!build) - return; - - if (mDebugObject == null) - { - PolyMeshDetail mesh = build.BuildData.GetDetailMesh(tx, tz); - - if (mesh != null) - mDebugObject = mesh.GetData(false); - } - - if (mDebugObject != null) - NMGenDebug.Draw((PolyMeshDetailData)mDebugObject); - } - - public void OnRenderObject(NavmeshBuild build, TileSelection selection) - { - if (!build) - return; - - TileBuildData tdata = build.BuildData; - - if (!mEnabled - || mShow == MeshDebugOption.None - || tdata == null // This restriction is appropriate. - || build != selection.Build) // Important error check. - { - return; - } - - INavmeshData target = build.BuildTarget; - - if (target != null && target.HasNavmesh && NavmeshSceneDraw.Instance.IsShown(target)) - // Don't overdraw the target mesh's display. It has priority. - return; - - if (tdata.Version != mLastVersion) - { - // Build data has changed. Clear debug object. - mLastVersion = tdata.Version; - mDebugObject = null; - } - - int tx = 0; - int tz = 0; - int size = 0; - - if (tdata.IsTiled) - { - tx = selection.SelectedX; - tz = selection.SelectedZ; - size = selection.ZoneSize; - } - - if (mLastX != tx || mLastZ != tz || mLastSize != size) - { - // Change in selection. Clear debug object. - mLastX = tx; - mLastZ = tz; - mLastSize = size; - mDebugObject = null; - // Debug.Log("Clear debug on selection change."); - } - - if (mShow == MeshDebugOption.WorkingMesh) - { - HandleWorkingNavmesh(selection); - return; - } - else if (tdata.IsTiled && !selection.Validate()) - { - // The mesh is tiled with no valid selection. - // Can't display any of the other meshes. - mLastX = -1; - mLastZ = -1; - mLastSize = -1; - return; - } - - // Can only display a single tile for all other display options. - // Choose the tile to display. - - switch (mShow) - { - case MeshDebugOption.PolyMesh: - - HandlePolyMesh(build, tx, tz); - break; - - case MeshDebugOption.Detailmesh: - - HandleDetailMesh(build, tx, tz); - break; - - case MeshDebugOption.InputGeometry: - - if (build.TileSetDefinition != null) - HandleInputGeom(build, tx, tz); - break; - } - } - } -} diff --git a/critterai/.svn/pristine/a1/a1d56e877577d29b88a8931fdb7cfdc357528480.svn-base b/critterai/.svn/pristine/a1/a1d56e877577d29b88a8931fdb7cfdc357528480.svn-base deleted file mode 100644 index bf4a935e..00000000 --- a/critterai/.svn/pristine/a1/a1d56e877577d29b88a8931fdb7cfdc357528480.svn-base +++ /dev/null @@ -1,754 +0,0 @@ -package org.critterai.nmgen; - -import java.util.ArrayDeque; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Implements three algorithms that clean up issues that can - * develop around null region boarders. - * - *

      Detect and fix encompassed null regions:

      - *

      If a null region is found that is fully encompassed by a single - * region, then the region will be split into two regions at the - * null region border.

      - * - *

      Detect and fix "short wrapping" of null regions:

      - *

      Regions can sometimes wrap slightly around the corner of a null region - * in a manner that eventually results in the formation of self-intersecting - * polygons.

      - *

      Example: Before the algorithm is applied:

      - *

      - * - *

      - *

      Example: After the algorithm is applied:

      - *

      - * - *

      - * - *

      Detect and fix incomplete null region connections:

      - *

      If a region touches null region only diagonally, then contour detection - * algorithms may not properly detect the null region connection. This can - * adversely effect other algorithms in the pipeline.

      - *

      Example: Before algorithm is applied:

      - *

      - *     b b a a a a
      - *     b b a a a a
      - *     a a x x x x
      - *     a a x x x x
      - * 

      - *

      Example: After algorithm is applied:

      - *

      - *     b b a a a a
      - *     b b b a a a <-- Span transferred to region B.
      - *     a a x x x x
      - *     a a x x x x
      - * 

      - * - * @see Region Generation - */ -public class CleanNullRegionBorders - implements IOpenHeightFieldAlgorithm -{ - - /* - * Design Notes: - * - * Three algorithms have been aggregated into this single class - * for performance reasons. Otherwise we would be stuck - * performing three full contour searches rather than one. - * - * The optimization method used in the search can result in missed - * null region contours. Consider the following pattern: - * - * x x x x x x - * x a a a a x x - null region WITHOUT SPANS - * x a v v a x a - region A - * x a v v a x v - null region WITHOUT SPANS - * x a a a a x - * x x x x x x - * - * If an all span search is performed, the outer null region (x) will - * be detected, but during the process all a-region spans will be marked as - * viewed. This will leave no spans available to detect the inner null - * region (v). - * - * I've not fixing this until it proves to be a problem or I figure out - * a way of resolving the design issue without killing performance. - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private final boolean mUseOnlyNullSpans; - - // Working variables. Content is meaningless outside of - // method they are used. - private final ArrayDeque mwOpenSpans - = new ArrayDeque(1024); - private final ArrayDeque mwBorderDistance - = new ArrayDeque(1024); - private final int[] mwNeighborRegions = new int[8]; - - /** - * Constructor. - *

      Choosing a contour detection type:

      - *

      This algorithm has to detect and walk null region contours. (Where - * null regions border non-null regions.) There are two options for - * detection: Search every single span looking for null region - * neighbors. Or search only null region spans looking for - * non-null region neighbors. Since null region spans are only a tiny - * fraction of total spans, the second option has better performance.

      - *

      If a heightfield is constructed such that all null regions have - * at least one null region span in each contour, then set - * useOnlyNullRegionSpans to TRUE.

      - * @param useOnlyNullRegionSpans If TRUE, then only null region spans - * will be used to initially detect null region borders. This - * improves performance. If FALSE, all spans are searched to detect - * borders. - */ - public CleanNullRegionBorders(boolean useOnlyNullRegionSpans) - { - mUseOnlyNullSpans = useOnlyNullRegionSpans; - } - - /** - * {@inheritDoc} - *

      This operation utilizes {@link OpenHeightSpan#flags}. It - * expects the value to be zero on entry, and re-zero's the value - * on exit.

      - *

      Expects a heightfield with fully built regions.

      - */ - @Override - public void apply(OpenHeightfield field) - { - - int nextRegionID = field.regionCount(); - final OpenHeightFieldIterator iter = field.dataIterator(); - - // Iterate over the spans, trying to find null region borders. - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - - if (span.flags != 0) - // Span was processed in a previous iteration. - // Ignore it. - continue; - - span.flags = 1; - - OpenHeightSpan workingSpan = null; - int edgeDirection = -1; - - if (span.regionID() == NULL_REGION) - { - // This is a null region span. See if it - // connects to a span in a non-null region. - edgeDirection = getNonNullBorderDrection(span); - if (edgeDirection == -1) - // This span is not a border span. Ignore it. - continue; - - // This is a border span. Step into the non-null - // region and swing the direction around 180 degrees. - workingSpan = span.getNeighbor(edgeDirection); - edgeDirection = (edgeDirection+2) & 0x3; - } - else if (!mUseOnlyNullSpans) - { - // This is a non-null region span and I'm allowed - // to look at it. See if it connects to a null region. - edgeDirection = getNullBorderDrection(span); - if (edgeDirection == -1) - // This span is not a null region border span. Ignore it. - continue; - workingSpan = span; - } - else - // Not interested in this span. - continue; - - // Process the null region contour. Detect and fix - // local issues. Determine if the region is - // fully encompassed by a single non-null region. - boolean isEncompassedNullRegion = processNullRegion( - workingSpan - , edgeDirection); - - if (isEncompassedNullRegion) - { - // This span is part of a group of null region spans - // that is encompassed within a single non-null region. - // This is not permitted. Need to fix it. - partialFloodRegion(workingSpan - , edgeDirection - , nextRegionID); - nextRegionID++; - } - } - - field.setRegionCount(nextRegionID); - - // Clear all flags. - iter.reset(); - while (iter.hasNext()) - { - iter.next().flags = 0; - } - } - - /** - * Partially flood a region away from the specified direction. - *

      {@link OpenHeightSpan#distanceToRegionCore()} - * is set to zero for all flooded spans.

      - * @param startSpan The span to start the flood from. - * @param borderDirection The hard border for flooding. No - * spans in this direction from the startSpan will be flooded. - * @param newRegionID The region id to assign the flooded - * spans to. - */ - private void partialFloodRegion(OpenHeightSpan startSpan - , int borderDirection - , int newRegionID) - { - // Gather some information. - final int antiBorderDirection = (borderDirection+2) & 0x3; - final int regionID = startSpan.regionID(); - - // Re-assign the start span and queue it for the neighbor search. - startSpan.setRegionID(newRegionID); - startSpan.setDistanceToRegionCore(0); // This information is lost. - mwOpenSpans.add(startSpan); - mwBorderDistance.add(0); - - // Search for new spans that can be assigned the new region. - while(!mwOpenSpans.isEmpty()) - { - // Get the next span off the stack. - final OpenHeightSpan span = mwOpenSpans.pollLast(); - final int distance = mwBorderDistance.pollLast(); - - // Search in all directions for neighbors. - for (int i = 0; i < 4; i++) - { - final OpenHeightSpan nSpan = span.getNeighbor(i); - if (nSpan == null - || nSpan.regionID() != regionID) - // No span in this direction, or the span - // is not in the region being processed. - // Note: It may have already been transferred. - continue; - int nDistance = distance; - if (i == borderDirection) - { - // This neighbor is back toward the border. - if (distance == 0) - // The span is at the border. Can't go - // further in this direction. Ignore - // this neighbor. - continue; - nDistance--; - } - else if (i == antiBorderDirection) - // This neighbor is further away from the border. - nDistance++; - - // Transfer the neighbor to the new region. - nSpan.setRegionID(newRegionID); - nSpan.setDistanceToRegionCore(0); // This information is lost. - - // Add the span to the stack to be processed. - mwOpenSpans.add(nSpan); - mwBorderDistance.add(nDistance); - - } - - } - - } - - /** - * Detects and fixes bad span configurations in the vicinity of a - * null region contour. (See class description for details.) - * @param startSpan A span in a non-null region that borders a null - * region. - * @param startDirection The direction of the null region border. - * @return TRUE if the start span's region completely encompasses - * the null region. - */ - private boolean processNullRegion(OpenHeightSpan startSpan - , int startDirection) - { - - /* - * This algorithm traverses the contour. As it does so, it detects - * and fixes various known dangerous span configurations. - * - * Traversing the contour: A good way to visualize it is to think - * of a robot sitting on the floor facing a known wall. It then - * does the following to skirt the wall: - * 1. If there is a wall in front of it, turn clockwise in 90 degrees - * increments until it finds the wall is gone. - * 2. Move forward one step. - * 3. Turn counter-clockwise by 90 degrees. - * 4. Repeat from step 1 until it finds itself at its original - * location facing its original direction. - * - * See also: http://www.critterai.org/nmgen_contourgen#robotwalk - * - * As the traversal occurs, the number of acute (90 degree) and - * obtuse (270 degree) corners are monitored. If a complete contour is - * detected and (obtuse corners > acute corners), then the null - * region is inside the contour. Otherwise the null region is - * outside the contour, which we don't care about. - */ - - int borderRegionID = startSpan.regionID(); - - // Prepare for loop. - OpenHeightSpan span = startSpan; - OpenHeightSpan nSpan = null; - int dir = startDirection; - - // Initialize monitoring variables. - int loopCount = 0; - int acuteCornerCount = 0; - int obtuseCornerCount = 0; - int stepsWithoutBorder = 0; - boolean borderSeenLastLoop = false; - boolean isBorder = true; // Initial value doesn't matter. - - // Assume a single region is connected to the null region - // until proven otherwise. - boolean hasSingleConnection = true; - - /* - * The loop limit exists for the sole reason of preventing - * an infinite loop in case of bad input data. - * It is set to a very high value because there is no way of - * definitively determining a safe smaller value. Setting - * the value too low can result in rescanning a contour - * multiple times, killing performance. - */ - while (++loopCount < Integer.MAX_VALUE) - { - // Get the span across the border. - nSpan = span.getNeighbor(dir); - - // Detect which type of edge this direction points across. - if (nSpan == null) - { - // It points across a null region border edge. - isBorder = true; - } - else - { - // We never need to perform contour detection - // on this span again. So mark it as processed. - nSpan.flags = 1; - if (nSpan.regionID() == NULL_REGION) - { - // It points across a null region border edge. - isBorder = true; - } - else - { - // This isn't a null region border. - isBorder = false; - if (nSpan.regionID() != borderRegionID) - // It points across a border to a non-null region. - // This means the current contour can't - // represent a fully encompassed null region. - hasSingleConnection = false; - } - } - - // Process the border. - if (isBorder) - { - // It is a border edge. - if (borderSeenLastLoop) - { - /* - * A border was detected during the last loop as well. - * Two detections in a row indicates we passed an acute - * (inner) corner. - * - * a x - * x x - */ - acuteCornerCount++; - } - else if (stepsWithoutBorder > 1) - { - /* - * We have moved at least two spans before detecting - * a border. This indicates we passed an obtuse - * (outer) corner. - * - * a a - * a x - */ - obtuseCornerCount++; - stepsWithoutBorder = 0; - // Detect and fix span configuraiton issue around this - // corner. - if (processOuterCorner(span, dir)) - // A change was made and it resulted in the - // corner area having multiple region connections. - hasSingleConnection = false; - } - dir = (dir+1) & 0x3; // Rotate in clockwise direction. - borderSeenLastLoop = true; - stepsWithoutBorder = 0; - } - else - { - /* - * Not a null region border. - * Move to the neighbor and swing the search direction back - * one increment (counterclockwise). By moving the direction - * back one increment we guarantee we don't miss any edges. - */ - span = nSpan; - dir = (dir+3) & 0x3; // Rotate counterclockwise direction. - borderSeenLastLoop = false; - stepsWithoutBorder++; - } - - if (startSpan == span && startDirection == dir) - // Have returned to the original span and direction. - // The search is complete. - // Is the null region inside the contour? - return (hasSingleConnection - && obtuseCornerCount > acuteCornerCount); - } - - // If got here then the null region boarder is too large to be fully - // explored. So it can't be encompassed. - return false; - } - - /** - * Detects and fixes span configuration issues in the vicinity - * of obtuse (outer) null region corners. - * @param referenceSpan The span in a non-null region that is - * just past the outer corner. - * @param borderDirection The direciton of the null region border. - * @return TRUE if more than one region connects to the null region - * in the vicinity of the corner. (This may or may not be due to - * a change made by this operation.) - */ - private boolean processOuterCorner(OpenHeightSpan referenceSpan - , int borderDirection) - { - - boolean hasMultiRegions = false; - - // Get the previous two spans along the border. - OpenHeightSpan backOne = - referenceSpan.getNeighbor((borderDirection+3) & 0x3); - OpenHeightSpan backTwo = backOne.getNeighbor(borderDirection); - OpenHeightSpan testSpan; - - if (backOne.regionID() != referenceSpan.regionID() - && backTwo.regionID() == referenceSpan.regionID()) - { - /* - * Dangerous corner configuration. - * - * a x - * b a - * - * Need to change to one of the following configurations: - * - * b x a x - * b a b b - * - * Reason: During contour detection this type of configuration can - * result in the region connection being detected as a - * region-region portal, when it is not. The region connection - * is actually interrupted by the null region. - * - * This configuration has been demonstrated to result in - * two regions being improperly merged to encompass an - * internal null region. - * - * Example: - * - * a a x x x a - * a a x x a a - * b b a a a a - * b b a a a a - * - * During contour and connection detection for region b, at no - * point will the null region be detected. It will appear - * as if a clean a-b portal exists. - * - * An investigation into fixing this issue via updates to the - * watershed or contour detection algorithms did not turn - * up a better way of resolving this issue. - */ - hasMultiRegions = true; - // Determine how many connections backTwo has to backOne's region. - testSpan = backOne.getNeighbor((borderDirection+3) & 0x3); - int backTwoConnections = 0; - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - { - backTwoConnections++; - testSpan = testSpan.getNeighbor(borderDirection); - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - backTwoConnections++; - } - // Determine how many connections the reference span has - // to backOne's region. - int referenceConnections = 0; - testSpan = backOne.getNeighbor((borderDirection+2) & 0x3); - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - { - referenceConnections++; - testSpan = testSpan.getNeighbor((borderDirection+2) & 0x3); - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - backTwoConnections++; - } - // Change the region of the span that has the most connections - // to the target region. - if (referenceConnections > backTwoConnections) - referenceSpan.setRegionID(backOne.regionID()); - else - backTwo.setRegionID(backOne.regionID()); - } - else if (backOne.regionID() == referenceSpan.regionID() - && backTwo.regionID() == referenceSpan.regionID()) - { - /* - * Potential dangerous short wrap. - * - * a x - * a a - * - * Example of actual problem configuration: - * - * b b x x - * b a x x <- Short wrap. - * b a a a - * - * In the above case, the short wrap around the corner of the - * null region has been demonstrated to cause self-intersecting - * polygons during polygon formation. - * - * This algorithm detects whether or not one (and only one) - * of the axis neighbors of the corner should be re-assigned to - * a more appropriate region. - * - * In the above example, the following configuration is more - * appropriate: - * - * b b x x - * b b x x <- Change to this row. - * b a a a - */ - // Check to see if backTwo should be in a different region. - int selectedRegion = selectedRegionID(backTwo - , (borderDirection+1) & 0x3 - , (borderDirection+2) & 0x3); - if (selectedRegion == backTwo.regionID()) - { - // backTwo should not be re-assigned. How about - // the reference span? - selectedRegion = selectedRegionID(referenceSpan - , borderDirection - , (borderDirection+3) & 0x3); - if (selectedRegion != referenceSpan.regionID()) - { - // The reference span should be reassigned - // to a new region. - referenceSpan.setRegionID(selectedRegion); - hasMultiRegions = true; - } - } - else - { - // backTwo should be re-assigned to a new region. - backTwo.setRegionID(selectedRegion); - hasMultiRegions = true; - } - } - else - /* - * No dangerous configurations detected. But definitely - * has a change in regions at the corner. (We know this - * because one of the previous checks looked for a single - * region for all wrap spans.) - */ - hasMultiRegions = true; - - return hasMultiRegions; - } - - /** - * Checks the span to see if it should be reassigned to a new region. - * @param referenceSpan A span on one side of an null region contour's - * outer corner. It is expected that the all spans that wrap the - * corner are in the same region. - * @param borderDirection The direction of the null region border. - * @param cornerDirection The direction of the outer corner from the - * reference span. - * @return The region the span should be a member of. May be the - * region the span is currently a member of. - */ - private int selectedRegionID(OpenHeightSpan referenceSpan - , int borderDirection - , int cornerDirection) - { - - // Get the regions of all neighbors. - referenceSpan.getDetailedRegionMap(mwNeighborRegions, 0); - - /* - * Initial example state: - * - * a - Known region. - * x - Null region. - * u - Unknown, not checked yet. - * - * u u u - * u a x - * u a a - */ - - // The only possible alternate region id is from - // the span that is opposite the border. So check it first. - int regionID = mwNeighborRegions[(borderDirection+2) & 0x3]; - if (regionID == referenceSpan.regionID() - || regionID == NULL_REGION) - /* - * The region away from the border is either a null region - * or the same region. So we keep the current region. - * - * u u u u u u - * a a x or x a x <-- Potentially bad, but stuck with it. - * u a a u a a - */ - return referenceSpan.regionID(); - - // Candidate region for re-assignment. - int potentialRegion = regionID; - - // Next we check the region opposite from the corner direction. - // If it is the current region, then we definitely can't - // change the region id without risk of splitting the region. - regionID = mwNeighborRegions[(cornerDirection+2) & 0x3]; - if (regionID == referenceSpan.regionID() || regionID == NULL_REGION) - /* - * The region opposite from the corner direction is - * either a null region or the same region. So we - * keep the current region. - * - * u a u u x u - * b a x or b a x - * u a a u a a - */ - return referenceSpan.regionID(); - - /* - * We have checked the early exit special cases. Now a generalized - * brute count is performed. - * - * Priority is given to the potential region. Here is why: - * (Highly unlikely worst case scenario.) - * - * c c c c c c - * b a x -> b b x Select b even though b count == a count. - * b a a b a a - */ - - // Neighbors in potential region. - // We know this will have a minimum value of 1. - int potentialCount = 0; - - // Neighbors in the span's current region. - // We know this will have a minimum value of 2. - int currentCount = 0; - - /* - * Maximum edge case: - * - * b b b - * b a x - * b a a - * - * The maximum edge case for region A can't exist. It - * is filtered out during one of the earlier special cases - * handlers. - * - * Other cases may exist if more regions are involved. - * Such cases will tend to favor the current region. - */ - - for (int i = 0; i < 8; i++) - { - if (mwNeighborRegions[i] == referenceSpan.regionID()) - currentCount++; - else if (mwNeighborRegions[i] == potentialRegion) - potentialCount++; - } - - return (potentialCount < currentCount - ? referenceSpan.regionID() : potentialRegion); - } - - /** - * Returns the direction of the first neighbor in a non-null region. - * @param span The span to check. - * @return The direction of the first neighbor in a non-null region, or - * -1 if all neighbors are in the null region. - */ - private static int getNonNullBorderDrection(OpenHeightSpan span) - { - // Search axis-neighbors. - for (int dir = 0; dir < 4; ++dir) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null && nSpan.regionID() != NULL_REGION) - // The neighbor is a non-null region. - return dir; - } - // All neighbors are in the null region. - return -1; - } - - /** - * Returns the direction of the first neighbor in the null region. - * @param span The span to check. - * @return The direction of the first neighbor that is in the null - * region, or -1 if there are no null region neighbors. - */ - private static int getNullBorderDrection(OpenHeightSpan span) - { - // Search axis-neighbors. - for (int dir = 0; dir < 4; ++dir) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null || nSpan.regionID() == NULL_REGION) - // The neighbor is a null region. - return dir; - } - // All neighbors are in a non-null region. - return -1; - } - -} diff --git a/critterai/.svn/pristine/a2/a22aa5a2c4077371f1b1d6a66e0ae28b9f351725.svn-base b/critterai/.svn/pristine/a2/a22aa5a2c4077371f1b1d6a66e0ae28b9f351725.svn-base deleted file mode 100644 index 1f77cf40..00000000 --- a/critterai/.svn/pristine/a2/a22aa5a2c4077371f1b1d6a66e0ae28b9f351725.svn-base +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.Hashtable; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Contains data that represents the obstructed (solid) area of a bounded - * field of voxels. - *

      The data is stored within spans which represent a vertically contiguous - * group of solid voxels. A reference to the lowest span within a grid - * location is stored at that grid location's width/depth index. Height spans - * further up in the grid's column can be accessed via - * {@link HeightSpan#next()} on the base span. (I.e. By climbing up the links.) - *

      - * @see SolidHeightfieldBuilder - * @see The Voxelization Process - * @see Introduction to Height Fields - */ -public final class SolidHeightfield - extends BoundedField -{ - - /* - * Recast Reference: reHeightfield in Recast.h - */ - - /** - * Implements an iterator that will iterate through all spans within a - * height field. (Not just the base spans.) - *

      Behavior of the iterator is undefined if the interator's source - * is changed during iteration.

      - */ - public class SolidHeightFieldIterator - implements Iterator - { - - private int mNextWidth = 0; - private int mNextDepth = 0; - private HeightSpan mNext = null; - - private int mLastWidth = 0; - private int mLastDepth = 0; - - private SolidHeightFieldIterator() - { - moveToNext(); - } - - /** - * The depth index of the last span returned by {@link #next()} - * @return The depth index of the last span returned by {@link #next()} - */ - public int depthIndex() { return mLastDepth; } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasNext() - { - return (mNext != null); - } - - /** - * {@inheritDoc} - */ - @Override - public HeightSpan next() - { - if (mNext == null) throw new NoSuchElementException(); - HeightSpan next = mNext; - mLastWidth = mNextWidth; - mLastDepth = mNextDepth; - moveToNext(); - return next; - } - - /** - * {@inheritDoc} - * This operation is not supported. - */ - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } - - /** - * Resets the iterator so that it can be re-used. - */ - public void reset() - { - mNextWidth = 0; - mNextDepth = 0; - mNext = null; - mLastWidth = 0; - mLastDepth = 0; - moveToNext(); - } - - /** - * The width index of the last span returned by {@link #next()} - * @return The width index of the last span returned by {@link #next()} - */ - public int widthIndex() { return mLastWidth; } - - /** - * Move to the next span in the data set. - */ - private void moveToNext() - { - if (mNext != null) - { - // There is a current span selected. - if (mNext.next() != null) - { - // The current span has a next. - // Move to it. - mNext = mNext.next(); - return; - } - else - // No more spans in the column of the current grid location. - // Move to next grid location. - mNextWidth++; - } - // Search through the grid until a new base span is found. - for (int depthIndex = mNextDepth - ; depthIndex < depth() - ; depthIndex++) - { - for (int widthIndex = mNextWidth - ; widthIndex < width() - ; widthIndex++) - { - HeightSpan span = - mSpans.get(gridIndex(widthIndex, depthIndex)); - if (span != null) - { - // A new base span was found. Select it. - mNext = span; - mNextWidth = widthIndex; - mNextDepth = depthIndex; - return; - } - } - mNextWidth = 0; - } - // If got here, then there are no more spans. - mNext = null; - mNextDepth = -1; - mNextWidth = -1; - } - } - - /** - * Contains the spans within the heightfield's grid. - *

      Key: Grid index obtained via {@link #gridIndex(int, int)}.
      - * Value: The lowest span at the grid location, or null if there are no - * spans at the grid location.

      - */ - private final Hashtable mSpans = - new Hashtable(); - - /** - * Constructor - *

      The bounds of the field will default to min(0, 0, 0) - * and max(1, 1, 1).

      - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - */ - public SolidHeightfield(float cellSize - , float cellHeight) - { - super(cellSize, cellHeight); - } - - /** - * Adds span data to the heightfield. New span data is either merged - * into existing spans or a new span is created. - *

      Only the following validations are peformed:

      - *
        - *
      • The bounds of the width and depth indices.
      • - *
      • The lower bounds of the height indices. (>=0)
      • - *
      • Height min <= max.
      • - *
      - *

      No check that the height maximum is within bounds is performed.

      - *

      Flags are set as follows:

      - *
        - *
      • If the maximum of the new data coincides with the maximum of an - * existing span, the old and new flags are merged.
      • - *
      • If the new data represents a new maximum (new span or new maximum - * for an existing span), the flags for the new data is used - * exclusively.
      • - *
      • Otherwise, the new data's flags are ignored.
      • - *
      - *

      Basically, only the flags at the top of a span are considered - * to matter.

      - * @param widthIndex The width index of the column that contains the - * new data. - * @param depthIndex The depth index of the column that contains the - * new data. - * @param heightIndexMin The solid span's minimum. The minimum of the - * obstructed space. (In zero-based height increments based on - * {@link #cellHeight()}.) - * @param heightIndexMax The solid span's maximum. The maximum of the - * obstructed space. (In zero-based height increments based on - * {@link #cellHeight()}.) - * @param flags The flags for the new data. - * @return TRUE if the data was successfully added. Otherwise FALSE. - * The only time this operation will fail is if the argument data is - * invalid in some way. - */ - public boolean addData(int widthIndex - , int depthIndex - , int heightIndexMin - , int heightIndexMax - , int flags) - { - if (widthIndex < 0 - || widthIndex >= width() - || depthIndex < 0 - || depthIndex >= depth()) - // Outside of grid bounds. - return false; - - if (heightIndexMin < 0 - || heightIndexMax < 0 - || heightIndexMin > heightIndexMax) - // Invalid height values. - return false; - - // Find the grid location of the span and get existing data for the - // location. - int gridIndex = gridIndex(widthIndex, depthIndex); - HeightSpan currentSpan = mSpans.get(gridIndex); - - if (currentSpan == null) - { - // This is the first span for this grid location. - // Generate a new span. - mSpans.put(gridIndex, new HeightSpan(heightIndexMin - , heightIndexMax - , flags)); - return true; - } - - // Span data already exists at this location. Search the spans in - // this column to see which one should contain this span. Or if a - // new span should be created. - HeightSpan previousSpan = null; - while (currentSpan != null) - { - /* - * Note: The way the spans are built, separate spans are always - * guaranteed to have a gap between them. The minimum gap will - * be the cell height increment. - */ - if (currentSpan.min() > heightIndexMax + 1) - { - /* - * The new span is below the current span and NOT adjacent. - * Due to the structure of the data, the new span is - * guaranteed to fit below the current span. - * - * Create a new span. - */ - HeightSpan newSpan = new HeightSpan(heightIndexMin - , heightIndexMax - , flags); - // Insert this span below the current span. - newSpan.setNext(currentSpan); - if (previousSpan == null) - // The new span is the new first span in this column. - // Insert it at the base of this column. - mSpans.put(gridIndex, newSpan); - else - // The new span is between two spans. - // Link the previous span to the new span. - previousSpan.setNext(newSpan); - return true; - } - else if (currentSpan.max() < heightIndexMin - 1) - { - // Current span is below the new span and NOT adjacent. - if (currentSpan.next() == null) - { - // The new span is the final span. - // Insert it above the current span. - currentSpan.setNext(new HeightSpan(heightIndexMin - , heightIndexMax - , flags)); - return true; - } - // Continue searching up the span's in this column. - previousSpan = currentSpan; - currentSpan = currentSpan.next(); - } - else - { - /* - * There is either overlap or adjacency between the current - * span and the new span. - * Need to perform a merge of some type. - * Will always return after the merge is complete. - * Get easy stuff out of the way first. - */ - if (heightIndexMin < currentSpan.min()) - // This span will result in a new minimum for the current - // span. Adjust the current span's minimum. - currentSpan.setMin(heightIndexMin); - if (heightIndexMax == currentSpan.max()) - { - // The new span ends at same height as current span. - // Merge flags. - currentSpan.setFlags((byte)(currentSpan.flags() | flags)); - return true; - } - if (currentSpan.max() > heightIndexMax) - // The top of the current span is higher than the new span. - // So discard the new span's flag. - return true; - // The new spans's maximum height is higher than the current - // span's maximum height. - // Need to search up the spans to find where the merge ends. - HeightSpan nextSpan = currentSpan.next(); - while (true) - { - if (nextSpan == null || nextSpan.min() > heightIndexMax + 1) - { - /* - * There are no spans above the current span, or the - * height increase caused by this span will not touch - * the next span. Can just expand the current span - * upward. - */ - currentSpan.setMax(heightIndexMax); - // New span is new "top", so its flags replace current - // span's flags. - currentSpan.setFlags(flags); - if (nextSpan == null) - // The current span is at the top of the column. - // Get rid of any links it may have had. - currentSpan.setNext(null); - else - // Take care of re-pointing. (Some spans may have - // been encompassed.) - currentSpan.setNext(nextSpan); - // Finished. - return true; - } - // The new height of the current span will touch the next - // span in some manner. Merging is needed. - if (nextSpan.min() == heightIndexMax + 1 - || heightIndexMax <= nextSpan.max()) - { - // No gap between current and next spans, but no - // overlap with next span. (Spans abut each other.) - // Encompass the next span. - currentSpan.setMax(nextSpan.max()); - // Set the current span to point the the encompassed - // span's next span. - currentSpan.setNext(nextSpan.next()); - // Take the flags of the next span since we know the - // next span's max is higher than the current span. - currentSpan.setFlags(nextSpan.flags()); - if (heightIndexMax == currentSpan.max()) - { - // New span ends at same height as merged span. - // Merge flags. - currentSpan.setFlags(currentSpan.flags() | flags); - return true; - } - return true; - } - // The current span overlaps with the next span. - // Need to continue up the column to see if the next span - // will be fully engulfed. - nextSpan = nextSpan.next(); - } - } - } - - // Will only ever get here if there is a code logic error. - return false; - - } - - /** - * Provides an iterator that iterates all spans in the field. - *

      Unlike {@link #getData(int, int)}, this iterator will iterate - * through all spans, not just the base spans. So their is no need to - * use {@link HeightSpan#next()} to climb the span structure.

      - */ - public SolidHeightFieldIterator dataIterator() - { - return this.new SolidHeightFieldIterator(); - } - - /** - * Gets the lowest span at the grid location, or null if there are no - * spans at the location. - *

      The data will be the lowest span at the grid location.

      - * @return The lowest span at the grid location. - */ - public HeightSpan getData(int widthIndex, int depthIndex) - { - return mSpans.get(gridIndex(widthIndex, depthIndex)); - } - - /** - * Indicates whether or not the field contains any spans. If FALSE is - * returned, then the field does not contain any obstructed space. - * @return TRUE if the field contains spans. Otherwise FALSE. - */ - public boolean hasSpans() { return (mSpans.size() > 0); } - -} diff --git a/critterai/.svn/pristine/a2/a2884ad1b6c6d5176be1c56387475706de3ab284.svn-base b/critterai/.svn/pristine/a2/a2884ad1b6c6d5176be1c56387475706de3ab284.svn-base deleted file mode 100644 index 88b36664..00000000 --- a/critterai/.svn/pristine/a2/a2884ad1b6c6d5176be1c56387475706de3ab284.svn-base +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * A utility class which holds meta data related to building regions. - */ -final class Region -{ - /** - * The region ID. - */ - public int id = 0; - - /** - * The number of spans in this region. - */ - public int spanCount = 0; - - /** - * Used to indicate whether or not a re-mapping of the region ID is - * required. - */ - public boolean remap = false; - - /** - * Represents an ordered list of connections between this and other regions. - * All properly initialized regions will have at least one connection, - * even if that connection is only to the null region. - *

      The start point, end point, and direction of the ordering is - * arbitrary. If the current region connects at multiple non-adjacent - * points t another region, then the list will contain multiple references. - * One entry for each non-adjacent connection point.

      - *

      Example: 1, 5, 8, 1, 2 -> This region connects to region 1 at - * two points.

      - *

      The reason that multiple connection information is stored is that - * it can be used to indicate whether two regions, if combined, would - * result in a polygon with internal space, which is an invalid state.

      - */ - public final ArrayList connections = new ArrayList(); - - /** - * A list of non-null regions that overlap this region. - *

      An overlap is considered to have occurred - * if a span in this region is below a span belonging to another region.

      - *

      Note that if two spans in the same grid cell are in the same region, - * then the region will show as overlapping itself.

      - */ - public final ArrayList overlappingRegions = - new ArrayList(); - - /** - * Constructor - * @param id The initial ID of the region. - */ - public Region(int id) - { - this.id = id; - } - - /** - * Reinitializes (clears) all instance fields and sets the id to a - * new value. - * @param newRegionID The new region ID. - */ - public void resetWithID(int newRegionID) - { - id = newRegionID; - spanCount = 0; - connections.clear(); - overlappingRegions.clear(); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() - { - return "id: " + id + ", spans: " + spanCount - + ", connections: " + connections + ", overlaps: " - + overlappingRegions; - } - -} diff --git a/critterai/.svn/pristine/a2/a2d95e6e18f73688d6555d0007dd1def0d673d2e.svn-base b/critterai/.svn/pristine/a2/a2d95e6e18f73688d6555d0007dd1def0d673d2e.svn-base deleted file mode 100644 index 68b8a483..00000000 Binary files a/critterai/.svn/pristine/a2/a2d95e6e18f73688d6555d0007dd1def0d673d2e.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/a2/a2e0796020efcd68d088c51ac86c2708f7d2fc5c.svn-base b/critterai/.svn/pristine/a2/a2e0796020efcd68d088c51ac86c2708f7d2fc5c.svn-base deleted file mode 100644 index f305669b..00000000 --- a/critterai/.svn/pristine/a2/a2e0796020efcd68d088c51ac86c2708f7d2fc5c.svn-base +++ /dev/null @@ -1,71 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336} - Library - Properties - org.critterai - cai-nmbuild - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG;NUNITY - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE;NUNITY - prompt - 4 - ..\bin\Release\cai-nmbuild.XML - - - - - 3.5 - - - - - - processors\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - {42218E47-156D-46ff-84E0-119D47B0E4EB} - cai-nav - - - {9DFC1FE0-6469-4a04-AB13-9EAC59087802} - cai-nmgen - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/a3/a35159a0d0d01783e3313b7ecc4fea1dc73e9a88.svn-base b/critterai/.svn/pristine/a3/a35159a0d0d01783e3313b7ecc4fea1dc73e9a88.svn-base deleted file mode 100644 index 4104f2f3..00000000 --- a/critterai/.svn/pristine/a3/a35159a0d0d01783e3313b7ecc4fea1dc73e9a88.svn-base +++ /dev/null @@ -1,5 +0,0 @@ -Add the following plugins to this directory if you are using it as the basis for -a Unity project: - -cai-nav-rcn.dll -cai-nmgen-rcn.dll diff --git a/critterai/.svn/pristine/a5/a55546db341702fdc4e5edd117f0e0b9bb7fba6c.svn-base b/critterai/.svn/pristine/a5/a55546db341702fdc4e5edd117f0e0b9bb7fba6c.svn-base deleted file mode 100644 index 1723e3c7..00000000 --- a/critterai/.svn/pristine/a5/a55546db341702fdc4e5edd117f0e0b9bb7fba6c.svn-base +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -/** - * Provides various math related utility operations. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, no divide by zero checks, etc.

      - *

      Static operations are thread safe.

      - */ -public class MathUtil -{ - - /** - * A standard epsilon value. (Minimum positive value greater than zero.) - */ - public static final float EPSILON_STD = 0.00001f; - - /** - * A standard tolerance value. - */ - public static final float TOLERANCE_STD = 0.0001f; - - private MathUtil() { } - - /** - * Determines whether the values are within the specified tolerance - * of each other. - *

      The values are considered equal if the following condition is met: - * (b >= a - tolerance && b <= a + tolerance)

      - * @param a The a-value to compare the b-value against. - * @param b The b-value to compare against the a-value. - * @param tolerence The tolerance to use for the comparison. - * @return TRUE if the values are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float a, float b, float tolerence) - { - return !(b < a - tolerence || b > a + tolerence); - } - - /** - * Clamps the value to a positive non-zero value. - * @param value The value to clamp. - * @return The value clamped to a minimum of {@link Float#MIN_VALUE}. - */ - public static float clampToPositiveNonZero(float value) - { - return Math.max(Float.MIN_VALUE, value); - } - - /** - * Clamps the value to the specified range. The clamp is inclusive - * such that minimum <= result <= maximum. - * @param value The value to clamp. - * @param minimum The minimum allowed value. - * @param maximum The maximum allowed value. - * @return A value clamped to the specified range. - */ - public static float clamp(float value, float minimum, float maximum) - { - return (value < minimum ? minimum : (value > maximum ? maximum : value)); - } - - /** - * Clamps the value to the specified range. The clamp is inclusive - * such that minimum <= result <= maximum. - * @param value The value to clamp. - * @param minimum The minimum allowed value. - * @param maximum The maximum allowed value. - * @return A value clamped to the specified range. - */ - public static int clamp(int value, int minimum, int maximum) - { - return (value < minimum ? minimum : (value > maximum ? maximum : value)); - } - - /** - * Clamps the value to the specified range. The clamp is inclusive - * such that minimum <= result <= maximum. - * @param value The value to clamp. - * @param minimum The minimum allowed value. - * @param maximum The maximum allowed value. - * @return A value clamped to the specified range. - */ - public static short clamp(short value, short minimum, short maximum) - { - return (value < minimum ? minimum : (value > maximum ? maximum : value)); - } - - /** - * Returns the maximum value in the list of values. - * @param values The values to search. - * @return The maximum value in the list of values. - */ - public static float max(float ...values) - { - float result = values[0]; - for (int i = 1; i < values.length; i++) - result = Math.max(result, values[i]); - return result; - } - - /** - * Returns the minimum value in the list of values. - * @param values The values to search. - * @return The minimum value in the list of values. - */ - public static float min(float ...values) - { - float result = values[0]; - for (int i = 1; i < values.length; i++) - result = Math.min(result, values[i]); - return result; - } - -} diff --git a/critterai/.svn/pristine/a5/a5aab8e9278cd8e1e4d21fd0333f3ef3205e29fe.svn-base b/critterai/.svn/pristine/a5/a5aab8e9278cd8e1e4d21fd0333f3ef3205e29fe.svn-base deleted file mode 100644 index 12f36a4f..00000000 --- a/critterai/.svn/pristine/a5/a5aab8e9278cd8e1e4d21fd0333f3ef3205e29fe.svn-base +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; -using org.critterai.nav; -using System.Collections.Generic; - -namespace org.critterai.nmbuild -{ - /// - /// A standard build task that provides data upon completion. - /// - /// - /// - /// The task is single use. The task is constructed, run, then its data and messages retrieved. - /// - /// - /// The type of data provided upon completion. - public abstract class BuildTask - : IBuildTask - { - // Design note: Everything is locked on the messages list. - - private T mData; - - private BuildTaskState mState; - private bool mIsFinished = false; - private readonly int mPriority; - - private readonly List mMessages = new List(); - - /// - /// Constructor. - /// - /// The priority of the task. - public BuildTask(int priority) - { - mPriority = priority; - } - - /// - /// The priority of the item. - /// - /// - /// This value is immutable. - /// - public int Priority { get { return mPriority; } } - - /// - /// If true, the task can be safely run on a separate thread from the object(s) monitoring - /// its state. - /// - /// - /// This value of immutable. - /// - public abstract bool IsThreadSafe { get; } - - /// - /// Performs a work increment. - /// - /// - /// - /// This method will be 'reasonably' responsive. It should block its thread - /// for the minimum possible amount of time. - /// - /// - /// Called in a loop by the method until the task is finished. - /// - /// - /// Not guarenteed to be called. (I.e. Will not be called if the task is aborted - /// before the task is run.) - /// - /// - /// True if the task is not yet finished. Otherwise false. - protected abstract bool LocalUpdate(); - - /// - /// Gets the result of the completed task. - /// - /// - /// - /// Called by after the task completes and before - /// is run. Will not be called on tasks in the aborted state. - /// - /// - /// The result of the completed task. - /// - /// True if the result is available, false if the task should abort with no result. - /// (I.e. An internal abort.) - /// - protected abstract bool GetResult(out T result); - - /// - /// Finalize the task. - /// - /// - /// - /// Used for task cleanup. Will be called before the method exits, - /// even on an exception. Must never throw an exception. - /// - /// - protected virtual void FinalizeTask() { } - - /// - /// Adds a message to the message queue. - /// - /// The message to add. - protected void AddMessage(string messsage) - { - lock (mMessages) - mMessages.Add(messsage); - } - /// - /// Appends an array of messages to the message queue. - /// - /// The messages to append. - protected void AddMessages(string[] messages) - { - lock (mMessages) - mMessages.AddRange(messages); - } - - /// - /// The current state of the task. - /// - public BuildTaskState TaskState { get { lock (mMessages) return mState; } } - - /// - /// The task is in a finished state. - /// - public bool IsFinished { get { return mIsFinished; } } - - /// - /// Messages available after the task is finished. - /// - /// - /// - /// Will return a zero length array if the task is not finished or there are - /// no messages. Will always provide a message on abort. - /// - /// - public string[] Messages { get { lock (mMessages) return mMessages.ToArray(); } } - - /// - /// The data produced by the task. - /// - /// - /// - /// Will only contain useable data when the task is finished with a state of - /// . - /// - /// - public T Result { get { return mData; } } - - /// - /// Runs the task through to a finished state. - /// - /// - /// - /// Never call this method more than once. - /// - /// - /// If is true, this method can be run on a separate - /// thread from the object(s) that are monitoring the task state. - /// - /// - public void Run() - { - lock (mMessages) - { - if (mState != BuildTaskState.Inactive) - return; - - mState = BuildTaskState.InProgress; - } - - try - { - while (LocalUpdate()) - { - lock (mMessages) - { - if (mState == BuildTaskState.Aborting) - break; - } - } - FinalizeRequest(); - } - catch (System.Exception ex) - { - FinalizeRequest(ex); - } - finally - { - FinalizeTask(); - } - } - - /// - /// Requests an abort of the task. - /// - /// - /// - /// There may be a delay in the actual abort for tasks running on a separate thread. - /// - /// - /// The reason for the abort. - public void Abort(string reason) - { - lock (mMessages) - { - if (mIsFinished) - return; - - AddMessage(reason); - - if (mState == BuildTaskState.Inactive) - { - mState = BuildTaskState.Aborting; - FinalizeRequest(); - } - else - mState = BuildTaskState.Aborting; - } - } - - private void FinalizeRequest() - { - lock (mMessages) - { - if (mState == BuildTaskState.Aborting) - { - // Don't care if the task actually finished. - // An abort takes presidence. - mState = BuildTaskState.Aborted; - mData = default(T); - } - else - { - try - { - mState = GetResult(out mData) ? BuildTaskState.Complete : BuildTaskState.Aborted; - } - catch (System.Exception ex) - { - FinalizeRequest(ex); - } - } - - mIsFinished = true; // Always last. - } - } - - private void FinalizeRequest(System.Exception ex) - { - lock (mMessages) - { - mMessages.Add(string.Format("Build task aborted on exception: {0} ({1})" - , ex.Message, this.GetType().Name)); - mData = default(T); - mState = BuildTaskState.Aborted; - mIsFinished = true; - } - } - } -} diff --git a/critterai/.svn/pristine/a5/a5e754e77b9780a258b8130351876e6f557c362e.svn-base b/critterai/.svn/pristine/a5/a5e754e77b9780a258b8130351876e6f557c362e.svn-base deleted file mode 100644 index cb9b59e0..00000000 --- a/critterai/.svn/pristine/a5/a5e754e77b9780a258b8130351876e6f557c362e.svn-base +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// The state of the input build. (Editor Only) - /// - public enum InputBuildState - { - /// - /// Component's are being loaded. - /// - LoadComponents, - - /// - /// Component's are being filtered. - /// - FilterComponents, - - /// - /// Area modifiers are being applied to the components. - /// - ApplyAreaModifiers, - - /// - /// Components are being compiled into geometry, connections, and NMGen processors. - /// - CompileInput, - - /// - /// Input post-processing is occurring. - /// - PostProcess, - - /// - /// The input build aborted. (A finished state.) - /// - Aborted, - - /// - /// The input build is complete. (A finished state.) - /// - Complete - } -} diff --git a/critterai/.svn/pristine/a6/a6ca7a067842340084476c43fcaf9b7d824f6ea7.svn-base b/critterai/.svn/pristine/a6/a6ca7a067842340084476c43fcaf9b7d824f6ea7.svn-base deleted file mode 100644 index 79d43220..00000000 --- a/critterai/.svn/pristine/a6/a6ca7a067842340084476c43fcaf9b7d824f6ea7.svn-base +++ /dev/null @@ -1,137 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include "DetourLocalBoundary.h" -#include "DetourNavMeshQuery.h" -#include "DetourCommon.h" -#include "DetourAssert.h" - - -dtLocalBoundary::dtLocalBoundary() : - m_nsegs(0), - m_npolys(0) -{ - dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX); -} - -dtLocalBoundary::~dtLocalBoundary() -{ -} - -void dtLocalBoundary::reset() -{ - dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX); - m_npolys = 0; - m_nsegs = 0; -} - -void dtLocalBoundary::addSegment(const float dist, const float* s) -{ - // Insert neighbour based on the distance. - Segment* seg = 0; - if (!m_nsegs) - { - // First, trivial accept. - seg = &m_segs[0]; - } - else if (dist >= m_segs[m_nsegs-1].d) - { - // Further than the last segment, skip. - if (m_nsegs >= MAX_LOCAL_SEGS) - return; - // Last, trivial accept. - seg = &m_segs[m_nsegs]; - } - else - { - // Insert inbetween. - int i; - for (i = 0; i < m_nsegs; ++i) - if (dist <= m_segs[i].d) - break; - const int tgt = i+1; - const int n = dtMin(m_nsegs-i, MAX_LOCAL_SEGS-tgt); - dtAssert(tgt+n <= MAX_LOCAL_SEGS); - if (n > 0) - memmove(&m_segs[tgt], &m_segs[i], sizeof(Segment)*n); - seg = &m_segs[i]; - } - - seg->d = dist; - memcpy(seg->s, s, sizeof(float)*6); - - if (m_nsegs < MAX_LOCAL_SEGS) - m_nsegs++; -} - -void dtLocalBoundary::update(dtPolyRef ref, const float* pos, const float collisionQueryRange, - dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - static const int MAX_SEGS_PER_POLY = DT_VERTS_PER_POLYGON*3; - - if (!ref) - { - dtVset(m_center, FLT_MAX,FLT_MAX,FLT_MAX); - m_nsegs = 0; - m_npolys = 0; - return; - } - - dtVcopy(m_center, pos); - - // First query non-overlapping polygons. - navquery->findLocalNeighbourhood(ref, pos, collisionQueryRange, - filter, m_polys, 0, &m_npolys, MAX_LOCAL_POLYS); - - // Secondly, store all polygon edges. - m_nsegs = 0; - float segs[MAX_SEGS_PER_POLY*6]; - int nsegs = 0; - for (int j = 0; j < m_npolys; ++j) - { - navquery->getPolyWallSegments(m_polys[j], filter, segs, 0, &nsegs, MAX_SEGS_PER_POLY); - for (int k = 0; k < nsegs; ++k) - { - const float* s = &segs[k*6]; - // Skip too distant segments. - float tseg; - const float distSqr = dtDistancePtSegSqr2D(pos, s, s+3, tseg); - if (distSqr > dtSqr(collisionQueryRange)) - continue; - addSegment(distSqr, s); - } - } -} - -bool dtLocalBoundary::isValid(dtNavMeshQuery* navquery, const dtQueryFilter* filter) -{ - if (!m_npolys) - return false; - - // Check that all polygons still pass query filter. - for (int i = 0; i < m_npolys; ++i) - { - if (!navquery->isValidPolyRef(m_polys[i], filter)) - return false; - } - - return true; -} - diff --git a/critterai/.svn/pristine/a8/a898dd8c08b6eee067757503a40d6672e6e0f7da.svn-base b/critterai/.svn/pristine/a8/a898dd8c08b6eee067757503a40d6672e6e0f7da.svn-base deleted file mode 100644 index d0465b3d..00000000 --- a/critterai/.svn/pristine/a8/a898dd8c08b6eee067757503a40d6672e6e0f7da.svn-base +++ /dev/null @@ -1,524 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" - -/// @par -/// -/// Basically, any spans that are closer to a boundary or obstruction than the specified radius -/// are marked as unwalkable. -/// -/// This method is usually called immediately after the heightfield has been built. -/// -/// @see rcCompactHeightfield, rcBuildCompactHeightfield, rcConfig::walkableRadius -bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf) -{ - rcAssert(ctx); - - const int w = chf.width; - const int h = chf.height; - - ctx->startTimer(RC_TIMER_ERODE_AREA); - - unsigned char* dist = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); - if (!dist) - { - ctx->log(RC_LOG_ERROR, "erodeWalkableArea: Out of memory 'dist' (%d).", chf.spanCount); - return false; - } - - // Init distance. - memset(dist, 0xff, sizeof(unsigned char)*chf.spanCount); - - // Mark boundary cells. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - if (chf.areas[i] == RC_NULL_AREA) - { - dist[i] = 0; - } - else - { - const rcCompactSpan& s = chf.spans[i]; - int nc = 0; - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int nx = x + rcGetDirOffsetX(dir); - const int ny = y + rcGetDirOffsetY(dir); - const int nidx = (int)chf.cells[nx+ny*w].index + rcGetCon(s, dir); - if (chf.areas[nidx] != RC_NULL_AREA) - { - nc++; - } - } - } - // At least one missing neighbour. - if (nc != 4) - dist[i] = 0; - } - } - } - } - - unsigned char nd; - - // Pass 1 - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - - if (rcGetCon(s, 0) != RC_NOT_CONNECTED) - { - // (-1,0) - const int ax = x + rcGetDirOffsetX(0); - const int ay = y + rcGetDirOffsetY(0); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0); - const rcCompactSpan& as = chf.spans[ai]; - nd = (unsigned char)rcMin((int)dist[ai]+2, 255); - if (nd < dist[i]) - dist[i] = nd; - - // (-1,-1) - if (rcGetCon(as, 3) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(3); - const int aay = ay + rcGetDirOffsetY(3); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 3); - nd = (unsigned char)rcMin((int)dist[aai]+3, 255); - if (nd < dist[i]) - dist[i] = nd; - } - } - if (rcGetCon(s, 3) != RC_NOT_CONNECTED) - { - // (0,-1) - const int ax = x + rcGetDirOffsetX(3); - const int ay = y + rcGetDirOffsetY(3); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3); - const rcCompactSpan& as = chf.spans[ai]; - nd = (unsigned char)rcMin((int)dist[ai]+2, 255); - if (nd < dist[i]) - dist[i] = nd; - - // (1,-1) - if (rcGetCon(as, 2) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(2); - const int aay = ay + rcGetDirOffsetY(2); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 2); - nd = (unsigned char)rcMin((int)dist[aai]+3, 255); - if (nd < dist[i]) - dist[i] = nd; - } - } - } - } - } - - // Pass 2 - for (int y = h-1; y >= 0; --y) - { - for (int x = w-1; x >= 0; --x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - - if (rcGetCon(s, 2) != RC_NOT_CONNECTED) - { - // (1,0) - const int ax = x + rcGetDirOffsetX(2); - const int ay = y + rcGetDirOffsetY(2); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 2); - const rcCompactSpan& as = chf.spans[ai]; - nd = (unsigned char)rcMin((int)dist[ai]+2, 255); - if (nd < dist[i]) - dist[i] = nd; - - // (1,1) - if (rcGetCon(as, 1) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(1); - const int aay = ay + rcGetDirOffsetY(1); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 1); - nd = (unsigned char)rcMin((int)dist[aai]+3, 255); - if (nd < dist[i]) - dist[i] = nd; - } - } - if (rcGetCon(s, 1) != RC_NOT_CONNECTED) - { - // (0,1) - const int ax = x + rcGetDirOffsetX(1); - const int ay = y + rcGetDirOffsetY(1); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 1); - const rcCompactSpan& as = chf.spans[ai]; - nd = (unsigned char)rcMin((int)dist[ai]+2, 255); - if (nd < dist[i]) - dist[i] = nd; - - // (-1,1) - if (rcGetCon(as, 0) != RC_NOT_CONNECTED) - { - const int aax = ax + rcGetDirOffsetX(0); - const int aay = ay + rcGetDirOffsetY(0); - const int aai = (int)chf.cells[aax+aay*w].index + rcGetCon(as, 0); - nd = (unsigned char)rcMin((int)dist[aai]+3, 255); - if (nd < dist[i]) - dist[i] = nd; - } - } - } - } - } - - const unsigned char thr = (unsigned char)(radius*2); - for (int i = 0; i < chf.spanCount; ++i) - if (dist[i] < thr) - chf.areas[i] = RC_NULL_AREA; - - rcFree(dist); - - ctx->stopTimer(RC_TIMER_ERODE_AREA); - - return true; -} - -static void insertSort(unsigned char* a, const int n) -{ - int i, j; - for (i = 1; i < n; i++) - { - const unsigned char value = a[i]; - for (j = i - 1; j >= 0 && a[j] > value; j--) - a[j+1] = a[j]; - a[j+1] = value; - } -} - -/// @par -/// -/// This filter is usually applied after applying area id's using functions -/// such as #rcMarkBoxArea, #rcMarkConvexPolyArea, and #rcMarkCylinderArea. -/// -/// @see rcCompactHeightfield -bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf) -{ - rcAssert(ctx); - - const int w = chf.width; - const int h = chf.height; - - ctx->startTimer(RC_TIMER_MEDIAN_AREA); - - unsigned char* areas = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); - if (!areas) - { - ctx->log(RC_LOG_ERROR, "medianFilterWalkableArea: Out of memory 'areas' (%d).", chf.spanCount); - return false; - } - - // Init distance. - memset(areas, 0xff, sizeof(unsigned char)*chf.spanCount); - - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - if (chf.areas[i] == RC_NULL_AREA) - { - areas[i] = chf.areas[i]; - continue; - } - - unsigned char nei[9]; - for (int j = 0; j < 9; ++j) - nei[j] = chf.areas[i]; - - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); - if (chf.areas[ai] != RC_NULL_AREA) - nei[dir*2+0] = chf.areas[ai]; - - const rcCompactSpan& as = chf.spans[ai]; - const int dir2 = (dir+1) & 0x3; - if (rcGetCon(as, dir2) != RC_NOT_CONNECTED) - { - const int ax2 = ax + rcGetDirOffsetX(dir2); - const int ay2 = ay + rcGetDirOffsetY(dir2); - const int ai2 = (int)chf.cells[ax2+ay2*w].index + rcGetCon(as, dir2); - if (chf.areas[ai2] != RC_NULL_AREA) - nei[dir*2+1] = chf.areas[ai2]; - } - } - } - insertSort(nei, 9); - areas[i] = nei[4]; - } - } - } - - memcpy(chf.areas, areas, sizeof(unsigned char)*chf.spanCount); - - rcFree(areas); - - ctx->stopTimer(RC_TIMER_MEDIAN_AREA); - - return true; -} - -/// @par -/// -/// The value of spacial parameters are in world units. -/// -/// @see rcCompactHeightfield, rcMedianFilterWalkableArea -void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, - rcCompactHeightfield& chf) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_MARK_BOX_AREA); - - int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); - int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); - int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs); - int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs); - int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch); - int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs); - - if (maxx < 0) return; - if (minx >= chf.width) return; - if (maxz < 0) return; - if (minz >= chf.height) return; - - if (minx < 0) minx = 0; - if (maxx >= chf.width) maxx = chf.width-1; - if (minz < 0) minz = 0; - if (maxz >= chf.height) maxz = chf.height-1; - - for (int z = minz; z <= maxz; ++z) - { - for (int x = minx; x <= maxx; ++x) - { - const rcCompactCell& c = chf.cells[x+z*chf.width]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - rcCompactSpan& s = chf.spans[i]; - if ((int)s.y >= miny && (int)s.y <= maxy) - { - if (chf.areas[i] != RC_NULL_AREA) - chf.areas[i] = areaId; - } - } - } - } - - ctx->stopTimer(RC_TIMER_MARK_BOX_AREA); - -} - - -static int pointInPoly(int nvert, const float* verts, const float* p) -{ - int i, j, c = 0; - for (i = 0, j = nvert-1; i < nvert; j = i++) - { - const float* vi = &verts[i*3]; - const float* vj = &verts[j*3]; - if (((vi[2] > p[2]) != (vj[2] > p[2])) && - (p[0] < (vj[0]-vi[0]) * (p[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) ) - c = !c; - } - return c; -} - -/// @par -/// -/// The value of spacial parameters are in world units. -/// -/// The y-values of the polygon vertices are ignored. So the polygon is effectively -/// projected onto the xz-plane at @p hmin, then extruded to @p hmax. -/// -/// @see rcCompactHeightfield, rcMedianFilterWalkableArea -void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, - const float hmin, const float hmax, unsigned char areaId, - rcCompactHeightfield& chf) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); - - float bmin[3], bmax[3]; - rcVcopy(bmin, verts); - rcVcopy(bmax, verts); - for (int i = 1; i < nverts; ++i) - { - rcVmin(bmin, &verts[i*3]); - rcVmax(bmax, &verts[i*3]); - } - bmin[1] = hmin; - bmax[1] = hmax; - - int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); - int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); - int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs); - int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs); - int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch); - int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs); - - if (maxx < 0) return; - if (minx >= chf.width) return; - if (maxz < 0) return; - if (minz >= chf.height) return; - - if (minx < 0) minx = 0; - if (maxx >= chf.width) maxx = chf.width-1; - if (minz < 0) minz = 0; - if (maxz >= chf.height) maxz = chf.height-1; - - - // TODO: Optimize. - for (int z = minz; z <= maxz; ++z) - { - for (int x = minx; x <= maxx; ++x) - { - const rcCompactCell& c = chf.cells[x+z*chf.width]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - rcCompactSpan& s = chf.spans[i]; - if (chf.areas[i] == RC_NULL_AREA) - continue; - if ((int)s.y >= miny && (int)s.y <= maxy) - { - float p[3]; - p[0] = chf.bmin[0] + (x+0.5f)*chf.cs; - p[1] = 0; - p[2] = chf.bmin[2] + (z+0.5f)*chf.cs; - - if (pointInPoly(nverts, verts, p)) - { - chf.areas[i] = areaId; - } - } - } - } - } - - ctx->stopTimer(RC_TIMER_MARK_CONVEXPOLY_AREA); -} - -/// @par -/// -/// The value of spacial parameters are in world units. -/// -/// @see rcCompactHeightfield, rcMedianFilterWalkableArea -void rcMarkCylinderArea(rcContext* ctx, const float* pos, - const float r, const float h, unsigned char areaId, - rcCompactHeightfield& chf) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_MARK_CYLINDER_AREA); - - float bmin[3], bmax[3]; - bmin[0] = pos[0] - r; - bmin[1] = pos[1]; - bmin[2] = pos[2] - r; - bmax[0] = pos[0] + r; - bmax[1] = pos[1] + h; - bmax[2] = pos[2] + r; - const float r2 = r*r; - - int minx = (int)((bmin[0]-chf.bmin[0])/chf.cs); - int miny = (int)((bmin[1]-chf.bmin[1])/chf.ch); - int minz = (int)((bmin[2]-chf.bmin[2])/chf.cs); - int maxx = (int)((bmax[0]-chf.bmin[0])/chf.cs); - int maxy = (int)((bmax[1]-chf.bmin[1])/chf.ch); - int maxz = (int)((bmax[2]-chf.bmin[2])/chf.cs); - - if (maxx < 0) return; - if (minx >= chf.width) return; - if (maxz < 0) return; - if (minz >= chf.height) return; - - if (minx < 0) minx = 0; - if (maxx >= chf.width) maxx = chf.width-1; - if (minz < 0) minz = 0; - if (maxz >= chf.height) maxz = chf.height-1; - - - for (int z = minz; z <= maxz; ++z) - { - for (int x = minx; x <= maxx; ++x) - { - const rcCompactCell& c = chf.cells[x+z*chf.width]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - rcCompactSpan& s = chf.spans[i]; - - if (chf.areas[i] == RC_NULL_AREA) - continue; - - if ((int)s.y >= miny && (int)s.y <= maxy) - { - const float sx = chf.bmin[0] + (x+0.5f)*chf.cs; - const float sz = chf.bmin[2] + (z+0.5f)*chf.cs; - const float dx = sx - pos[0]; - const float dz = sz - pos[2]; - - if (dx*dx + dz*dz < r2) - { - chf.areas[i] = areaId; - } - } - } - } - } - - ctx->stopTimer(RC_TIMER_MARK_CYLINDER_AREA); -} diff --git a/critterai/.svn/pristine/aa/aafebeecded1d53a5d08b2fcbe1ad74970ed74bd.svn-base b/critterai/.svn/pristine/aa/aafebeecded1d53a5d08b2fcbe1ad74970ed74bd.svn-base deleted file mode 100644 index cc4f141d..00000000 --- a/critterai/.svn/pristine/aa/aafebeecded1d53a5d08b2fcbe1ad74970ed74bd.svn-base +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.geom -{ - /// - /// Specifies the position relationship between a point and a line. - /// - public enum PointLineRelType : byte - { - /// - /// The reference point is on, or very near, the line - /// - OnLine, - - /// - /// The reference point is to the left when looking from point A toward point B along - /// the line. - /// - LeftSide, - - /// - /// The reference point is to the right when looking from point A toward point B along - /// the line. - /// - RightSide - } -} diff --git a/critterai/.svn/pristine/ac/ac624785fc0551e148f4d79c338bee23ae6de4cc.svn-base b/critterai/.svn/pristine/ac/ac624785fc0551e148f4d79c338bee23ae6de4cc.svn-base deleted file mode 100644 index ebe58579..00000000 --- a/critterai/.svn/pristine/ac/ac624785fc0551e148f4d79c338bee23ae6de4cc.svn-base +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; -using org.critterai.nav; - -namespace org.critterai.nmbuild -{ - /// - /// A task used to manage the build of an object. - /// - /// - /// - /// The primary purpose of this class is to run the builder on a background thread. - /// It handles aborts and exception handling, which are not possible if the - /// builder is run directly on a thread. - /// - /// - public sealed class NMGenTask - : BuildTask - { - private readonly IncrementalBuilder mBuilder; - - private NMGenTask(IncrementalBuilder builder, int priority) - : base(priority) - { - mBuilder = builder; - } - - /// - /// If true, the task is safe to run on its own thread. - /// - /// - /// - /// Will be true if the root builder is thread-safe. - /// - /// - public override bool IsThreadSafe { get { return mBuilder.IsThreadSafe; } } - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int TileX { get { return mBuilder.TileX; } } - - /// - /// The z-index of the tile within the tile grid. (x, z) - /// - public int TileZ { get { return mBuilder.TileZ; } } - - /// - /// Creates a new task. - /// - /// The builder to manage. - /// The task priority. - /// A task, or null on error. - public static NMGenTask Create(IncrementalBuilder builder, int priority) - { - if (builder == null || builder.IsFinished) - return null; - - return new NMGenTask(builder, priority); - } - - /// - /// Performs a work increment. - /// - /// True if the task is not yet finished. Otherwise false. - protected override bool LocalUpdate() - { - mBuilder.Build(); - return !mBuilder.IsFinished; // Go to false when IsFinished. - } - - /// - /// Gets the result of the completed task. - /// - /// The result of the completed task. - /// - /// True if the result is available, false if the task should abort with no result. - /// (I.e. An internal abort.) - /// - protected override bool GetResult(out NMGenAssets result) - { - AddMessages(mBuilder.GetMessages()); - - switch (mBuilder.State) - { - case NMGenState.Complete: - - result = mBuilder.Result; - return true; - - case NMGenState.NoResult: - - result = new NMGenAssets(mBuilder.TileX, mBuilder.TileZ, null, null); - return true; - - default: - - result = new NMGenAssets(); - return false; - } - } - } -} diff --git a/critterai/.svn/pristine/ad/adc34e8dfa78a3add7cb52e78b6d7fef606c0097.svn-base b/critterai/.svn/pristine/ad/adc34e8dfa78a3add7cb52e78b6d7fef606c0097.svn-base deleted file mode 100644 index 85669538..00000000 --- a/critterai/.svn/pristine/ad/adc34e8dfa78a3add7cb52e78b6d7fef606c0097.svn-base +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// Applies to a . - /// - /// - /// - /// This is a system processor. - /// - /// - public sealed class FilterLedgeSpans - : NMGenProcessor - { - internal const int ProcessorPriority = LowObstaclesWalkable.ProcessorPriority + 5; - - private static FilterLedgeSpans mInstance = new FilterLedgeSpans(); - - - private FilterLedgeSpans() - : base(typeof(FilterLedgeSpans).Name, ProcessorPriority) - { - } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// Will be applied during the state. - /// - /// - /// The current build state. - /// The context to process. - /// False on error, otherwise true. - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - if (state != NMGenState.HeightfieldBuild) - return true; - - if (context.Heightfield.MarkLedgeSpansNotWalkable(context - , context.Config.WalkableHeight - , context.Config.WalkableStep)) - { - context.Log(Name + ": Marked ledge spans as not walklable.", this); - return true; - } - - context.Log(Name + ": Mark ledge spans failed.", this); - return false; - } - - /// - /// The processor instance. - /// - public static FilterLedgeSpans Instance { get { return mInstance; } } - } -} diff --git a/critterai/.svn/pristine/ae/aea5aee9572f0a4d4e552836a863befc58e68d17.svn-base b/critterai/.svn/pristine/ae/aea5aee9572f0a4d4e552836a863befc58e68d17.svn-base deleted file mode 100644 index e20915f3..00000000 --- a/critterai/.svn/pristine/ae/aea5aee9572f0a4d4e552836a863befc58e68d17.svn-base +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Provides high level information related to a object. - /// - [StructLayout(LayoutKind.Sequential)] - public struct NavmeshTileHeader - { - /// - /// The tile magic number. (Undocumented.) - /// - public int magic; - - /// - /// The tile version. (Undocumented.) - /// - public int version; - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int tileX; - - /// - /// The z-index of the tile within the tile grid. (x, z) - /// - public int tileZ; - - /// - /// The layer of the tile. - /// - /// - /// Layering occurs on the y-axis. (Height) - /// - public int layer; - - /// - /// The user-defined id of the tile. - /// - public uint userId; - - /// - /// The number of polygons in the tile. - /// - public int polyCount; - - /// - /// The number of polygon vertices in the tile. - /// - public int vertCount; - - /// - /// The number of links allocated. - /// - public int maxLinkCount; - - /// - /// The number of sub-meshes in the detail mesh. - /// - public int detailMeshCount; - - /// - /// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.) - /// - public int detailVertCount; - - /// - /// The number of triangles in the detail mesh. - /// - public int detailTriCount; - - /// - /// The number of bounding volume nodes. (Zero if bounding volumes are disabled.) - /// - public int bvNodeCount; - - /// - /// The number of off-mesh connections. - /// - public int connCount; - - /// - /// The index of the first polygon which is an off-mesh connection. - /// - public int connBase; - - /// - /// The minimum floor to 'ceiling' height that will still \allow the floor area to be - /// considered traversable. - /// - public float walkableHeight; - - /// - /// The amount the polygon walls have been eroded away from - /// obstructions. - /// - public float walkableRadius; - - /// - /// The maximum ledge height that is considered to still be - /// traversable. - /// - public float walkableStep; - - /// - /// The minimum bounds of the tile's AABB. - /// - public Vector3 boundsMin; - - /// - /// The maximum bounds of the tile's AABB. - /// - public Vector3 boundsMax; - - /// - /// The bounding volumn quantization factor. (For converting from world to bounding volumn - /// coordinates.) - /// - public float bvQuantFactor; - - /// - /// Privides human readable text for the header. (Multi-line.) - /// - /// Text describing the header. - public override string ToString() - { - return string.Format("Tile: X: {2}, Z: {3}, Layer: {4}\n" - + "Version: {1}, UserId: {5}\n" - + "Polys: {6}, Verts: {7}\n" - + "Detail: Meshes: {9}, Tris: {11}, Verts: {10}\n" - + "Conns: {13}, ConnBase: {14}\n" - + "Walkable: Height: {15}, Radius: {16}, Step: {17}\n" - + "Bounds: Min: {18}, Max: {19}\n" - + "MaxLinks: {8}, BVQuantFactor: {20}, BVNodes: {12}\n" - + "Magic: {0}\n" - , magic, version - , tileX, tileZ, layer - , userId - , polyCount, vertCount - , maxLinkCount - , detailMeshCount - , detailVertCount - , detailTriCount - , bvNodeCount - , connCount, connBase - , walkableHeight - , walkableRadius - , walkableStep - , Vector3Util.ToString(boundsMin) - , Vector3Util.ToString(boundsMax) - , bvQuantFactor); - } - } -} diff --git a/critterai/.svn/pristine/ae/aecbf0c87eb7f52d994c494c8eaff205dc2bb7b4.svn-base b/critterai/.svn/pristine/ae/aecbf0c87eb7f52d994c494c8eaff205dc2bb7b4.svn-base deleted file mode 100644 index ad96ff44..00000000 --- a/critterai/.svn/pristine/ae/aecbf0c87eb7f52d994c494c8eaff205dc2bb7b4.svn-base +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.interop; - -namespace org.critterai.nmgen -{ - /// - /// Represents a simple, non-overlapping contour in voxel space. - /// - /// - /// - /// While the height of the border will vary, the contour will always form a simple polygon - /// when projected onto the xz-plane. - /// - /// - /// Minimum bounds and cell size information is needed in order to translate vertex - /// coordinates into world space. - /// - /// - /// worldX = boundsMin[0] + vertX * xzCellSize - /// worldY = boundsMin[1] + vertY * yCellSize - /// worldZ = boundsMin[2] + vertZ * xzCellSize - /// - /// - /// A contour only exists within the context of a . - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class Contour - : IManagedObject - { - /// - /// The mask to apply to the forth element of the vertices data in order to extract region - /// ids. (Removes flags from the element.) - /// - /// - /// - /// Example: - /// - /// - /// int region = verts[i * 4 + 3] & Contour.RegionMask; - /// - /// - public const int RegionMask = 0xfff; - - private IntPtr mVerts; // int[vertCount * 4] - private int mVertCount; - private IntPtr mRawVerts; // int[rawVertCount * 4] - private int mRawVertCount; - private ushort mRegion; - private byte mArea; - - /// - /// The number of vertices in the simplified contour. - /// - public int VertCount { get { return mVertCount; } } - - /// - /// The number of vertices in the raw contour. - /// - public int RawVertCount { get { return mRawVertCount; } } - - /// - /// The region id associated with the contour. - /// - /// - /// - /// Note: The is not associated with this field. - /// - /// - public ushort Region { get { return mRegion; } } - - /// - /// The area associated with the contour. - /// - public byte Area { get { return mArea; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return (mVerts == IntPtr.Zero); } } - - /// - /// The type of unmanaged resources within the object. - /// - public AllocType ResourceType - { - get { return AllocType.ExternallyManaged; } - } - - internal Contour() { } - - internal void Reset() - { - mVertCount = 0; - mRawVertCount = 0; - mRegion = NMGen.NullRegion; - mArea = NMGen.NullArea; - mVerts = IntPtr.Zero; - mRawVerts = IntPtr.Zero; - } - - /// - /// Has no effect on the object. (The object owner will handle disposal.) - /// - /// - /// - /// Objects of this type are always owned by a object, which - /// manages its disposal. - /// - /// - public void RequestDisposal() - { - // Can't be disposed manually. Owner will use reset. - } - - /// - /// Loads the vertices and connection data for the simplified contour into the specified - /// buffer. - /// - /// - /// - /// The simplified contour is a version of the raw contour with all 'unnecessary' vertices - /// removed. Whether a vertex is considered unnecessary depends on the contour build - /// process. - /// - /// - /// The data is represented as follows: (x, y, z, r) * VertCount. - /// - /// - /// A contour edge is formed by the current and next vertex. The r-value indicates the - /// region and connection information for the edge. - /// - /// - /// The region id is obtained by applying . - /// E.g. regionId = (vert[i * 4 + 3] & RegionMask) - /// - /// - /// The edge is not connected if the region id is . - /// - /// - /// If the r-value has the flag set, then the edge - /// represents an change in area as well as region. - /// - /// - /// The buffer to load the data into. [Size: >= 4 * VertCount] - /// True if the operation completed successfully. - public bool GetVerts(int[] buffer) - { - if (IsDisposed) - return false; - - Marshal.Copy(mVerts, buffer, 0, mVertCount * 4); - - return true; - } - - /// - /// Loads the vertices and connection data for the raw contour into the specified buffer. - /// - /// - /// - /// See the method for details on the element layout. - /// - /// - /// The buffer to load the data into. [Size: >= 4 * VertCount] - /// True if the operation completed successfully. - public bool GetRawVerts(int[] buffer) - { - if (IsDisposed) - return false; - - Marshal.Copy(mRawVerts, buffer, 0, mVertCount * 4); - - return true; - } - } -} diff --git a/critterai/.svn/pristine/af/af74c19a0676f9a4c2ad12dda9517a6c65d94ab6.svn-base b/critterai/.svn/pristine/af/af74c19a0676f9a4c2ad12dda9517a6c65d94ab6.svn-base deleted file mode 100644 index 1d939949..00000000 Binary files a/critterai/.svn/pristine/af/af74c19a0676f9a4c2ad12dda9517a6c65d94ab6.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/af/af82b70a2048ab740f05191b87e4215d059c6d0c.svn-base b/critterai/.svn/pristine/af/af82b70a2048ab740f05191b87e4215d059c6d0c.svn-base deleted file mode 100644 index 14f5b870..00000000 --- a/critterai/.svn/pristine/af/af82b70a2048ab740f05191b87e4215d059c6d0c.svn-base +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -#if NUNITY -using Vector2 = org.critterai.Vector2; -#else -using Vector2 = UnityEngine.Vector2; -#endif - -namespace org.critterai -{ - /// - /// Provides various 2D vector utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Vector2Util - { - private const float Epsilon = MathUtil.Epsilon; - - /// - /// The zero vector. (0, 0) - /// - public static Vector2 Zero { get { return new Vector2(0, 0); } } - - /// - /// Returns the - /// dot product of the specified vectors. (u . v) - /// - /// Vector u - /// Vector v - /// The dot product of the specified vectors. - public static float Dot(Vector2 u, Vector2 v) - { - return (u.x * v.x) + (u.y * v.y); - } - - /// - /// Derives the normalized direction vector from point A to point B. (Costly method!) - /// - /// The starting point A. - /// The end point B. - /// - /// The normalized direction vector for the vector pointing from point A to B. - /// - public static Vector2 GetDirectionAB(Vector2 a, Vector2 b) - { - // Subtract. - Vector2 result = new Vector2(b.x - a.x, b.y - a.y); - - // Normalize. - float length = (float)Math.Sqrt((result.x * result.x) + (result.y * result.y)); - - if (length <= Epsilon) - length = 1; - - result.x /= length; - result.y /= length; - - if (Math.Abs(result.x) < Epsilon) - result.x = 0; - if (Math.Abs(result.y) < Epsilon) - result.y = 0; - - return result; - } - - /// - /// Determines whether or not the specified vectors are equal within the specified tolerance. - /// - /// - /// - /// Change in beahvior: Prior to version 0.4, the area of equality for this method was - /// an axis-aligned bounding box at the tip of the vector. As of version 0.4 the area of - /// equality is a sphere. This change improves performance. - /// - /// - /// Vector u. - /// Vector v - /// The allowed tolerance. [Limit: >= 0] - /// - /// - /// True if the specified vectors are similar enough to be considered equal. - /// - public static bool SloppyEquals(Vector2 u, Vector2 v, float tolerance) - { - // Duplicating code for performance reasons. - float dx = u.x - v.x; - float dy = u.y - v.y; - return (dx * dx + dy * dy) <= tolerance * tolerance; - } - - /// - /// Returns the square of the distance between two points. - /// - /// Point A. - /// Point B. - /// The square of the distance between the points. - public static float GetDistanceSq(Vector2 a, Vector2 b) - { - float dx = a.x - b.x; - float dy = a.y - b.y; - return (dx * dx + dy * dy); - } - - /// - /// Normalizes the specified vector such that its length is equal to one. (Costly method!) - /// - /// A vector. - /// The normalized vector. - public static Vector2 Normalize(Vector2 v) - { - float length = (float)Math.Sqrt(v.x * v.x + v.y * v.y); - - if (length <= Epsilon) - length = 1; - - v.x /= length; - v.y /= length; - - if (Math.Abs(v.x) < Epsilon) - v.x = 0; - if (Math.Abs(v.y) < Epsilon) - v.y = 0; - - return v; - } - - /// - /// Scales the vector to the specified length. (Costly method!) - /// - /// A vector. - /// The length to scale the vector to. - /// A vector scaled to the specified length. - public static Vector2 ScaleTo(Vector2 v, float length) - { - if (length == 0 || (v.x == 0 && v.y == 0)) - return new Vector2(0, 0); - - float factor = (length / (float)(Math.Sqrt(v.x * v.x + v.y * v.y))); - - v.x *= factor; - v.y *= factor; - - return v; - } - - /// - /// Truncates the length of the vector to the specified value. - /// - /// - /// - /// If the vector's length is longer than the specified value the length of the vector is - /// scaled back to the specified length. - /// - /// - /// If the vector's length is shorter than the specified value, it is not changed. - /// - /// - /// This is a potentially costly method. - /// - /// - /// The vector to truncate. - /// The maximum allowed length of the resulting vector. - /// A vector with a length at or below the maximum length. - public static Vector2 TruncateLength(Vector2 v, float maxLength) - { - if (maxLength == 0 || (v.x < float.Epsilon && v.y < float.Epsilon)) - return new Vector2(0, 0); - - float csq = v.x * v.x + v.y * v.y; - - if (csq <= maxLength * maxLength) - return v; - - float factor = (float)(maxLength / Math.Sqrt(csq)); - - v.x *= factor; - v.y *= factor; - - return v; - } - } -} diff --git a/critterai/.svn/pristine/af/afc84ec7dfcc18ab5ed35025d1b68cf2567ceee4.svn-base b/critterai/.svn/pristine/af/afc84ec7dfcc18ab5ed35025d1b68cf2567ceee4.svn-base deleted file mode 100644 index b6cb9247..00000000 --- a/critterai/.svn/pristine/af/afc84ec7dfcc18ab5ed35025d1b68cf2567ceee4.svn-base +++ /dev/null @@ -1,866 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using org.critterai.nmgen; -using org.critterai.geom; - -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Provides a way of building navigation mesh data in incremental steps. - /// - /// - /// - /// Processors will be called for processing after each step. (Post-processing) - /// The assests available by default at each step will be as follows: - /// - /// - /// HeightfieldBuild:
      - /// CompactFieldBuild:
      - /// RegionBuild:
      - /// ContourBuild: and
      - /// PolyMeshBuild: and
      - /// DetailMeshBuild: and
      - ///
      - /// - /// More assets will be avialable based on - /// requirements. - /// - /// - /// The detail mesh step will only occur if the settings - /// require it. - /// - /// - /// Processors are allowed to replace assets. But they must never set the assets to - /// an invalid state. - /// - /// - /// Each instance can be used to perform only a single build. (Single use.) - /// - ///
      - public sealed class IncrementalBuilder - { - private readonly string mTileText; - private readonly NMGenTileParams mTileConfig; - private readonly NMGenParams mConfig; - - private readonly NMGenAssetFlag mResultOptions; - - private NMGenState mState = NMGenState.Initialized; - - private readonly InputGeometry mGeometry; - private readonly ProcessorSet mProcessors; - - private NMGenContext mBuildContext; - - /// - /// True if the builder is safe to run on a separate thread from which it was created. - /// - /// - /// - /// Thread-safely only applies to running the build. Builder objects are - /// never safe to access from multiple threads at the same time. - /// - /// - public bool IsThreadSafe { get { return mProcessors.IsThreadSafe; } } - - /// - /// The current state of the builder. - /// - /// - /// - /// If the value is an unfinished state, then it represents the build step that will - /// occur the next time the method called. - /// - /// - public NMGenState State { get { return mState; } } - - /// - /// True if the the build has finished. (Successfully or not.) - /// - public bool IsFinished - { - get - { - return (mState == NMGenState.Aborted - || mState == NMGenState.Complete - || mState == NMGenState.NoResult); - } - } - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int TileX { get { return mTileConfig.TileX; } } - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int TileZ { get { return mTileConfig.TileZ; } } - - /// - /// The result of the build. - /// - /// - /// - /// Will return a result only when in the state. - /// - /// - public NMGenAssets Result - { - get - { - if (mState == NMGenState.Complete) - { - return new NMGenAssets(mTileConfig.TileX, mTileConfig.TileZ - , mBuildContext.PolyMesh, mBuildContext.DetailMesh - , mBuildContext.Heightfield, mBuildContext.CompactField, mBuildContext.Contours); - } - return new NMGenAssets(); - } - } - - /// - /// The NMGen assets that will be included in the . - /// - /// - /// - /// Will always include - /// - /// - public NMGenAssetFlag ResultOptions { get { return mResultOptions; } } - - /// - /// The number of messages generated by the build. - /// - public int MessageCount - { - get { return (IsFinished ? mBuildContext.MessageCount : 0); } - } - - private IncrementalBuilder(NMGenTileParams tileConfig - , NMGenParams config - , NMGenAssetFlag resultOptions - , InputGeometry source - , ProcessorSet processors) - { - mConfig = config; - mTileConfig = tileConfig; - - mGeometry = source; - mProcessors = processors; - mResultOptions = resultOptions; - - mBuildContext = new NMGenContext(tileConfig.TileX, tileConfig.TileZ, mConfig.Clone()); - - mTileText = string.Format("({0},{1})", tileConfig.TileX, tileConfig.TileZ); - - mState = NMGenState.Initialized; - } - - /// - /// Gets available build messages, or a zero length array if no messages are available. - /// - /// - /// - /// Messages will only be available when the build is finished. - /// - /// - /// Available build messages. - public string[] GetMessages() - { - return (IsFinished ? mBuildContext.GetMessages() : new string[0]); - } - - /// - /// Gets a new line delimited flattened version of all build messages. - /// - /// - /// - /// Messages will only be available when the build is finished. - /// - /// - /// All build messages. - public string GetMessagesFlat() - { - return (IsFinished ? mBuildContext.GetMessagesFlat() : ""); - } - - /// - /// Performs a single build step. - /// - /// - /// - /// The result state will represent either a finished state or the build step that - /// will be performed during the next call to the method. - /// - /// - /// The state at the end of the build step. - public NMGenState Build() - { - switch (mState) - { - case NMGenState.Initialized: - - mBuildContext.Log("Build: " + mTileText, this); - - mProcessors.LogProcessors(mBuildContext); - - mState = NMGenState.HeightfieldBuild; - - break; - - case NMGenState.HeightfieldBuild: - - //UnityEngine.Debug.Log("hfb"); - BuildHeightfield(); - break; - - case NMGenState.CompactFieldBuild: - - //UnityEngine.Debug.Log("cfb"); - BuildCompactField(); - break; - - case NMGenState.RegionBuild: - - //UnityEngine.Debug.Log("rb"); - BuildRegions(); - break; - - case NMGenState.ContourBuild: - - //UnityEngine.Debug.Log("cb"); - BuildContours(); - break; - - case NMGenState.PolyMeshBuild: - - BuildPolyMesh(); - break; - - case NMGenState.DetailMeshBuild: - - BuildDetailMesh(); - break; - } - return mState; - } - - /// - /// Performs all build steps. - /// - public void BuildAll() - { - while (!IsFinished) { Build(); } - } - - private void BuildHeightfield() - { - int width; - int depth; - - NMGen.DeriveSizeOfCellGrid(mTileConfig.BoundsMin - , mTileConfig.BoundsMax - , mConfig.XZCellSize - , out width - , out depth); - - Heightfield hf = Heightfield.Create(width, depth - , mTileConfig.BoundsMin, mTileConfig.BoundsMax - , mConfig.XZCellSize, mConfig.YCellSize); - - - hf.AddTriangles(mBuildContext - , mGeometry.Mesh - , mTileConfig.boundsMin - , mTileConfig.boundsMax - , mConfig.WalkableStep); // Merge for any spans less than step. - - - if (hf.GetSpanCount() < 1) - { - FinalizeNoResult("Complete at heightfield build. No spans."); - return; - } - - - mBuildContext.Heightfield = hf; - - if (PostProcess() && PostHeightfieldCheck()) - { - mBuildContext.Log("Voxelized triangles. Span count: " + hf.GetSpanCount(), this); - mState = NMGenState.CompactFieldBuild; - } - } - - private bool PostHeightfieldCheck() - { - Heightfield hf = mBuildContext.Heightfield; - - if (hf == null || hf.IsDisposed) - { - FinalizeAbort("Custom processors destroyed the heightfield. (" + mState + " Post)"); - return false; - } - else if (hf.GetSpanCount() < 1) - { - FinalizeNoResult("Complete at heightfield build. No spans. (" + mState + " Post)"); - return false; - } - return true; - } - - private bool PostProcess() - { - if (!mProcessors.Process(mBuildContext, mState)) - { - FinalizeAbort("Abort requested by custom processors. (" + mState + " Post)"); - return false; - } - if (mBuildContext.NoResult) - { - FinalizeNoResult("Custom processors set as no result. (" + mState + " Post)"); - return false; - } - return true; - } - - private void BuildCompactField() - { - Heightfield hf = mBuildContext.Heightfield; - - CompactHeightfield chf = CompactHeightfield.Build(mBuildContext - , hf - , mConfig.WalkableHeight - , mConfig.WalkableStep); - - if (CanDispose(NMGenAssetFlag.Heightfield)) - { - hf.RequestDisposal(); - mBuildContext.Heightfield = null; - } - - if (chf == null) - { - FinalizeAbort("Aborted at compact heightfield build."); - return; - } - - if (chf.SpanCount < 1) - { - FinalizeNoResult("Complete at compact heightfield build. No spans."); - return; - } - - mBuildContext.CompactField = chf; - - // Note: Post process is done before eroding the walkable area - // so that the processors can stamp additional obstructions into - // the heightfield. - if (PostProcess() && PostCompactFieldCheck()) - { - if (mConfig.WalkableRadius > 0) - { - chf = mBuildContext.CompactField; - chf.ErodeWalkableArea(mBuildContext, mConfig.WalkableRadius); - mBuildContext.Log("Eroded walkable area by radius: " + mConfig.walkableRadius - , this); - } - - mBuildContext.Log("Built compact heightfield. Spans: " + chf.SpanCount, this); - - mState = NMGenState.RegionBuild; - } - } - - private bool PostCompactFieldCheck() - { - CompactHeightfield chf = mBuildContext.CompactField; - - if (chf == null || chf.IsDisposed) - { - FinalizeAbort( - "Custom processors destroyed the compact heightfield. (" + mState + " Post)"); - return false; - } - else if (chf.SpanCount < 1) - { - FinalizeNoResult( - "Complete at compact heightfield build. No spans. (" + mState + " Post)"); - return false; - } - return true; - } - - private void BuildRegions() - { - CompactHeightfield chf = mBuildContext.CompactField; - - chf.BuildDistanceField(mBuildContext); - mBuildContext.Log("Built distance field. Max Distance: " + chf.MaxDistance, this); - - if (mConfig.UseMonotone) - { - if (!chf.BuildRegionsMonotone(mBuildContext - , mConfig.BorderSize - , mConfig.MinRegionArea - , mConfig.MergeRegionArea)) - { - FinalizeAbort("Monotone region generation failed."); - return; - } - } - else - { - if (!chf.BuildRegions(mBuildContext - , mConfig.BorderSize - , mConfig.MinRegionArea - , mConfig.MergeRegionArea)) - { - FinalizeAbort("Region generation failed."); - return; - } - } - - if (PostProcess() && PostCompactFieldCheck()) - { - if (chf.MaxRegion < 2) - { - // Null region counts as a region. So expect - // at least 2. - FinalizeNoResult("Completed after region build. No useable regions formed."); - return; - } - - mBuildContext.Log("Generated regions. Region Count: " + chf.MaxRegion, this); - - // Success. - mState = NMGenState.ContourBuild; - } - } - - private void BuildContours() - { - ContourSet cset = ContourSet.Build(mBuildContext - , mBuildContext.CompactField - , mConfig.EdgeMaxDeviation - , mConfig.MaxEdgeLength - , mConfig.ContourOptions); - - if (cset == null) - { - FinalizeAbort("Aborted at contour set build."); - return; - } - - if (cset.Count < 1) - { - FinalizeNoResult("Completed after contour build. No useable contours generated."); - return; - } - - mBuildContext.Contours = cset; - - if (PostProcess() && PostContoursCheck() && PostCompactFieldCheck()) - { - mBuildContext.Log("Built contour set. Contour count: " + cset.Count, this); - mState = NMGenState.PolyMeshBuild; - } - } - - private bool PostContoursCheck() - { - ContourSet contours = mBuildContext.Contours; - - if (contours == null || contours.IsDisposed) - { - FinalizeAbort("Custom processors destroyed the contour set. (" + mState + " Post)"); - return false; - } - else if (contours.Count < 1) - { - FinalizeNoResult( - "Aborted after contour set build. No contours generated. (" + mState + " Post)"); - return false; - } - return true; - } - - private void BuildPolyMesh() - { - ContourSet cset = mBuildContext.Contours; - - PolyMesh polyMesh = PolyMesh.Build(mBuildContext - , cset - , mConfig.MaxVertsPerPoly - , mConfig.WalkableHeight - , mConfig.WalkableRadius - , mConfig.WalkableStep); - - if (CanDispose(NMGenAssetFlag.ContourSet)) - { - cset.RequestDisposal(); - mBuildContext.Contours = null; - } - - if (polyMesh == null) - { - FinalizeAbort("Aborted at poly mesh build."); - return; - } - - if (polyMesh.PolyCount < 1) - { - FinalizeNoResult("Aborted after poly mesh build. No polygons generated."); - return; - } - - mBuildContext.PolyMesh = polyMesh; - - if (PostProcess() & PostPolyMeshCheck() & PostCompactFieldCheck()) - { - mBuildContext.Log("Built poly mesh. PolyCount: " + polyMesh.PolyCount, this); - mState = NMGenState.DetailMeshBuild; - } - } - - private bool PostPolyMeshCheck() - { - PolyMesh polyMesh = mBuildContext.PolyMesh; - - if (polyMesh == null || polyMesh.IsDisposed) - { - FinalizeAbort("Custom processors destroyed the poly mesh. (" + mState + " Post)"); - return false; - } - else if (polyMesh.PolyCount < 1) - { - FinalizeNoResult( - "Aborted after poly mesh build. No polygons generated. (" + mState + " Post)"); - return false; - } - return true; - } - - private void BuildDetailMesh() - { - if ((mResultOptions & NMGenAssetFlag.DetailMesh) == 0) - { - FinalizeComplete(); - return; - } - - PolyMesh polyMesh = mBuildContext.PolyMesh; - CompactHeightfield chf = mBuildContext.CompactField; - - PolyMeshDetail detailMesh = PolyMeshDetail.Build(mBuildContext - , polyMesh - , chf - , mConfig.detailSampleDistance - , mConfig.detailMaxDeviation); - - if (CanDispose(NMGenAssetFlag.CompactField)) - { - chf.RequestDisposal(); - mBuildContext.CompactField = null; - } - - if (detailMesh == null) - { - FinalizeAbort("Aborted at detail mesh build."); - return; - } - - mBuildContext.DetailMesh = detailMesh; - - if (detailMesh.MeshCount < 1) - { - // Will only happen on an error. - FinalizeAbort("Aborted after detail mesh build. No detail meshes generated."); - return; - } - - if (PostProcess() & PostPolyMeshCheck() & PostDetailCheck()) - { - mBuildContext.Log("Built detail mesh. TriangleCount: " + detailMesh.TriCount, this); - FinalizeComplete(); - } - } - - private void FinalizeComplete() - { - if ((mResultOptions & NMGenAssetFlag.Heightfield) == 0 && mBuildContext.Heightfield != null) - { - mBuildContext.Heightfield.RequestDisposal(); - mBuildContext.Heightfield = null; - } - - if ((mResultOptions & NMGenAssetFlag.CompactField) == 0 && mBuildContext.CompactField != null) - { - mBuildContext.CompactField.RequestDisposal(); - mBuildContext.CompactField = null; - } - - if ((mResultOptions & NMGenAssetFlag.ContourSet) == 0 && mBuildContext.Contours != null) - { - mBuildContext.Contours.RequestDisposal(); - mBuildContext.Contours = null; - } - - // Polymesh is always kept. - - if ((mResultOptions & NMGenAssetFlag.DetailMesh) == 0 && mBuildContext.DetailMesh != null) - { - mBuildContext.DetailMesh.RequestDisposal(); - mBuildContext.DetailMesh = null; - } - - mBuildContext.Log("Build Complete. Result: " + mResultOptions, this); - mState = NMGenState.Complete; - } - - private void FinalizeAbort(string message) - { - mBuildContext.Log(message, this); - DisposeAssets(); - mState = NMGenState.Aborted; - } - - private void FinalizeNoResult(string message) - { - mBuildContext.Log(message, this); - DisposeAssets(); - mState = NMGenState.NoResult; - } - - private void DisposeAssets() - { - if (mBuildContext.Heightfield != null) - mBuildContext.Heightfield.RequestDisposal(); - - if (mBuildContext.CompactField != null) - mBuildContext.CompactField.RequestDisposal(); - - if (mBuildContext.Contours != null) - mBuildContext.Contours.RequestDisposal(); - - if (mBuildContext.PolyMesh != null) - mBuildContext.PolyMesh.RequestDisposal(); - - if (mBuildContext.DetailMesh != null) - mBuildContext.DetailMesh.RequestDisposal(); - } - - private bool PostDetailCheck() - { - PolyMeshDetail detailMesh = mBuildContext.DetailMesh; - PolyMesh polyMesh = mBuildContext.PolyMesh; - - if (detailMesh == null || detailMesh.IsDisposed) - { - FinalizeAbort("Custom processors destroyed the detail mesh. (" + mState + " Post)"); - return false; - } - else if (polyMesh.PolyCount != detailMesh.MeshCount) - { - FinalizeAbort("Custom processors returned with poly/detail count mismatch. (" - + mState + " Post)"); - return false; - } - - return true; - } - - private bool CanDispose(NMGenAssetFlag asset) - { - return ((mProcessors.PreserveAssets & asset) == 0 && (mResultOptions & asset) == 0); - } - - /// - /// Creates a new builder for a single-tile mesh build. - /// - /// - /// - /// The bounds of the tile will be based on the geometry. - /// - /// - /// Will return null if a processor requires the the detail mesh but - /// the detail mesh is not included in the result options. - /// - /// - /// The build configuration. - /// The assets to include in the result. - /// The input geometry. - /// The processors to apply. - /// A new builder, or null on error. - public static IncrementalBuilder Create(NMGenParams buildConfig - , NMGenAssetFlag resultOptions - , InputGeometry geometry - , ProcessorSet processors) - { - if (buildConfig == null - || geometry == null - || processors == null) - { - return null; - } - - resultOptions |= NMGenAssetFlag.PolyMesh; - - if ((processors.PreserveAssets & NMGenAssetFlag.DetailMesh) != 0 - && (resultOptions & NMGenAssetFlag.DetailMesh) == 0) - { - // The processors require the detail mesh, but the result won't include it. - return null; - } - - NMGenTileParams tileConfig = - new NMGenTileParams(0, 0, geometry.BoundsMin, geometry.BoundsMax); - - return new IncrementalBuilder(tileConfig - , buildConfig, resultOptions, geometry, processors); - } - - /// - /// Creates a new builder for a multi-tile mesh build. - /// - /// - /// - /// Will return null if a processor requires the the detail mesh but the detail mesh is - /// not included in the result options. - /// - /// - /// The x-index of the tile to build. - /// The z-index of the tile to build. - /// The assets to include in the result. - /// The tile set definition to base the build on. - /// The processors to apply. - /// A new builder, or null on error. - public static IncrementalBuilder Create(int tx, int tz - , NMGenAssetFlag resultOptions - , TileSetDefinition tdef - , ProcessorSet processors) - { - if (tdef == null || processors == null) - return null; - - resultOptions |= NMGenAssetFlag.PolyMesh; - - if ((processors.PreserveAssets & NMGenAssetFlag.DetailMesh) != 0 - && (resultOptions & NMGenAssetFlag.DetailMesh) == 0) - { - // The processors require the detail mesh, but the result won't include it. - return null; - } - - Vector3 bmin; - Vector3 bmax; - - // This next call checks for valid tx/tz. - if (!tdef.GetTileBounds(tx, tz, true, out bmin, out bmax)) - return null; - - NMGenTileParams tileConfig = new NMGenTileParams(tx, tz, bmin, bmax); - - return new IncrementalBuilder(tileConfig, tdef.GetBaseConfig(), resultOptions - , tdef.Geometry, processors); - } - - /// - /// Returns human friendly text for the specified state. - /// - /// The state. - /// Human friendly text. - public static string ToLabel(NMGenState state) - { - switch (state) - { - case NMGenState.Aborted: - return "Aborted."; - case NMGenState.CompactFieldBuild: - return "Building compact heightfield."; - case NMGenState.Complete: - return "Complete"; - case NMGenState.ContourBuild: - return "Building contours."; - case NMGenState.DetailMeshBuild: - return "Building detail mesh."; - case NMGenState.HeightfieldBuild: - return "Building heightfield."; - case NMGenState.PolyMeshBuild: - return "Building polygon mesh."; - case NMGenState.RegionBuild: - return "Building regions."; - case NMGenState.NoResult: - return "No result."; - } - return "Unhandled state: " + state; - } - - /// - /// Returns a progress value associated with the specified state. - /// - /// - /// - /// The value will be between 0 and 1.0, suitable for providing build progress feedback. - /// - /// - /// The state. - /// A progress value for the state. - public static float ToProgress(NMGenState state) - { - const float inc = 1 / 6f; - switch (state) - { - case NMGenState.Initialized: - return 0; - case NMGenState.HeightfieldBuild: - return inc * 1; - case NMGenState.CompactFieldBuild: - return inc * 2; - case NMGenState.RegionBuild: - return inc * 3; - case NMGenState.ContourBuild: - return inc * 4; - case NMGenState.PolyMeshBuild: - return inc * 5; - case NMGenState.DetailMeshBuild: - return inc * 6; - case NMGenState.Complete: - return 1; - case NMGenState.Aborted: - return 1; - case NMGenState.NoResult: - return 1; - } - return 1; - } - } -} diff --git a/critterai/.svn/pristine/af/affdc2163af84cea9791d93336844bbf6c4dc333.svn-base b/critterai/.svn/pristine/af/affdc2163af84cea9791d93336844bbf6c4dc333.svn-base deleted file mode 100644 index d6361b2d..00000000 --- a/critterai/.svn/pristine/af/affdc2163af84cea9791d93336844bbf6c4dc333.svn-base +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#if NUNITY -using Vector2 = org.critterai.Vector2; -#else -using Vector2 = UnityEngine.Vector2; -#endif - -namespace org.critterai.geom -{ - /// - /// Provides circle related utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Circle - { - /// - /// Determines whether or not two circles intersect each other. - /// - /// - /// - /// Test is inclusive of the circle boundary. - /// - /// - /// Containment of one circle by another is considered intersection. - /// - /// - /// The center point of circle A. - /// The radius of circle A. - /// The center point of circle B. - /// The radius of Circle B. - /// True if the circles intersect. - public static bool Intersects(Vector2 acenter, float aradius - , Vector2 bcenter, float bradius) - { - float dx = acenter.x - bcenter.x; - float dy = acenter.y - bcenter.y; - return (dx * dx + dy * dy) <= (aradius + bradius) * (aradius + bradius); - } - - /// - /// Determines whether or not a point is contained within a circle. - /// - /// - /// - /// The test is inclusive of the circle boundary. - /// - /// - /// The point to test. - /// The center point of the circle. - /// The radius of the circle. - /// True if the point is contained within the circle. - public static bool Contains(Vector2 point, Vector2 circle, float radius) - { - float dx = point.x - circle.x; - float dy = point.y - circle.y; - return (dx * dx + dy * dy) <= radius * radius; - } - } -} diff --git a/critterai/.svn/pristine/b0/b0685157046b888cbcbf84842b1d44425f14347e.svn-base b/critterai/.svn/pristine/b0/b0685157046b888cbcbf84842b1d44425f14347e.svn-base deleted file mode 100644 index 03227455..00000000 --- a/critterai/.svn/pristine/b0/b0685157046b888cbcbf84842b1d44425f14347e.svn-base +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class FailureControl - : BuildControl - { - private readonly string mMessage; - - public FailureControl(string message) - { - if (message == null) - message = "Internal Error"; - - mMessage = message; - } - - public override bool Enter(ControlContext context, DebugViewContext debug) - { - if (base.Enter(context, debug)) - { - DebugContext.DisableAllViews(); - return true; - } - - return false; - } - - protected override void OnGUIMain() - { - GUI.Box(Context.MainArea, mMessage); - - if (Context.Build != null) - { - ControlUtil.BeginButtonArea(Context.ButtonArea); - GUILayout.FlexibleSpace(); - ControlUtil.OnGUIResetButton(Context, DebugContext, ControlUtil.HighlightedButton); - ControlUtil.EndButtonArea(); - } - } - - protected override void OnGUIButtons() - { - ControlUtil.BeginButtonArea(Context.ButtonArea); - - if (Context.Build != null) - { - GUILayout.FlexibleSpace(); - ControlUtil.OnGUIResetButton(Context, DebugContext, ControlUtil.HighlightedButton); - } - - ControlUtil.EndButtonArea(); - } - } -} diff --git a/critterai/.svn/pristine/b1/b17b32fe4efc3fe49793d2fa61e30941f2adc9f1.svn-base b/critterai/.svn/pristine/b1/b17b32fe4efc3fe49793d2fa61e30941f2adc9f1.svn-base deleted file mode 100644 index 1417c8e0..00000000 --- a/critterai/.svn/pristine/b1/b17b32fe4efc3fe49793d2fa61e30941f2adc9f1.svn-base +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#if NUNITY - -using System.Runtime.InteropServices; - -namespace org.critterai -{ - /// - /// Represents a 2D floating point vector. - /// - /// - /// - /// Not present in the Unity build. - /// - /// - /// This structure's API kept very simple in order to minimize conflicts with other vector - /// implementations. The class provides some standard vector - /// operations. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct Vector2 - { - /// - /// The x-value of vector (x, y). - /// - public float x; - - /// - /// The y-value of vector (x, y). - /// - public float y; - - /// - /// Constructor. - /// - /// The x-value of vector (x, y). - /// The y-value of vector (x, y). - public Vector2(float x, float y) - { - this.x = x; - this.y = y; - } - - /// - /// The vector equality operator. - /// - /// A vector. - /// A vector. - /// True if each element of the vectors are equal. - public static bool operator ==(Vector2 v, Vector2 u) - { - return (v.x == u.x && v.y == u.y); - } - - /// - /// The vector inequality operator. - /// - /// A vector. - /// A vector. - /// True if any equivalent element of the vectors is not equal. - public static bool operator !=(Vector2 v, Vector2 u) - { - return !(v.x == u.x && v.y == u.y); - } - - /// - /// Vector subtraction operator. (v - u) - /// - /// The l-value vector. - /// The r-value vector. - /// A vector represnting (v - u). - public static Vector2 operator -(Vector2 v, Vector2 u) - { - return new Vector2(v.x - u.x, v.y - u.y); - } - - /// - /// Vector addition operator. (v + u) - /// - /// A vector. - /// A vector. - /// A vector represnting (v + u). - public static Vector2 operator +(Vector2 v, Vector2 u) - { - return new Vector2(v.x + u.x, v.y + u.y); - } - - /// - /// The vector hash code. - /// - /// The vector hash code. - public override int GetHashCode() - { - int result = 17; - result = 31 * result + x.GetHashCode(); - result = 31 * result + y.GetHashCode(); - return result; - } - - /// - /// Tests the vector for equality. - /// - /// The vector to compare. - /// True if each element of the vector is equal to this vector. - public override bool Equals(object obj) - { - if (obj is Vector2) - { - Vector2 u = (Vector2)obj; - return (x == u.x && y == u.y); - } - return false; - } - } -} - -#endif \ No newline at end of file diff --git a/critterai/.svn/pristine/b1/b1af9489d20de56dae566db9e37b65c4331a2e03.svn-base b/critterai/.svn/pristine/b1/b1af9489d20de56dae566db9e37b65c4331a2e03.svn-base deleted file mode 100644 index 39c17a05..00000000 Binary files a/critterai/.svn/pristine/b1/b1af9489d20de56dae566db9e37b65c4331a2e03.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/b2/b22af00e9ff12596a81bbd8763db2932bce974c6.svn-base b/critterai/.svn/pristine/b2/b22af00e9ff12596a81bbd8763db2932bce974c6.svn-base deleted file mode 100644 index 67267162..00000000 --- a/critterai/.svn/pristine/b2/b22af00e9ff12596a81bbd8763db2932bce974c6.svn-base +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav.u3d.editor; -using org.critterai.nav.u3d; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class DebugViewContext - { - private static GUIContent mShowInputLabel = new GUIContent( - "Input Geometry" - , "Framerate Killer!"); - - private readonly InputDebugView mInputView = new InputDebugView(); - private readonly TileGridDebugView mGridView = new TileGridDebugView(); - private readonly SelectionDebugView mSelectionView; - private readonly MeshDebugView mMeshView = new MeshDebugView(); - - private readonly NavmeshBuild mBuild; - private readonly TileSelection mSelection; - - private bool mNeedsRepaint; - - public DebugViewContext(NavmeshBuild build, TileSelection selection) - { - if (!build || selection == null) - throw new System.ArgumentNullException(); - - mSelectionView = new SelectionDebugView(); - mSelectionView.Enabled = true; - mSelectionView.Show = true; - mSelectionView.IncludeRootTile = true; - - mBuild = build; - mSelection = selection; - } - - public bool NeedsRepaint - { - get - { - return mNeedsRepaint - || mSelectionView.NeedsRepaint - || mMeshView.NeedsRepaint - || mInputView.NeedsRepaint - || mGridView.NeedsRepaint; - } - set - { - mNeedsRepaint = value; - if (!mNeedsRepaint) - { - mSelectionView.NeedsRepaint = false; - mMeshView.NeedsRepaint = false; - mInputView.NeedsRepaint = false; - mGridView.NeedsRepaint = false; - } - } - } - - public void DisableAllViews() - { - mInputView.Enabled = false; - mGridView.Enabled = false; - mSelectionView.Enabled = false; - mMeshView.Enabled = false; - } - - public void SetViews(ViewOption options) - { - // Debug.Log("Set Debug Views: " + options); - mInputView.Enabled = (options & ViewOption.Input) != 0; - mGridView.Enabled = (options & ViewOption.Grid) != 0; - mSelectionView.Enabled = (options & ViewOption.Selection) != 0; - mMeshView.Enabled = (options & ViewOption.Mesh) != 0; - } - - public void OnSceneGUI() - { - if (!mBuild) - return; - - mInputView.OnRenderObject(mBuild); - mGridView.OnRenderObject(mBuild); - mSelectionView.OnRenderObject(mBuild, mSelection); - mMeshView.OnRenderObject(mBuild, mSelection); - } - - public void OnGUIDebugExtras() - { - // Design note: Not allowing the selection display to be disabled. - // It is too important. - - bool guiEnabled = GUI.enabled; - - if (mInputView.Enabled) - mInputView.Show = GUILayout.Toggle(mInputView.Show, "Input Bounds"); - - if (mGridView.Enabled) - { - mGridView.Show = GUILayout.Toggle(mGridView.Show, "Tile Grid"); - - GUILayout.Space(ControlUtil.MarginSize); - - GUI.enabled = guiEnabled && mGridView.Show; - - mGridView.YOffset = - GUILayout.HorizontalSlider(mGridView.YOffset, 0, 1); - - GUI.enabled = guiEnabled; - } - - if (mSelectionView.Enabled) - { - mSelectionView.Show = GUILayout.Toggle(mSelectionView.Show, "Selection Bounds"); - } - } - - public void OnGUIMeshDisplayOptions() - { - if (!mBuild || !mMeshView.Enabled) - return; - - bool guiEnabled = GUI.enabled; - - MeshDebugView meshView = mMeshView; - - INavmeshData bnm = mBuild.BuildTarget; - NavmeshSceneDraw sceneDraw = NavmeshSceneDraw.Instance; - - bool showBaked = false; - - if (bnm != null) - { - showBaked = sceneDraw.OnGUI(bnm, "Baked Navmesh", false, false); - if (showBaked) - meshView.Show = MeshDebugOption.None; - } - - if (GUILayout.Toggle(meshView.Show == MeshDebugOption.WorkingMesh - , "Working Navmesh")) - { - meshView.Show = MeshDebugOption.WorkingMesh; - showBaked = false; - } - else if (meshView.Show == MeshDebugOption.WorkingMesh) - meshView.Show = MeshDebugOption.None; - - GUI.enabled = guiEnabled - && meshView.Show == MeshDebugOption.WorkingMesh || showBaked; - - bool orig = sceneDraw.ColorByArea; - sceneDraw.ColorByArea = GUILayout.Toggle(sceneDraw.ColorByArea, "Color by Area"); - if (sceneDraw.ColorByArea != orig) - mNeedsRepaint = true; - - GUILayout.Space(ControlUtil.MarginSize); - - GUI.enabled = guiEnabled - && (mSelection.HasSelection || !mBuild.BuildData.IsTiled); - - if (GUILayout.Toggle(meshView.Show == MeshDebugOption.PolyMesh - , "PolyMesh")) - { - meshView.Show = MeshDebugOption.PolyMesh; - showBaked = false; - } - else if (meshView.Show == MeshDebugOption.PolyMesh) - meshView.Show = MeshDebugOption.None; - - if (GUILayout.Toggle(meshView.Show == MeshDebugOption.Detailmesh - , "Detail Mesh")) - { - meshView.Show = MeshDebugOption.Detailmesh; - showBaked = false; - } - else if (meshView.Show == MeshDebugOption.Detailmesh) - meshView.Show = MeshDebugOption.None; - - if (mBuild.TileSetDefinition != null) - { - if (GUILayout.Toggle(meshView.Show == MeshDebugOption.InputGeometry - , mShowInputLabel)) - { - meshView.Show = MeshDebugOption.InputGeometry; - showBaked = false; - } - else if (meshView.Show == MeshDebugOption.InputGeometry) - meshView.Show = MeshDebugOption.None; - } - - GUI.enabled = guiEnabled; - - if (showBaked) - meshView.Show = MeshDebugOption.None; - else - sceneDraw.Hide(); - } - } -} diff --git a/critterai/.svn/pristine/b2/b269daac94e30bd7abe79a47924a7155a268e134.svn-base b/critterai/.svn/pristine/b2/b269daac94e30bd7abe79a47924a7155a268e134.svn-base deleted file mode 100644 index b098261e..00000000 --- a/critterai/.svn/pristine/b2/b269daac94e30bd7abe79a47924a7155a268e134.svn-base +++ /dev/null @@ -1,70 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURPROXIMITYGRID_H -#define DETOURPROXIMITYGRID_H - -class dtProximityGrid -{ - int m_maxItems; - float m_cellSize; - float m_invCellSize; - - struct Item - { - unsigned short id; - short x,y; - unsigned short next; - }; - Item* m_pool; - int m_poolHead; - int m_poolSize; - - unsigned short* m_buckets; - int m_bucketsSize; - - int m_bounds[4]; - -public: - dtProximityGrid(); - ~dtProximityGrid(); - - bool init(const int maxItems, const float cellSize); - - void clear(); - - void addItem(const unsigned short id, - const float minx, const float miny, - const float maxx, const float maxy); - - int queryItems(const float minx, const float miny, - const float maxx, const float maxy, - unsigned short* ids, const int maxIds) const; - - int getItemCountAt(const int x, const int y) const; - - inline const int* getBounds() const { return m_bounds; } - inline const float getCellSize() const { return m_cellSize; } -}; - -dtProximityGrid* dtAllocProximityGrid(); -void dtFreeProximityGrid(dtProximityGrid* ptr); - - -#endif // DETOURPROXIMITYGRID_H - diff --git a/critterai/.svn/pristine/b3/b31c39e3161b5079d1087d98efd0775b93525d3b.svn-base b/critterai/.svn/pristine/b3/b31c39e3161b5079d1087d98efd0775b93525d3b.svn-base deleted file mode 100644 index 9958def1..00000000 --- a/critterai/.svn/pristine/b3/b31c39e3161b5079d1087d98efd0775b93525d3b.svn-base +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using org.critterai.geom; -using org.critterai.nmgen; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Represents the definition for a set of tiles that make up a tiled navigation mesh. - /// - /// - /// - /// This object provides common configuration settings and input geometry for a tiled - /// navigation mesh build. For example, the will create - /// a builder from a tile set defintion. - /// - /// - /// Objects of this type are thread-safe and immutable. - /// - /// - public sealed class TileSetDefinition - { - private readonly InputGeometry mGeometry; - private readonly NMGenParams mBaseConfig; - private readonly Vector3 mBoundsMin; - private readonly Vector3 mBoundsMax; - - private int mWidth; - private int mDepth; - - private TileSetDefinition(int width, int depth - , Vector3 boundsMin, Vector3 boundsMax - , NMGenParams config - , InputGeometry geom) - { - // Note: The constructor is private, which is why - // the references are being stored. - mBaseConfig = config.Clone(); - mGeometry = geom; - mWidth = width; - mDepth = depth; - mBoundsMin = boundsMin; - mBoundsMax = boundsMax; - } - - /// - /// The number of tiles along the x-axis. - /// - public int Width { get { return mWidth; } } - - /// - /// The number of tiles along the z-axis. - /// - public int Depth { get { return mDepth; } } - - /// - /// The minimum AABB bounds of the tile set for build purposes. - /// - /// - /// - /// This value will be the origin of the navigation mesh created from the tile set. - /// - /// - public Vector3 BoundsMin { get { return mBoundsMin; } } - - /// - /// The maximum AABB bounds of the tile set for build purposes. - /// - public Vector3 BoundsMax { get { return mBoundsMax; } } - - /// - /// The shared input geometry used to build tiles in the set. - /// - public InputGeometry Geometry { get { return mGeometry; } } - - /// - /// The world size of the tiles in the set. - /// - public float TileWorldSize { get { return mBaseConfig.TileWorldSize; } } - - /// - /// Gets a copy of the shared NMGen configuration. - /// - /// A copy of the shared NMGen configuration. - public NMGenParams GetBaseConfig() - { - return mBaseConfig.Clone(); - } - - /// - /// Gets the bounds of the specified tile. - /// - /// - /// The x-index of the tile within the tile grid. (x, z) - /// [0 <= value < ] - /// - /// - /// The z-index of the tile within the tile grid. (x, z) - /// [0 <= value < ] - /// - /// - /// True if the bounds should be expanded by the border size configuration setting. - /// - /// The minimum AABB bounds of the tile. - /// The maximum AABB bounds of the tile. - /// True if the tile is valid, otherwise false. - public bool GetTileBounds(int tx, int tz, bool includeBorder - , out Vector3 boundsMin, out Vector3 boundsMax) - { - boundsMin = mBoundsMin; - boundsMax = mBoundsMin; - - if (tx < 0 || tz < 0 || tx >= mWidth || tz >= mDepth) - { - boundsMin = Vector3Util.Zero; - boundsMax = Vector3Util.Zero; - return false; - } - - float tcsFactor = mBaseConfig.TileSize * mBaseConfig.XZCellSize; // World tile size. - - // Note: The minimum bounds of the base configuration is - // considered to be the origin of the mesh set. - - boundsMin = mBoundsMin; - boundsMax = mBoundsMin; // This is not an error. - - boundsMin.x += tx * tcsFactor; - boundsMin.z += tz * tcsFactor; - - boundsMax.x += (tx + 1) * tcsFactor; - boundsMax.y = mBoundsMax.y; - boundsMax.z += (tz + 1) * tcsFactor; - - if (includeBorder) - { - float borderOffset = mBaseConfig.BorderSize * mBaseConfig.XZCellSize; - - boundsMin.x -= borderOffset; - boundsMin.z -= borderOffset; - - boundsMax.x += borderOffset; - boundsMax.z += borderOffset; - } - - return true; - } - - /// - /// Creates a new tile set. - /// - /// - /// - /// The bounds is normally based on the desired origin of the navigation mesh - /// and the maximum bounds of the input geometry. - /// - /// - /// The minimum AABB bounds of the set. - /// The maximum AABB counds of the set. - /// The shared NMGen configuration. - /// The input geometry. - /// A new tile set, or null on error. - public static TileSetDefinition Create(Vector3 boundsMin, Vector3 boundsMax - , NMGenParams config - , InputGeometry geom) - { - if (config == null || !config.IsValid() - || !TriangleMesh.IsBoundsValid(boundsMin, boundsMax) - || geom == null - || config.tileSize <= 0) - { - return null; - } - - int w; - int d; - - NMGen.DeriveSizeOfTileGrid(boundsMin, boundsMax - , config.XZCellSize - , config.tileSize - , out w, out d); - - if (w < 1 || d < 1) - return null; - - return new TileSetDefinition(w, d, boundsMin, boundsMax, config, geom); - } - } -} diff --git a/critterai/.svn/pristine/b4/b45ff8c48c42ab603a729da468f9da60f83cf2fa.svn-base b/critterai/.svn/pristine/b4/b45ff8c48c42ab603a729da468f9da60f83cf2fa.svn-base deleted file mode 100644 index 010b0ab2..00000000 Binary files a/critterai/.svn/pristine/b4/b45ff8c48c42ab603a729da468f9da60f83cf2fa.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/b4/b462a030ab6219fb4fce69c8a0089afdd69b603f.svn-base b/critterai/.svn/pristine/b4/b462a030ab6219fb4fce69c8a0089afdd69b603f.svn-base deleted file mode 100644 index 837f3f25..00000000 Binary files a/critterai/.svn/pristine/b4/b462a030ab6219fb4fce69c8a0089afdd69b603f.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/b4/b46f73acb7fb8d057003344ae3b3a30b00e7a9e0.svn-base b/critterai/.svn/pristine/b4/b46f73acb7fb8d057003344ae3b3a30b00e7a9e0.svn-base deleted file mode 100644 index cae6fc15..00000000 --- a/critterai/.svn/pristine/b4/b46f73acb7fb8d057003344ae3b3a30b00e7a9e0.svn-base +++ /dev/null @@ -1,712 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nav.rcn; -using org.critterai.interop; -using System.Runtime.Serialization; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// A navigation mesh based on convex polygons. - /// - /// - /// - /// See - /// An Introduction to Navigation for information on how to use the navigation mesh. - /// - /// - /// This class is used in conjunction with the class to - /// provide path planning features. - /// - /// - /// Most object references returned by this class cannot be compared for equality. - /// I.e. mesh.GetTile(0) != mesh.GetTile(0). The object state may be equal, but the - /// references are not. - /// - /// - /// This class does not have any asynchronous methods. So the return status of all - /// methods will always contain either a success or failure flag. - /// - /// - /// Warning: The serializable attribute and interface will be removed in v0.5. - /// Use instead. - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - [Serializable] - public sealed class Navmesh - : ManagedObject, ISerializable - { - // Local version is not needed. Detour includes its own mesh - // versioning. - // private const long ClassVersion = 1L; - - private const string DataKey = "d"; - - /// - /// A flag that indicates a link is external. (Context dependent.) - /// - public const ushort ExternalLink = 0x8000; - - /// - /// Indicates that a link is null. (Does not link to anything.) - /// - public const uint NullLink = 0xffffffff; - - /// - /// The maximum supported vertices per polygon. - /// - public const int MaxAllowedVertsPerPoly = 6; - - /// - /// The maximum allowed area value. - /// - public const byte MaxArea = 63; - - /// - /// Represents an unwalkable area. - /// - /// - /// - /// When a data element is given this value it is considered to no longer be - /// assigned to a walkable area. (It usually becomes an obstruction.) - /// - /// - /// This is also the minimum value that can be used as an area value. - /// - /// - public const byte NullArea = 0; - - /// - /// The reference for a null polygon. (Does not exist.) - /// - public const uint NullPoly = 0; - - /// - /// The reference for a null tile. (Does not exist.) - /// - public const uint NullTile = 0; - - /// - /// Represents an polygon index that does not point to anything. - /// - public const ushort NullIndex = 0xffff; - - /// - /// dtNavMesh object. - /// - internal IntPtr root; - - private Navmesh(IntPtr mesh) - : base(AllocType.External) - { - root = mesh; - } - - private Navmesh(SerializationInfo info, StreamingContext context) - : base(AllocType.External) - { - root = IntPtr.Zero; - - if (info.MemberCount != 1) - return; - - byte[] data = (byte[])info.GetValue(DataKey, typeof(byte[])); - NavmeshEx.dtnmBuildDTNavMeshFromRaw(data, data.Length, true, ref root); - } - - /// - /// Destructor - /// - ~Navmesh() - { - RequestDisposal(); - } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public override bool IsDisposed - { - get { return (root == IntPtr.Zero); } - } - - /// - /// Request all resources controlled by the object be immediately freed and the object - /// marked as disposed. - /// - public override void RequestDisposal() - { - if (root != IntPtr.Zero) - { - NavmeshEx.dtnmFreeNavMesh(ref root, false); - root = IntPtr.Zero; - } - } - - /// - /// Returns the configuration parameters used to initialize the navigation mesh. - /// - /// The configuration parameters used to initialize the navigation mesh. - public NavmeshParams GetConfig() - { - NavmeshParams result = new NavmeshParams(); - NavmeshEx.dtnmGetParams(root, result); - return result; - } - - /// - /// Adds a tile to the navigation mesh. - /// - /// The tile data. - /// - /// The desired reference for the tile. - /// (Or if the reference doesn't matter or is not known.) - /// - /// The actual reference assigned to the tile. - /// The flags for the operation. - public NavStatus AddTile(NavmeshTileData tileData - , uint desiredTileRef - , out uint resultTileRef) - { - if (tileData == null - || tileData.IsOwned - || tileData.Size == 0) - { - resultTileRef = 0; - return NavStatus.Failure | NavStatus.InvalidParam; - } - - resultTileRef = 0; - - return NavmeshEx.dtnmAddTile(root - , tileData - , desiredTileRef - , ref resultTileRef); - } - - /// - /// Removes the specified tile from the mesh. - /// - /// The tile reference. - /// The flags for the operation. - public NavStatus RemoveTile(uint tileRef) - { - int trash = 0; - IntPtr dump = IntPtr.Zero; - return NavmeshEx.dtnmRemoveTile(root, tileRef, ref dump, ref trash); - } - - /// - /// Derives the tile grid location based on the provided world space position. - /// - /// Position - /// The tile's grid x-location. - /// The tiles's grid z-location. - public void DeriveTileLocation(Vector3 position - , out int x - , out int z) - { - x = 0; - z = 0; - NavmeshEx.dtnmCalcTileLoc(root, ref position, ref x, ref z); - } - - /// - /// Gets the tile at the specified grid location. - /// - /// The tile grid x-location. - /// The tile grid z-location. - /// The tile layer. - /// The tile at the specified grid location. (May be empty.) - public NavmeshTile GetTile(int x, int z, int layer) - { - IntPtr tile = NavmeshEx.dtnmGetTileAt(root, x, z, layer); - if (tile == IntPtr.Zero) - return null; - return new NavmeshTile(this, tile); - } - - /// - /// Gets all tiles at the specified grid location. (All layers.) - /// - /// - /// - /// Some tiles in the result may be empty. (Zero polygon count.) - /// - /// - /// The tile grid x-location. - /// The tile grid z-location. - /// The result tiles. - /// The number of tiles returned in the buffer. - public int GetTiles(int x, int z, NavmeshTile[] buffer) - { - IntPtr[] tiles = new IntPtr[buffer.Length]; - - int tileCount = NavmeshEx.dtnmGetTilesAt(root, x, z, tiles, tiles.Length); - - for (int i = 0; i < tileCount; i++) - { - buffer[i] = new NavmeshTile(this, tiles[i]); - } - - return tileCount; - } - - /// - /// Gets the reference for the tile at the specified grid location. - /// - /// The tile grid x-location. - /// The tile grid z-location. - /// The tiles layer. - /// The tile reference, or zero if there is no tile at the location. - public uint GetTileRef(int x, int z, int layer) - { - return NavmeshEx.dtnmGetTileRefAt(root, x, z, layer); - } - - /// - /// Gets a tile using its reference. - /// - /// The reference of the tile. - /// The tile, or null if none was found. - public NavmeshTile GetTileByRef(uint tileRef) - { - IntPtr tile = NavmeshEx.dtnmGetTileByRef(root, tileRef); - if (tile == IntPtr.Zero) - return null; - return new NavmeshTile(this, tile); - } - - /// - /// The maximum number of tiles supported by the navigation mesh. - /// - /// The maximum number of tiles supported by the navigation mesh. - public int GetMaxTiles() - { - return NavmeshEx.dtnmGetMaxTiles(root); - } - - /// - /// Gets a tile from the tile buffer. - /// - /// - /// The index of the tile. [Limits: 0 <= index < ] - /// - /// The flags for the operation. - public NavmeshTile GetTile(int tileIndex) - { - IntPtr tile = NavmeshEx.dtnmGetTile(root, tileIndex); - if (tile == IntPtr.Zero) - return null; - return new NavmeshTile(this, tile); - } - - /// - /// Gets a polygon and its tile. - /// - /// The reference of the polygon. - /// The tile the polygon belongs to. - /// The polygon. - /// The flags for the operation. - public NavStatus GetTileAndPoly(uint polyRef - , out NavmeshTile tile - , out NavmeshPoly poly) - { - IntPtr pTile = IntPtr.Zero; - IntPtr pPoly = IntPtr.Zero; - - NavStatus status = NavmeshEx.dtnmGetTileAndPolyByRef(root - , polyRef - , ref pTile - , ref pPoly); - - if (NavUtil.Succeeded(status)) - { - tile = new NavmeshTile(this, pTile); - poly = (NavmeshPoly)Marshal.PtrToStructure(pPoly - , typeof(NavmeshPoly)); - } - else - { - tile = null; - poly = new NavmeshPoly(); - } - - return status; - - } - - /// - /// Indicates whether or not the specified polygon reference is valid. - /// - /// The reference to check. - /// True if the provided reference is valid. - public bool IsValidPolyRef(uint polyRef) - { - return NavmeshEx.dtnmIsValidPolyRef(root, polyRef); - } - - /// - /// Gets the endpoints for an off-mesh connection, ordered by 'direction of travel'. - /// - /// - /// - /// Off-mesh connections are stored in the navigation mesh as special 2-vertex polygons - /// with a single edge. At least one of the vertices is expected to be inside a normal - /// polygon. So an off-mesh connection is "entered" from a normal polygon at one of its - /// endpoints. This is the polygon identified by . - /// - /// - /// - /// The reference of the polygon that contains the start point. - /// - /// The off-mesh connection's reference. - /// The start point. (Out) - /// The end point. (Out) - /// The flags for the operation. - public NavStatus GetConnectionEndpoints(uint startPolyRef - , uint connectionPolyRef - , out Vector3 startPoint - , out Vector3 endPoint) - { - startPoint = Vector3Util.Zero; - endPoint = Vector3Util.Zero; - return NavmeshEx.dtnmGetConnectionEndPoints(root - , startPolyRef - , connectionPolyRef - , ref startPoint - , ref endPoint); - } - - /// - /// Gets an off-mesh connection. - /// - /// The reference of the off-mesh connection. - /// The off-mesh connection. - public NavmeshConnection GetConnectionByRef(uint polyRef) - { - IntPtr conn = NavmeshEx.dtnmGetOffMeshConnectionByRef(root, polyRef); - - NavmeshConnection result; - if (conn == IntPtr.Zero) - result = new NavmeshConnection(); - else - result = (NavmeshConnection)Marshal.PtrToStructure(conn - , typeof(NavmeshConnection)); - - return result; - } - - /// - /// Returns the flags for the specified polygon. - /// - /// The reference of the polygon. - /// The polygon flags. - /// The flags for the operation. - /// - public NavStatus GetPolyFlags(uint polyRef, out ushort flags) - { - flags = 0; - return NavmeshEx.dtnmGetPolyFlags(root, polyRef, ref flags); - } - - /// - /// Sets the flags for the specified polygon. - /// - /// The reference of the polygon. - /// The polygon flags. - /// The flags for the operation. - /// - public NavStatus SetPolyFlags(uint polyRef, ushort flags) - { - return NavmeshEx.dtnmSetPolyFlags(root, polyRef, flags); - } - - /// - /// Returns the area of the specified polygon. - /// - /// The reference of the polygon. - /// The area of the polygon. - /// The flags for the operation. - /// - public NavStatus GetPolyArea(uint polyRef, out byte area) - { - area = 0; - return NavmeshEx.dtnmGetPolyArea(root, polyRef, ref area); - } - - /// - /// Sets the area of the specified polygon. - /// - /// The reference of the polygon. - /// The area of the polygon. - /// [Limit: <= ] - /// The flags for the operation. - /// - public NavStatus SetPolyArea(uint polyRef, byte area) - { - return NavmeshEx.dtnmSetPolyArea(root, polyRef, area); - } - - /// - /// Gets a serialized version of the mesh. - /// - /// The serialized mesh. - public byte[] GetSerializedMesh() - { - if (IsDisposed) - return null; - - IntPtr data = IntPtr.Zero; - int dataSize = 0; - - NavmeshEx.dtnmGetNavMeshRawData(root, ref data, ref dataSize); - - if (dataSize == 0) - return null; - - byte[] resultData = UtilEx.ExtractArrayByte(data, dataSize); - - NavmeshEx.dtnmFreeBytes(ref data); - - return resultData; - } - - /// - /// Gets serialization data for the object. - /// - /// Serialization information. - /// Serialization context. - [System.Obsolete] - public void GetObjectData(SerializationInfo info - , StreamingContext context) - { - if (IsDisposed) - return; - - // info.AddValue(VersionKey, ClassVersion); - info.AddValue(DataKey, GetSerializedMesh()); - } - - /// - /// Creates a single-tile navigation mesh. - /// - /// The tile build data. - /// The result mesh. - /// The flags for the operation. - /// - public static NavStatus Create(NavmeshTileBuildData buildData - , out Navmesh resultMesh) - { - IntPtr navMesh = IntPtr.Zero; - - NavStatus status = NavmeshEx.dtnmBuildSingleTileMesh(buildData - , ref navMesh); - - if (NavUtil.Succeeded(status)) - resultMesh = new Navmesh(navMesh); - else - resultMesh = null; - - return status; - } - - /// - /// Creates a navigation mesh from data obtained from the - /// method. - /// - /// The serialized mesh. - /// The result mesh. - /// The flags for the operation. - /// - public static NavStatus Create(byte[] serializedMesh - , out Navmesh resultMesh) - { - return UnsafeCreate(serializedMesh, true, out resultMesh); - } - - private static NavStatus UnsafeCreate(byte[] serializedMesh - , bool safeStorage - , out Navmesh resultMesh) - { - if (serializedMesh == null || serializedMesh.Length == 0) - { - resultMesh = null; - return NavStatus.Failure | NavStatus.InvalidParam; - } - - IntPtr root = IntPtr.Zero; - - NavStatus status = NavmeshEx.dtnmBuildDTNavMeshFromRaw(serializedMesh - , serializedMesh.Length - , safeStorage - , ref root); - - if (NavUtil.Succeeded(status)) - resultMesh = new Navmesh(root); - else - resultMesh = null; - - return status; - } - - /// - /// Creates an empty navigation mesh ready for tiles to be added. - /// - /// - /// This is the method used when creating new multi-tile meshes. - /// Tiles are added using the method. - /// - /// The mesh configuration. - /// The result mesh. - /// The flags for the operation. - /// - public static NavStatus Create(NavmeshParams config - , out Navmesh resultMesh) - { - if (config == null || config.maxTiles < 1) - { - resultMesh = null; - return NavStatus.Failure | NavStatus.InvalidParam; - } - - IntPtr root = IntPtr.Zero; - - NavStatus status = NavmeshEx.dtnmInitTiledNavMesh(config, ref root); - - if (NavUtil.Succeeded(status)) - resultMesh = new Navmesh(root); - else - resultMesh = null; - - return status; - } - - /// - /// Extracts the tile data from a serialized navigation mesh. - /// - /// - /// - /// Tile data is normally preserved by serializing - /// the the content of the objects used to - /// create the navigation mesh. That is the most efficient method - /// and should be used whenever possible. - /// - /// - /// This method can be used to extract the tile data when - /// the original data is not available. It should only be used as - /// a backup to the normal method since this method is not efficient. - /// - /// - /// Always check the header polygon count - /// of the resulting objects before use since some tiles - /// in the navigation mesh may be empty. The - /// field will be null for empty tiles. - /// - /// - /// A valid serialized navigation mesh. - /// - /// The extracted tile data. [Length: ] - /// - /// The navigation mesh's configuration. - /// The flags for the operation. - public static NavStatus ExtractTileData(byte[] serializedMesh - , out NavmeshTileExtract[] tileData - , out NavmeshParams config) - { - /* - * Design notes: - * - * Normally, the only way to get tile data out of a navigation mesh - * is when the tile data is NOT owned by the mesh. This is not - * permitted for normal mesh objects, which is why the RemoveTile() method - * never returns the tile data. - * - * The most efficient way to extract the data is to get it directly - * from the serialized data. But that would be a code maintenance issue. - * (Duplicating the mesh creation process.) So I'm using this rather - * convoluted method instead. - * - */ - - if (serializedMesh == null) - { - tileData = null; - config = null; - return NavStatus.Failure | NavStatus.InvalidParam; - } - - Navmesh mesh; - NavStatus status = Navmesh.UnsafeCreate(serializedMesh, false, out mesh); - - if ((status & NavStatus.Failure) != 0) - { - tileData = null; - config = null; - return status; - } - - config = mesh.GetConfig(); - - int count = mesh.GetMaxTiles(); - - tileData = new NavmeshTileExtract[count]; - - if (count == 0) - return NavStatus.Sucess; - - for (int i = 0; i < count; i++) - { - NavmeshTile tile = mesh.GetTile(i); - - tileData[i].header = tile.GetHeader(); - - if (tileData[i].header.polyCount == 0) - // Tile not in use. - continue; - - tileData[i].tileRef = tile.GetTileRef(); - - IntPtr tdata = new IntPtr(); - int tsize = 0; - - NavmeshEx.dtnmRemoveTile(mesh.root, tileData[i].tileRef, ref tdata, ref tsize); - - tileData[i].data = UtilEx.ExtractArrayByte(tdata, tsize); - - NavmeshEx.dtnmFreeBytes(ref tdata); - } - - return NavStatus.Sucess; - } - } -} diff --git a/critterai/.svn/pristine/b5/b5024b0f529bc2af642c79b078425dae9ddca358.svn-base b/critterai/.svn/pristine/b5/b5024b0f529bc2af642c79b078425dae9ddca358.svn-base deleted file mode 100644 index 868229a8..00000000 --- a/critterai/.svn/pristine/b5/b5024b0f529bc2af642c79b078425dae9ddca358.svn-base +++ /dev/null @@ -1,182 +0,0 @@ -/* - * This feature removed from v0.4. - * - * Not tested. - * - * TODO: EVAL: v0.5: Is this really useful? - * - */ - -//* -// * Copyright (c) 2012 Stephen A. Pratt -// * -// * Permission is hereby granted, free of charge, to any person obtaining a copy -// * of this software and associated documentation files (the "Software"), to deal -// * in the Software without restriction, including without limitation the rights -// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// * copies of the Software, and to permit persons to whom the Software is -// * furnished to do so, subject to the following conditions: -// * -// * The above copyright notice and this permission notice shall be included in -// * all copies or substantial portions of the Software. -// * -// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// * THE SOFTWARE. -// */ -//using System.Collections.Generic; -//using org.critterai.nmbuild; -//using org.critterai.nmbuild.u3d.editor; -//using UnityEngine; - -//[System.Serializable] -//public sealed class ColliderCompiler -// : InputBuildProcessor -//{ -// public bool allowMeshColocation = false; - -// public string Name { get { return name; } } -// public override int Priority { get { return NMBuild.MinPriority - 1; } } -// public override bool DuplicatesAllowed { get { return false; } } - -// public override bool ProcessInput(InputBuildContext context, InputBuildState state) -// { -// if (context != null) -// { -// switch (state) -// { -// case InputBuildState.CompileInput: - -// Compile(context); -// break; - -// case InputBuildState.LoadComponents: - -// Load(context); -// break; -// } -// } - -// return true; -// } - -// private void Load(InputBuildContext context) -// { -// context.info.loaderCount++; - -// Collider[] items = context.GetFromScene(); - -// if (items.Length == 0) -// return; - -// List litems = new List(); - -// int colocated = 0; -// int unknown = 0; - -// foreach (Collider item in items) -// { -// MeshFilter filter = item.GetComponent(); - -// if (filter) -// { -// colocated++; -// if (!allowMeshColocation) -// continue; -// } - -// if (ColliderHelper.IsSupported(item)) -// litems.Add(item); -// else -// unknown++; -// } - -// context.components.AddRange(litems.ToArray()); - -// string msg = string.Format( -// "{0}: Loaded {1} Colliders. Ignored {2} unsupported. {3} colocated with mesh filters." -// + " Colocation allowed: {4}" -// , Name, litems.Count, unknown, colocated, allowMeshColocation); - -// context.Log(msg, this); -// } - -// private void Compile(InputBuildContext context) -// { -// context.info.compilerCount++; - -// ColliderHelper colliderHelper = new ColliderHelper(); - -// InputGeometryCompiler inputCompiler = context.geomCompiler; - -// List master = new List(context.components); -// List areas = new List(context.areas); - -// Queue combineInstances = new Queue(); - -// int count = 0; -// int ignored = 0; -// while (master.Count > 0) -// { -// byte area = 0; - -// for (int i = master.Count - 1; i >= 0; i--) -// { -// Component item = master[i]; - -// if (item is Collider && ColliderHelper.IsSupported((Collider)item)) -// { -// if (!allowMeshColocation && item.GetComponent()) -// { -// ignored++; -// areas.RemoveAt(i); -// master.RemoveAt(i); -// } -// else -// { -// if (combineInstances.Count == 0) -// area = areas[i]; - -// if (areas[i] == area) -// { -// count++; - -// CombineInstance ci; - -// if (colliderHelper.Get((Collider)item, out ci)) -// combineInstances.Enqueue(ci); - -// areas.RemoveAt(i); -// master.RemoveAt(i); -// } -// } -// } -// else -// { -// areas.RemoveAt(i); -// master.RemoveAt(i); -// } -// } - -// if (combineInstances.Count > 0) -// org.critterai.nmbuild.u3d.MeshUtil.CombineMeshes(combineInstances, area, inputCompiler); - -// combineInstances.Clear(); -// } - -// colliderHelper.Dispose(); - -// if (ignored > 0) -// { -// context.Log(string.Format("{0}: Ignored {1} colliders colocated with MeshFilters." -// , Name, ignored) -// , this); -// } - -// context.Log(string.Format("{0}: Compiled {1} colliders.", Name, count), this); -// } -//} diff --git a/critterai/.svn/pristine/b5/b5f847287b910624710ae6e66e00b52b36d45369.svn-base b/critterai/.svn/pristine/b5/b5f847287b910624710ae6e66e00b52b36d45369.svn-base deleted file mode 100644 index c69d6606..00000000 --- a/critterai/.svn/pristine/b5/b5f847287b910624710ae6e66e00b52b36d45369.svn-base +++ /dev/null @@ -1,92 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {B588A21A-1C12-4B20-83CE-D84F387FEEA1} - Library - Properties - org.critterai - cai-nmbuild-extras-u3d-editor - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - ..\bin\Release\cai-nmbuild-extras-u3d-editor.xml - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEditor.dll - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - Properties\AssemblyInfo.cs - - - - - {8093F287-EA45-46AB-AF58-710DA654392E} - cai-nav-u3d-editor - - - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8} - cai-nmbuild-extras-u3d - - - {8823F2CF-1139-41BF-BD47-A456B7FEE336} - cai-nmbuild-u3d-editor - - - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336} - cai-nmbuild - - - {9DFC1FE0-6469-4A04-AB13-9EAC59087802} - cai-nmgen - - - {1FF01BFD-2593-406A-959E-D4D84CEB662C} - cai-util-u3d-editor - - - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE} - cai-util-u3d - - - {C4B32B85-13F0-42B8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/b6/b63b074959ff2180b74c82b4f9e00c5c47829530.svn-base b/critterai/.svn/pristine/b6/b63b074959ff2180b74c82b4f9e00c5c47829530.svn-base deleted file mode 100644 index cbe757fa..00000000 --- a/critterai/.svn/pristine/b6/b63b074959ff2180b74c82b4f9e00c5c47829530.svn-base +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using System.Threading; -using org.critterai.nmgen; -using org.critterai.nav; - -namespace org.critterai.nmbuild -{ - /// - /// Provides a simple multi-threaded processsor for objects. - /// - /// - /// - /// The expected use case is that the processor is run on a separate thread. Clients - /// then create and pass it tasks to be run. The processor will run tasks concurrently up - /// to its maximum allowed, then queue remaining tasks for later. - /// - /// - /// Individual tasks are aborted via the method. The - /// processor will clear the task from its queue when it encounters the task for processing, - /// so the task count will not decrement immediately. - /// - /// - /// Warning: A zombie worker thread will result if a task does not meet its - /// obligation by throwing an exception in its - /// method. The worker thread will become un-usable for - /// new tasks. - /// - /// - public sealed class BuildTaskProcessor - { - /* - * Design notes: - * - * Everyting is locked on the task queue. - * - * The processors are not created or their threads started until the first task is queued. - * So the processor array will contain nulls until then. - * This is important to the design in Unity. Want to keep the threads in - * the editor to a minimum until they are actually needed. - */ - - /// - /// A standard value for high priority tasks. - /// - public const int HighPriority = 3000; - - /// - /// A standard value for medium priority tasks. - /// - public const int MediumPriority = 2000; - - /// - /// A standard value for low priority tasks. - /// - public const int LowPriority = 1000; - - private class Processor - { - private readonly Object mSemaphore = new Object(); - private IBuildTask mTask; - private bool mAbort = false; - - public void Abort() - { - mAbort = true; - } - - public void RunTask(IBuildTask task) - { - lock (mSemaphore) { mTask = task; } - } - - public void Run() - { - while (!mAbort) - { - IBuildTask task = null; - - lock (mSemaphore) - { - if (mTask != null && mTask.TaskState == BuildTaskState.Inactive) - { - task = mTask; - mTask = null; - } - } - - if (task == null) - Thread.Sleep(100); - else - { - // Have to re-check. State may have changed. - if (task.TaskState == BuildTaskState.Inactive) - { - /* - * Design note: - * - * This is a trade-off to deal with poorly written tasks. Technically, - * the task is responsible for catching and reporting its own - * exceptions. But if it doesn't it can bring down the processor - * thread. - * - * This method forces the task to abort so the main manager can detect - * and discard it. But if the task is so poorly written that the - * abort doesn't work, or throws another exception, then the processor - * will become a zombie, unresponsive to new requests from the manager. - */ - try - { - task.Run(); - } - catch (Exception ex) - { - task.Abort("Exception detected by processor: " + ex.Message); - } - } - } - } - } - } - - private const string AbortMessage = "Task processor shutdown."; - - private static int mStandardSleep = 10; - private static int mIdleSleep = 100; - - /// - /// The length of time the processor will idle when there are no tasks to process. - /// [Units: Milliseconds] - /// [Limit: >= 1] - /// - public static int IdleSleep - { - get { return mIdleSleep; } - set { mIdleSleep = Math.Max(1, value); } - } - - /// - /// The length of time the processor will idle when there are tasks being processed. - /// [Units: Milliseconds] - /// [Limit: >= 1] - /// - public static int StandardSleep - { - get { return mStandardSleep; } - set { mStandardSleep = Math.Max(1, value);} - } - - private readonly List mTaskQueue = new List(); - - // This sort order is correct. The queue list is emptied from the end. - private readonly PriorityComparer mComparer = new PriorityComparer(true); - - private readonly Processor[] mProcessors; - private readonly IBuildTask[] mActiveTasks; - - private int mTaskCount; - private bool mIsRunning; - private bool mAbort; - - /// - /// Constructor - /// - /// - /// The maximum permitted active tasks before new tasks are queued. [Limit: >= 1] - /// - public BuildTaskProcessor(int maxConcurrent) - { - maxConcurrent = Math.Max(1, maxConcurrent); - mProcessors = new Processor[maxConcurrent]; - mActiveTasks = new IBuildTask[maxConcurrent]; - } - - /// - /// The number of active and queued tasks. - /// - public int TaskCount { get { return mTaskCount; } } - - /// - /// The processor is running. - /// - public bool IsRunning { get { return mIsRunning; } } - - /// - /// The maximum permitted active tasks before new tasks are queued. - /// - /// - /// - /// This also represents the number of background worker threads the processor creates. - /// - /// - public int MaxConcurrent { get { return mProcessors.Length; } } - - /// - /// Aborts the processor. - /// - /// - /// - /// The processor will call the abort method only on active tasks. Queued tasks will - /// simply be abandoned. - /// - /// - public void Abort() - { - lock (mTaskQueue) - { - if (mAbort) - return; - - mAbort = true; - - mTaskQueue.Clear(); - - if (!mIsRunning) - mTaskCount = 0; - } - } - - /// - /// Queues a task to be run. - /// - /// - /// - /// The processor will only queue inactive tasks that are threadsafe. - /// - /// - /// The task to queue. - /// True if the task was accepted. - public bool QueueTask(IBuildTask task) - { - if (task == null || task.TaskState != BuildTaskState.Inactive || !task.IsThreadSafe) - return false; - - lock (mTaskQueue) - { - if (mAbort) - return false; - - if (mProcessors[0] == null) - { - for (int i = 0; i < mProcessors.Length; i++) - { - mProcessors[i] = new Processor(); - Thread t = new Thread(new ThreadStart(mProcessors[i].Run)); - t.Start(); - } - } - - mTaskQueue.Add(task); - - mTaskCount = mTaskQueue.Count; - foreach (IBuildTask item in mActiveTasks) - { - if (item != null) - mTaskCount++; - } - - return true; - } - } - - /// - /// Runs the processor. - /// - /// - /// - /// This method will block until the processor is aborted. So the expected use - /// case is that this method will be run on its own thread. - /// - /// - /// Processors are single use. They cannot be run again after they are aborted. - /// - /// - public void Run() - { - lock (mTaskQueue) - { - if (mAbort || mIsRunning) - return; - - mIsRunning = true; - } - - while (!mAbort) - { - int activeCount = 0; - - lock (mTaskQueue) - { - mTaskQueue.Sort(mComparer); - - for (int i = 0; i < mActiveTasks.Length; i++) - { - IBuildTask task = mActiveTasks[i]; - - if (task == null || task.IsFinished) - { - // Task complete. Clear it out. - mActiveTasks[i] = null; - task = null; - } - else - { - // Task still being processed. - activeCount++; - continue; - } - - // Need to assign a new task to this slot. - while (task == null && mTaskQueue.Count > 0) - { - task = mTaskQueue[mTaskQueue.Count - 1]; - mTaskQueue.RemoveAt(mTaskQueue.Count - 1); - - if (task.TaskState != BuildTaskState.Inactive) - task = null; - } - - if (task != null) - { - // Found a task to run. - activeCount++; - mActiveTasks[i] = task; - mProcessors[i].RunTask(task); - } - } - - mTaskCount = mTaskQueue.Count + activeCount; - } - - // Pause longer if there are no active tasks. - if (activeCount > 0) - Thread.Sleep(10); - else - Thread.Sleep(100); - } - - mTaskCount = 0; - - foreach (Processor processor in mProcessors) - { - if (processor == null) - // The processors were never started. - break; - - processor.Abort(); - } - - mIsRunning = false; - } - } -} diff --git a/critterai/.svn/pristine/b6/b66ea8e812f2d7798289eec35d48d28b2e95ce7f.svn-base b/critterai/.svn/pristine/b6/b66ea8e812f2d7798289eec35d48d28b2e95ce7f.svn-base deleted file mode 100644 index 438be9ea..00000000 --- a/critterai/.svn/pristine/b6/b66ea8e812f2d7798289eec35d48d28b2e95ce7f.svn-base +++ /dev/null @@ -1,124 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef RECASTALLOC_H -#define RECASTALLOC_H - -/// Provides hint values to the memory allocator on how long the -/// memory is expected to be used. -enum rcAllocHint -{ - RC_ALLOC_PERM, ///< Memory will persist after a function call. - RC_ALLOC_TEMP ///< Memory used temporarily within a function. -}; - -/// A memory allocation function. -// @param[in] size The size, in bytes of memory, to allocate. -// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use. -// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. -/// @see rcAllocSetCustom -typedef void* (rcAllocFunc)(int size, rcAllocHint hint); - -/// A memory deallocation function. -/// @param[in] ptr A pointer to a memory block previously allocated using #rcAllocFunc. -/// @see rcAllocSetCustom -typedef void (rcFreeFunc)(void* ptr); - -/// Sets the base custom allocation functions to be used by Recast. -/// @param[in] allocFunc The memory allocation function to be used by #rcAlloc -/// @param[in] freeFunc The memory de-allocation function to be used by #rcFree -void rcAllocSetCustom(rcAllocFunc *allocFunc, rcFreeFunc *freeFunc); - -/// Allocates a memory block. -/// @param[in] size The size, in bytes of memory, to allocate. -/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use. -/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. -/// @see rcFree -void* rcAlloc(int size, rcAllocHint hint); - -/// Deallocates a memory block. -/// @param[in] ptr A pointer to a memory block previously allocated using #rcAlloc. -/// @see rcAlloc -void rcFree(void* ptr); - - -/// A simple dynamic array of integers. -class rcIntArray -{ - int* m_data; - int m_size, m_cap; - inline rcIntArray(const rcIntArray&); - inline rcIntArray& operator=(const rcIntArray&); -public: - - /// Constructs an instance with an initial array size of zero. - inline rcIntArray() : m_data(0), m_size(0), m_cap(0) {} - - /// Constructs an instance initialized to the specified size. - /// @param[in] n The initial size of the integer array. - inline rcIntArray(int n) : m_data(0), m_size(0), m_cap(0) { resize(n); } - inline ~rcIntArray() { rcFree(m_data); } - - /// Specifies the new size of the integer array. - /// @param[in] n The new size of the integer array. - void resize(int n); - - /// Push the specified integer onto the end of the array and increases the size by one. - /// @param[in] item The new value. - inline void push(int item) { resize(m_size+1); m_data[m_size-1] = item; } - - /// Returns the value at the end of the array and reduces the size by one. - /// @return The value at the end of the array. - inline int pop() { if (m_size > 0) m_size--; return m_data[m_size]; } - - /// The value at the specified array index. - /// @warning Does not provide overflow protection. - /// @param[in] i The index of the value. - inline const int& operator[](int i) const { return m_data[i]; } - - /// The value at the specified array index. - /// @warning Does not provide overflow protection. - /// @param[in] i The index of the value. - inline int& operator[](int i) { return m_data[i]; } - - /// The current size of the integer array. - inline int size() const { return m_size; } -}; - -/// A simple helper class used to delete an array when it goes out of scope. -/// @note This class is rarely if ever used by the end user. -template class rcScopedDelete -{ - T* ptr; - inline T* operator=(T* p); -public: - - /// Constructs an instance with a null pointer. - inline rcScopedDelete() : ptr(0) {} - - /// Constructs an instance with the specified pointer. - /// @param[in] p An pointer to an allocated array. - inline rcScopedDelete(T* p) : ptr(p) {} - inline ~rcScopedDelete() { rcFree(ptr); } - - /// The root array pointer. - /// @return The root array pointer. - inline operator T*() { return ptr; } -}; - -#endif diff --git a/critterai/.svn/pristine/b7/b71bb32408d27f9d77b99c933e0d7d499ec6f88d.svn-base b/critterai/.svn/pristine/b7/b71bb32408d27f9d77b99c933e0d7d499ec6f88d.svn-base deleted file mode 100644 index c0601924..00000000 --- a/critterai/.svn/pristine/b7/b71bb32408d27f9d77b99c933e0d7d499ec6f88d.svn-base +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents the open space above a solid span within the cell column of - * a heightfield. - *

      - * - *

      - *

      - * @see Introduction to Heightfields - * @see HeightSpan - */ -public final class OpenHeightSpan -{ - /* - * Design Notes: - * - * Structurally this class is so similar with HeightSpan that it can - * extend HeightSpan. But it is being kept separate for clarity. - * As an independent class it can use the floor and ceiling nomenclature - * that makes reading code much easier. - * - */ - - /** - * A value representing a span in the null region. Spans in the null - * are considered not traversable. - *

      Spans in the null-region are often skipped during processing. - * Other processing is only applied when the null-region is involved.

      - */ - public static final int NULL_REGION = 0; - - /** - * Temporary flags associated with the span. - *

      The value is meaningless outside the operation in which the flags - * are needed. Since various operations may use this flag for their own - * purpose, always reset the flag after use.

      - *

      The contract is that an operation expects the flag to be zero when - * it receives the span data.

      - */ - public int flags = 0; - - private int mRegionID = 0; - private int mDistanceToRegionCore = 0; - private int mDistanceToBorder = 0; - - private int mFloor; - private int mHeight; - - private OpenHeightSpan mNext = null; - private OpenHeightSpan mNeighborConnection0 = null; - private OpenHeightSpan mNeighborConnection1 = null; - private OpenHeightSpan mNeighborConnection2 = null; - private OpenHeightSpan mNeighborConnection3 = null; - - /** - * Constructor - * @param floor The base height of the span. - * @param height The height of the unobstructed space above the floor. - * {@link Integer#MAX_VALUE} is generally used to indicate no obstructions - * exist above the floor. - * @throws IllegalArgumentException If the floor is below zero or the - * height is less than 1. - */ - public OpenHeightSpan(int floor, int height) - throws IllegalArgumentException - { - if (floor < 0) - throw new IllegalArgumentException("Floor is less than zero."); - if (height < 1) - throw new IllegalArgumentException("Height is less than one."); - this.mFloor = floor; - this.mHeight = height; - } - - /** - * The height of the ceiling. - * @return The height of the ceiling. - */ - public int ceiling() { return mFloor + mHeight; } - - /** - * The distance this span is from the nearest border of the heightfield - * it belongs to. - * @return The distance this span is from the nearest heightfield border. - */ - public int distanceToBorder() { return mDistanceToBorder; } - - /** - * The distance this span is from the core of the heightfield region - * it belongs to. - * @return The distance this span is from the core of the heightfield - * region it belongs to. - */ - public int distanceToRegionCore() { return mDistanceToRegionCore; } - - /** - * The base height of the span. - * @return The base height of the span. - */ - public int floor() { return mFloor; } - - /** - * Populates an array with information on the regions a span's - * 8-neighbors are assigned to. - *

      If necessary, both of a diagonal neighbor's associated - * axis-neighbors will be used to detect the diagonal neighbor.

      - *

      Special case: Since, diagonal neighbors are detected through - * axis-neighbors, if the span has no axis-neighbors in the - * direction of the diagonal-neighbor, then the diagonal-neighbor - * will not be detected.

      - *

      Neighbor order:
      - * 0 - 3 : Standard axis-neighbor order. - * (E.g. Starting at standard zero direction.)
      - * 4 - 7 : Standard diagonal neighbors. - * (E.g. Clockwise of associated axis-neighbor.)
      - * So the standard diagonal neigbor of an axis-neighbor can be - * found at "axis-neighbor index + 4". - *

      - * @param out An array of at least size 8. - * @see Neighbor Searches - */ - public void getDetailedRegionMap(int[] out, int insertIndex) - { - for (int i = 0; i < 8; i++) - out[insertIndex+i] = NULL_REGION; - OpenHeightSpan nSpan = null; - OpenHeightSpan nnSpan = null; - for (int dir = 0; dir < 4; dir++) - { - nSpan = getNeighbor(dir); - if (nSpan != null) - { - out[insertIndex+dir] = nSpan.regionID(); - nnSpan = nSpan.getNeighbor((dir+1) & 0x3); - if (nnSpan != null) - out[insertIndex+dir+4] = nnSpan.regionID(); - nnSpan = nSpan.getNeighbor((dir+3) & 0x3); - if (nnSpan != null) - out[insertIndex+((dir+3)&0x3)+4] = nnSpan.regionID(); - } - } - } - - /** - * Gets a reference to the span that is considered an axis-neighbor to - * this span for the specified direction. Uses the standard direction - * indices (0 through 3) where zero is the neighbor offset at (-1, 0) - * and the search proceeds clockwise. - * @param direction The direction to search. - * @return A reference to the axis-neighbor in the specified direction. - * Or null if there is no neighbor in the direction or the direction - * index is invalid. - * @see Neighbor Searches - */ - public OpenHeightSpan getNeighbor(int direction) - { - switch (direction) - { - case 0: return mNeighborConnection0; - case 1: return mNeighborConnection1; - case 2: return mNeighborConnection2; - case 3: return mNeighborConnection3; - default: return null; - } - } - - /** - * The height of the unobstructed space above the floor. - *

      {@link Integer#MAX_VALUE} is generally used to indicate no - * obstructions exist above the floor.

      - * @return The height of the unobstructed space above the floor. - */ - public int height() { return mHeight; } - - /** - * The next span higher in the span's heightfield column. - *

      The space between this span's ceiling and the next span's floor is - * considered to be obstructed space.

      - * @return The next higher span in the span's heightfield column. - * Or null if there is no heigher span. - */ - public OpenHeightSpan next() { return mNext; } - - /** - * The heightfield region this span belongs to. - *

      This value will never be less than {@link #NULL_REGION} - * for a finished, properly constructed heightfield.

      - *

      For a partially constructed heightfield the contract - * is that any region ID less than or equal to {@link #NULL_REGION} - * belongs to the null region.

      - * @return The heightfield region this span belongs to. - */ - public int regionID() { return mRegionID; } - - /** - * Set the distance this span is from the nearest border of the - * heightfield it belongs to. - * @param value The new distance. Auto-clamped at a minimum of zero. - */ - public void setDistanceToBorder(int value) - { - mDistanceToBorder = Math.max(value, 0); - } - - /** - * Set the distance this span is from the core of the heightfield region - * it belongs to. - * @param value The new distance. Auto-clamped at a minimum of zero. - */ - public void setDistanceToRegionCore(int value) - { - mDistanceToRegionCore = Math.max(value, 0); - } - - /** - * Sets the specified span at the neighbor of the current span. - *

      Uses the standard direction indices (0 through 3) where - * Zero is the neighbor offset at (-1, 0) and the search proceeds - * clockwise.

      - * @param direction The direction of the neighbor. - * @param neighbor The neighbor of this span. - * @see Neighbor Searches - */ - public void setNeighbor(int direction, OpenHeightSpan neighbor) - { - switch (direction) - { - case 0: mNeighborConnection0 = neighbor; break; - case 1: mNeighborConnection1 = neighbor; break; - case 2: mNeighborConnection2 = neighbor; break; - case 3: mNeighborConnection3 = neighbor; break; - } - } - - /** - * Set the next heigher span in the span's heightfield column. - * @param value The new value. null is an acceptable value. - */ - public void setNext(OpenHeightSpan value) { mNext = value; } - - /** - * The heightfield region this span belongs to. - *

      See {@link #regionID()} for important contract information.

      - * @param value The new value. - */ - public void setRegionID(int value) { mRegionID = value; } - - /** - * {@inheritDoc} - */ - @Override - public String toString() - { - return "Floor: " + mFloor - + ", Ceiling: " + mHeight - + ", Region: " + mRegionID; - } - -} diff --git a/critterai/.svn/pristine/b7/b79b18f9d8f4915f7487560d9cd07790127b8bf9.svn-base b/critterai/.svn/pristine/b7/b79b18f9d8f4915f7487560d9cd07790127b8bf9.svn-base deleted file mode 100644 index 86f56f93..00000000 --- a/critterai/.svn/pristine/b7/b79b18f9d8f4915f7487560d9cd07790127b8bf9.svn-base +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class MatchPredicate - { - private readonly Object mRoot; - private readonly MatchType mType; - private readonly bool mInvert; - - public MatchPredicate(Object root, MatchType type, bool invert) - { - mRoot = root; - mType = type; - mInvert = invert; - } - - public bool Matches(Object item) - { - if (mInvert) - return Matches(mRoot, item, mType); - else - return Matches(item, mRoot, mType); - } - - // Not commutative - public static bool Matches(Object target, Object source, MatchType option) - { - if (target == null || source == null) - return false; - - switch (option) - { - case MatchType.Strict: - - return (target == source); - - case MatchType.NameBeginsWith: - - return (target.name.StartsWith(source.name)); - - case MatchType.AnyInstance: - - return (target == source - || (target.name.StartsWith(source.name + " ") - && target.name.Contains("Instance"))); - } - return false; - } - - } -} diff --git a/critterai/.svn/pristine/b7/b7df1ab8e28a29e41e4a603939b0104a4cb85a80.svn-base b/critterai/.svn/pristine/b7/b7df1ab8e28a29e41e4a603939b0104a4cb85a80.svn-base deleted file mode 100644 index 01065970..00000000 --- a/critterai/.svn/pristine/b7/b7df1ab8e28a29e41e4a603939b0104a4cb85a80.svn-base +++ /dev/null @@ -1,1487 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.logging.Logger; - -/** - * Builds an convex polygon mesh consisting of variable sized polygons. - * The mesh is generated from contour data contained by a {@link ContourSet} - * object. - *

      - *

      - * @see Convex Polygon Generation - * @see PolyMeshField - */ -public final class PolyMeshFieldBuilder -{ - - /* - * Design notes: - * - * Recast Reference: rcBuildPolyMesh in RecastMesh.cpp - * - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - */ - - private static final Logger logger = - Logger.getLogger(PolyMeshFieldBuilder.class.getName()); - - /* - * Flag and associated deflag. Used during triangulation. - */ - private static final int FLAG = 0x80000000; - private static final int DEFLAG = 0x0fffffff; - - /** - * IMPORTANT: Only use this value during creation of the - * {@link PolyMeshField} objects. After that, use the value from the - * object since the object may alter the value. - */ - private final int mMaxVertsPerPoly; - - /** - * Constructor. - * @param maxVertsPerPoly The maximum vertices per polygon. The builder - * will not create polygons with more than this number of vertices. - */ - public PolyMeshFieldBuilder(int maxVertsPerPoly) - { - mMaxVertsPerPoly = maxVertsPerPoly; - } - - /** - * Builds a convex polygon mesh from the provided contour set. - *

      This build algorithm will fail and return null if the - * {@link ContourSet} contains any single contour with more than - * 0x0fffffff vertices. - * @param contours A properly populated contour set. - * @return The result of the build operation. - */ - public PolyMeshField build(ContourSet contours) - { - // Initialize - if (contours == null || contours.size() == 0) - return null; - - // Construct the result object. - PolyMeshField result = new PolyMeshField(contours.boundsMin() - , contours.boundsMax() - , contours.cellSize() - , contours.cellHeight() - , mMaxVertsPerPoly); - - // Number of vertices found in the source. - int sourceVertCount = 0; - - // The maximum possible number of polygons assuming that all will - // be triangles. - int maxPossiblePolygons = 0; - - // The maximum vertices found in a single contour. - int maxVertsPerContour = 0; - - // Loop through all contours. Determine the values for the - // variables above. - for (int contourIndex = 0 - ; contourIndex < contours.size() - ; contourIndex++) - { - int count = contours.get(contourIndex).vertCount; - sourceVertCount += count; - maxPossiblePolygons += count - 2; - maxVertsPerContour = Math.max(maxVertsPerContour, count); - } - - if (sourceVertCount - 1 > DEFLAG) - { - // Too man vertices to be able to process. Will run into the - // the flag value. - logger.severe("Polygon mesh generation failed: One or more" + - " input contours contain more than the maximum" + - " allowed vertices. (" + DEFLAG + ")"); - return null; - } - - /* - * Holds the unique vertices found during triangulation. - * This array is sized to hold the maximum possible vertices. - * The actual number of vertices will be smaller due to duplication - * in the source contours. - */ - final int[] globalVerts = new int[sourceVertCount * 3]; - int globalVertCount = 0; - - /* - * Holds polygon indices. - * - * The array is sized to hold the maximum possible polygons. - * The actual number will be significantly smaller once polygons - * are merged. - * - * Where mvpp = maximum vertices per polygon: - * - * Each polygon entry is mvpp. The first instance of NULL_INDEX means - * the end of poly indices. - * - * Example: If nvp = 6 and the the polygon has 4 vertices -> - * (1, 3, 4, 8, NULL_INDEX, NULL_INDEX) - * then (1, 3, 4, 8) defines the polygon. - */ - final int[] globalPolys = - new int[maxPossiblePolygons * mMaxVertsPerPoly]; - - // Fill with null index. - for (int i = 0; i < globalPolys.length; i++) - globalPolys[i] = PolyMeshField.NULL_INDEX; - - final int[] globalRegions = new int[maxPossiblePolygons]; - int globalPolyCount = 0; - - /* - * Holds information that allows mapping of contour vertex indices to - * shared vertex indices. (i.e. Index of vertex in contour.verts[] - * to index of vertex in within this operation.) - * - * index (key): The original vertex index of the contour. - * value in array: The vertex index in the shared vertex array. - * - * This is a working variable whose content is meaningless between - * iterations. It will contain cross-iteration trash. But that is - * OK because of the way the array is used. (I.e. Trash data left - * over from a previous iteration will never be accessed in the - * current iteration.) - */ - final int[] contourToGlobalIndicesMap = new int[maxVertsPerContour]; - - /* - * Key = Hash representing a unique vertex location. - * Value = The index of the vertex in the global vertices array. - * When a new vertex is found, it is added to the vertices array and - * its global index stored in this hash table. If a duplicate is - * found, the value from this table is used. - * There will always be duplicate vertices since different contours - * are connected by these duplicate vertices. - */ - final Hashtable vertIndices = - new Hashtable(); - - // Each list is initialized to a size that will minimize resizing. - final ArrayList workingIndices = - new ArrayList(maxVertsPerContour); - final ArrayList workingTriangles = - new ArrayList(maxVertsPerContour); - - // Various working variables. - // (Values are meaningless outside of the iteration.) - final int[] workingPolys = - new int[(maxVertsPerContour + 1) * mMaxVertsPerPoly]; - int workingPolyCount = 0; - final int[] mergeInfo = new int[3]; - final int[] mergedPoly = new int[mMaxVertsPerPoly]; - - // Process all contours. - for (int contourIndex = 0 - ; contourIndex < contours.size() - ; contourIndex++) - { - Contour contour = contours.get(contourIndex); - if (contour.verts.length < 3 * 4) - { - // This indicates a problem with contour creation - // since the contour builder should detect for this. - logger.severe("Polygon generation failure: Contour has " + - "too few vertices. Bad input data. Region " + - contour.regionID); - continue; - } - - // Create working indices for the contour vertices. - workingIndices.clear(); - for (int i = 0; i < contour.vertCount; i++) - workingIndices.add(i); - - // Triangulate the contour. - int triangleCount = triangulate(contour.verts - , workingIndices - , workingTriangles); - - if (triangleCount <= 0) - { - /* - * Failure of the triangulation. - * This is known to occur if the source polygon is - * self-intersecting or the source region contains internal - * holes. In both cases, the problem is likely due to bad - * region formation. - */ - logger.severe("Polygon generation failure: Could not" + - " triangulate contour. Region " + contour.regionID); - continue; - } - - /* - * Loop through the vertices in this contour. - * For new vertices (not seen in previous contours) get a new - * index and add it to the global vertices array. - */ - for (int iContourVert = 0 - ; iContourVert < contour.vertCount - ; iContourVert++) - { - int pContourVert = iContourVert*4; - int vertHash = getHashCode(contour.verts[pContourVert] - , contour.verts[pContourVert+1] - , contour.verts[pContourVert+2]); - Integer iGlobalVert = vertIndices.get(vertHash); - if (iGlobalVert == null) - { - // This is the first time this vertex has been seen. - // Assign it an index and add it to the vertex array. - iGlobalVert = globalVertCount; - globalVertCount++; - vertIndices.put(vertHash, iGlobalVert); - globalVerts[iGlobalVert*3] = contour.verts[pContourVert]; - globalVerts[iGlobalVert*3+1] = - contour.verts[pContourVert+1]; - globalVerts[iGlobalVert*3+2] = - contour.verts[pContourVert+2]; - } - // Creat the map entry. Contour vertex index -> global - // vertex index. - contourToGlobalIndicesMap[iContourVert] = iGlobalVert; - } - - - - // Initialize the working polygon array. - for (int i = 0; i < workingPolys.length; i++) - workingPolys[i] = PolyMeshField.NULL_INDEX; - - // Load the triangles into to the working polygon array, updating - // indices in the process. - workingPolyCount = 0; - for (int i = 0; i < triangleCount; i++) - { - /* - * The working triangles list contains vertex index data - * from the contour. The working polygon array needs the - * global vertex index. So the indices mapping array created - * above is used to do the conversion. - */ - workingPolys[workingPolyCount*mMaxVertsPerPoly] - = contourToGlobalIndicesMap[ - workingTriangles.get(i*3)]; - workingPolys[workingPolyCount*mMaxVertsPerPoly+1] - = contourToGlobalIndicesMap[ - workingTriangles.get(i*3+1)]; - workingPolys[workingPolyCount*mMaxVertsPerPoly+2] - = contourToGlobalIndicesMap[ - workingTriangles.get(i*3+2)]; - workingPolyCount++; - } - - if (mMaxVertsPerPoly > 3) - { - // Merging of triangles into larger polygons is permitted. - // Continue until no polygons can be found to merge. - // http://www.critterai.org/nmgen_polygen#mergepolys - while(true) - { - - int longestMergeEdge = -1; - int pBestPolyA = -1; - int iPolyAVert = -1; // Start of the shared edge. - int pBestPolyB = -1; - int iPolyBVert = -1; // Start of the shared edge. - - // Loop through all but the last polygon looking for the - // best polygons to merge in this iteration. - for (int iPolyA = 0 - ; iPolyA < workingPolyCount - 1 - ; iPolyA++) - { - for (int iPolyB = iPolyA + 1 - ; iPolyB < workingPolyCount - ; iPolyB++) - { - // Can polyB merge with polyA? - getPolyMergeInfo(iPolyA*mMaxVertsPerPoly - , iPolyB*mMaxVertsPerPoly - , workingPolys - , globalVerts - , result.maxVertsPerPoly() - , mergeInfo); - if (mergeInfo[0] > longestMergeEdge) - { - // polyB has the longest shared edge with - // polyA found so far. Save the merge - // information. - longestMergeEdge = mergeInfo[0]; - pBestPolyA = iPolyA * mMaxVertsPerPoly; - iPolyAVert = mergeInfo[1]; - pBestPolyB = iPolyB * mMaxVertsPerPoly; - iPolyBVert = mergeInfo[2]; - } - } - } - - if (longestMergeEdge <= 0) - // No valid merges found during this iteration. - break; - - // Found polygons to merge. Perform the merge. - - // Prepare the merged polygon array. - for (int i = 0; i < mergedPoly.length; i++) - mergedPoly[i] = PolyMeshField.NULL_INDEX; - - // Get the size of each polygon. - final int vertCountA - = PolyMeshField.getPolyVertCount(pBestPolyA - , workingPolys - , result.maxVertsPerPoly()); - final int vertCountB - = PolyMeshField.getPolyVertCount(pBestPolyB - , workingPolys - , result.maxVertsPerPoly()); - int position = 0; - - /* - * Fill the mergedPoly array. - * Start the vertex at the end of polygon A's shared edge. - * Add all vertices until looping back to the vertex just - * before the start of the shared edge. Repeat for - * polygon B. - * - * Duplicate vertices are avoided, while ensuring we get - * all vertices, since each loop drops the vertex that - * starts its polygon's shared edge and: - * - * PolyAStartVert == PolyBEndVert and - * PolyAEndVert == PolyBStartVert. - */ - for (int i = 0; i < vertCountA - 1; i++) - mergedPoly[position++] = workingPolys[pBestPolyA - + ((iPolyAVert+1+i) % vertCountA)]; - for (int i = 0; i < vertCountB - 1; i++) - mergedPoly[position++] = workingPolys[pBestPolyB - + ((iPolyBVert+1+i) % vertCountB)]; - - // Copy the merged polygon over the top of polygon A. - System.arraycopy(mergedPoly - , 0 - , workingPolys - , pBestPolyA - , mMaxVertsPerPoly); - // Remove polygon B by shifting all information to the - // left by one polygon, starting at polygon B. - System.arraycopy(workingPolys - , pBestPolyB + mMaxVertsPerPoly - , workingPolys, pBestPolyB - , workingPolys.length - - pBestPolyB - mMaxVertsPerPoly); - workingPolyCount--; - } - - } - - // Polygon creation for this contour is complete. - // Add polygons to the global polygon array and store region - // information. - - for (int i = 0; i < workingPolyCount; i++) - { - // Copy the polygon from the working array to the - // correct position in the global array. - System.arraycopy(workingPolys, i * mMaxVertsPerPoly - , globalPolys, globalPolyCount * mMaxVertsPerPoly - , mMaxVertsPerPoly); - globalRegions[globalPolyCount] = contour.regionID; - globalPolyCount++; - } - - } - - /* - * Transfer global array information into instance fields. - * Could have loaded data directly into instance fields and saved this - * processing cost. But this method has memory benefits since it is - * not necessary to oversize the instance arrays. - */ - - // Transfer vertex data. - result.verts = new int[globalVertCount * 3]; - System.arraycopy(globalVerts, 0, result.verts, 0, globalVertCount * 3); - - /* - * Transfer polygon indices data. - * - * The global polygon array is half the size of the instance polygon - * array since the instance polygon array also contains edge adjacency - * information. So array copy can't be used. - * - * Instead, copy the global polygon array over to instance polygon - * array in blocks and initialize the instance polygon array's - * adjacency information. - */ - result.polys = new int[globalPolyCount * mMaxVertsPerPoly * 2]; - for (int iPoly = 0; iPoly < globalPolyCount; iPoly++) - { - int pPoly = iPoly*mMaxVertsPerPoly; - for (int offset = 0; offset < mMaxVertsPerPoly; offset++) - { - // Transfer index information. - result.polys[pPoly*2+offset] = globalPolys[pPoly+offset]; - // Initialize edge's adjacency field. - result.polys[pPoly*2+mMaxVertsPerPoly+offset] = - PolyMeshField.NULL_INDEX; - } - } - - // Transfer region data. - result.polyRegions = new int[globalPolyCount]; - System.arraycopy(globalRegions - , 0 - , result.polyRegions - , 0 - , globalPolyCount); - - // Build polygon adjacency information. - buildAdjacencyData(result); - - return result; - - } - - /** - * The maximum vertices per polygon. The builder will not create - * polygons with more than this number of vertices. - * @return The maximum vertices per polygon. - */ - public int maxVertsPerPoly() { return mMaxVertsPerPoly; } - - /** - * Searches all polygons and adds adjacency data to the - * {@link PolyMeshField#polys} array. - *

      All other data initialization must have been completed before - * calling this operation. It is expected that all adjacency fields - * within the {@link PolyMeshField#polys} array have been initialized - * to NULL_INDEX before calling this operation. - * @param mesh The mesh to use. - */ - private static void buildAdjacencyData(PolyMeshField mesh) - { - - int vertCount = mesh.verts.length / 3; - // Purposely using the region count to avoid the division. - int polyCount = mesh.polyRegions.length; - - int maxEdgeCount = polyCount * mesh.maxVertsPerPoly(); - - /* - * Holds edge information - * - * IMPORTANT: This array does not catalog all edges. It is only - * guaranteed to catalog all shared edges. It will contain only a - * sub-set of border edges, which are edges only connected to a - * single polygon. - * - * Format: - * 0: Index of primary vertex connected to the edge. This index's - * value will always be less than the value of the secondary index. - * 1: Index of secondary vertex connected to the edge. - * 2: Index of polygon A connected to this edge. - * 3: Polygon A vertex offset. - * 4: Index of polygon B connected to this edge. - * (Or NULL_INDEX if this is a border edge.) - * 5: Polygon B vertex offset. - * (Only meaningful if 4 != NULL_INDEX.) - */ - int[] edges = new int[maxEdgeCount * 6]; - int edgeCount = 0; - - /* - * An array used in edge searches based on an edge's primary index. - * - * Index: Vertex index - * Value: An index to an edge in the edges array that has the vertex - * as its primary vertex. - * - * Example of use: - * - * Vertex index = 10; - * startEdge[10] = 8 -> This vertex is the primary vertex for edge 8. - * edges[8 * 6] <- Edge definition. - * nextEdge[8] = 12 -> This vertex is also the primary vertex for - * edge 12. - * nextEdge[12] = 15 -> This vertex is also the primary vertex for - * edge 15. - * nextEdge[15] = NULL_INDEX -> This edge is not the primary index - * for any further edges. - * - * If the value for a vertex is NULL_INDEX then the vertex is not a - * primary vertex for any known edge. (This can occur because not - * all border edges are cataloged by this algorithm.) - */ - int[] startEdge = new int[vertCount]; - for (int i = 0; i < startEdge.length; i++) - startEdge[i] = PolyMeshField.NULL_INDEX; - - /* - * An array used in edge searches. - * - * Use the startEdge array to get an index to a value in this array - * in order to start an edge search. See doc for startEdge for details. - * - * Index: Edge Index Same index used for the edges array and as - * values in the startEdge array. - * - * Value: Edge index of next edge attacked to the same vertex. - * (Or NULL_INDEX if there are no more connected edges.) - */ - int[] nextEdge = new int[maxEdgeCount]; - - /* - * Loop through all polygons. - * Find all shared edges. Populate all data arrays. - * At the end of this loop, all data will be gathered except for - * fields 4 and 5 in the edge array entries. - */ - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - int pPoly = iPoly * mesh.maxVertsPerPoly() * 2; - // Loop through each polygon vertex index. - for (int vertOffset = 0 - ; vertOffset < mesh.maxVertsPerPoly() - ; vertOffset++) - { - int iVert = mesh.polys[pPoly+vertOffset]; - if (iVert == PolyMeshField.NULL_INDEX) - // Reached the end of this polygon. - break; - - int iNextVert; - if (vertOffset + 1 >= mesh.maxVertsPerPoly() - || mesh.polys[pPoly+vertOffset+1] - == PolyMeshField.NULL_INDEX) - // Need to wrap to the beginning. This will only happen - // once per iteration since the loop will be forced to - // end during the next iteration. - iNextVert = mesh.polys[pPoly]; - else - // The next vertex in the array is a valid vertex in - // the polygon. - iNextVert = mesh.polys[pPoly+vertOffset+1]; - - /* - * This next check does several useful things: - * - It ensures that a particular edge is never selected - * twice since, for shared edges, this condition will - * only exist for one of the polygons. - * - Some border edges will be skipped entirely, saving - * some processing time. - */ - if (iVert < iNextVert) - { - // This is an edge's primary vertex. - // Set the vertices connected to this edge. - edges[edgeCount*6] = iVert; - edges[edgeCount*6+1] = iNextVert; - // Set the polygons associated with this edge. - edges[edgeCount*6+2] = iPoly; - edges[edgeCount*6+3] = vertOffset; - // Default to unconnected. (Border edge.) - edges[edgeCount*6+4] = PolyMeshField.NULL_INDEX; - edges[edgeCount*6+5] = PolyMeshField.NULL_INDEX; - - /* - * Update the search arrays. - * The first time a vertex is assigned as an edge's - * primary vertex, the NULL_INDEX will be copied into - * nextEdge, indicating the end of a vertex chain. - * - * The 2nd time a vertex is assign as an edge's primary - * vertex, the original edge pointer from startEdge - * is added to nextEdge, and startEdge is assigned - * the new starting edge. This results in a stack-like - * storage mechanism. - * - * The process is repeated every time the vertex is - * assigned as a primary vertex, creating a chain. - */ - nextEdge[edgeCount] - = startEdge[iVert]; - startEdge[iVert] = edgeCount; - - edgeCount++; - } - - } - } - - /* - * Loop through all polygons. - * Find the the 2nd polygon's information for all shared edges. - * (Fields 4 and 5 of the edge array entries.) - */ - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - int pPoly = iPoly * mesh.maxVertsPerPoly() * 2; - // Loop through each polygon vertex index. - for (int vertOffset = 0 - ; vertOffset < mesh.maxVertsPerPoly() - ; ++vertOffset) - { - int iVert = mesh.polys[pPoly+vertOffset]; - if (iVert == PolyMeshField.NULL_INDEX) - // Reached the end of this polygon. - break; - - int iNextVert; - if (vertOffset + 1 >= mesh.maxVertsPerPoly() - || mesh.polys[pPoly+vertOffset+1] - == PolyMeshField.NULL_INDEX) - // Need to wrap to the beginning. This will only happen - // once per iteration since the loop will be forced to - // end during the next iteration. - iNextVert = mesh.polys[pPoly]; - else - // The next vertex in the array is a valid vertex in - // the polygon. - iNextVert = mesh.polys[pPoly+vertOffset+1]; - - // Note that this next conditional is reversed from that - // used in the previous loop. - if (iVert > iNextVert) - { - /* - * iVert is NOT a primary vertex in this case. We are - * looking for the "other" polygon that shares this edge. - * If there is another polygon sharing this edge, its - * primary vertex will be iNextVert. - * - * Climb the edge chain for iNextVert, looking for an - * edge that has iVert as its secondary vertex. - */ - // Loop halts at the end of the chain. - for (int edgeIndex = startEdge[iNextVert] - ; edgeIndex != PolyMeshField.NULL_INDEX - ; edgeIndex = nextEdge[edgeIndex]) - { - if (edges[edgeIndex*6+1] == iVert) - { - // Found a shared edge. Assign this polygon - // as the secondary connected polygon. - edges[edgeIndex*6+4] = iPoly; - edges[edgeIndex*6+5] = vertOffset; - break; - } - } - } - } - } - - // All necessary data has been gathered. Any edge in the edge array - // that has both polygons assigned is a shared edge. - - // Store adjacency information. - // Loop through all edges. - for (int pEdge = 0; pEdge < edgeCount; pEdge += 6) - { - if (edges[pEdge+4] != PolyMeshField.NULL_INDEX) - { - // The second polygon in this edge is set. - // So this is a shared edge. - int pPolyA = edges[pEdge+2] * mesh.maxVertsPerPoly() * 2; - int pPolyB = edges[pEdge+4] * mesh.maxVertsPerPoly() * 2; - // In the second section of the polygon definition, where - // connection information is stored, put the polygon index - // into the same position as the edge's primary vertex. - mesh.polys[pPolyA + mesh.maxVertsPerPoly() + edges[pEdge+3]] - = edges[pEdge+4]; - mesh.polys[pPolyB + mesh.maxVertsPerPoly() + edges[pEdge+5]] - = edges[pEdge+2]; - } - } - - } - - /** - * Provides a hash value unique to the combination of values. - * @param x The vertices x-value. (x, y, z) - * @param y The vertices y-value. (x, y, z) - * @param z The vertices z-value. (x, y, z) - * @return A hash that is unique to the vertex. - */ - private static int getHashCode(int x, int y, int z) - { - /* - * Note: Tried the standard eclipse hash generation method. But - * it resulted in non-unique hash values during testing. Switched - * to this method. - * Hex values are arbitrary prime numbers. - */ - return 0x8da6b343 * x + 0xd8163841 * y + 0xcb1ab31f * z; - } - - /** - * Returns the index incremented by one, or if the increment causes - * an out of range high the minimum allowed index is returned. - * (e.g. Wrapping) - * @param i The index. - * @param n The size of the array the index belongs to. - * @return Returns the index incremented by one with wrapping. - */ - private static int getNextIndex(int i, int n) - { - return i+1 < n ? i+1 : 0; - } - - /** - * Checks two polygons to see if they can be merged. If a merge is - * allowed, provides data via the outResult argument. - *

      outResult will be an array of size 3 with the following - * information:

      - *

      0: The lenghtSq of the edge shared between the polygons.
      - * 1: The index (not pointer) of the start of the shared edge in - * polygon A.
      - * 2: The index (not pointer) of the start of the shared edge in - * polygon B.
      - *

      - *

      A value of -1 at index zero indicates one of the following:

      - *
        - *
      • The polygons cannot be merged because they would contain too - * many vertices.
      • - *
      • The polygons do not have a shared edge.
      • - *
      • Merging the polygons would result in a concave polygon.
      • - *
      - *

      To convert the values at indices 1 and 2 to pointers: - * (polyPointer + value)

      - * @param polyAPointer The pointer to the start of polygon A in the - * polys argument. - * @param polyBPointer The pointer to the start of polygon B in the - * polys argument. - * @param polys An array of polygons in the form: - * (vert1, vert2, vert3, ..., vertN, NULL_INDEX). - * The null index terminates every polygon. This permits polygons - * with different vertex counts. - * @param verts The vertex data associated with the polygons. - * @param outResult An array of size three which contains merge information. - */ - private static void getPolyMergeInfo(int polyAPointer - , int polyBPointer - , int[] polys - , int[] verts - , int maxVertsPerPoly - , int[] outResult) - { - - outResult[0] = -1; // Default to invalid merge - outResult[1] = -1; - outResult[2] = -1; - - final int vertCountA = PolyMeshField.getPolyVertCount(polyAPointer - , polys - , maxVertsPerPoly); - final int vertCountB = PolyMeshField.getPolyVertCount(polyBPointer - , polys - , maxVertsPerPoly); - - // If the merged polygon would would have to many vertices, do not - // merge. Subtracting two since to take into account the effect of - // a merge. - if (vertCountA + vertCountB - 2 > maxVertsPerPoly) - return; - - /* - * Check if the polygons share an edge. - * - * Loop through all of vertices for polygonA and extract its edge. - * (vertA -> vertANext) Then loop through all vertices for polygonB - * and check to see if any of its edges use the same vertices as - * polygonA. - */ - for (int iPolyVertA = 0; iPolyVertA < vertCountA; iPolyVertA++) - { - // Get the vertex indices for the polygonA edge - final int iVertA = polys[polyAPointer+iPolyVertA]; - final int iVertANext = polys[polyAPointer - + getNextIndex(iPolyVertA, vertCountA)]; - // Search polygonB for matches. - for (int iPolyVertB = 0; iPolyVertB < vertCountB; iPolyVertB++) - { - // Get the vertex indices for the polygonB edge. - final int iVertB = polys[polyBPointer+iPolyVertB]; - final int iVertBNext = polys[polyBPointer - + getNextIndex(iPolyVertB, vertCountB)]; - if (iVertA == iVertBNext && iVertANext == iVertB) - { - // The vertex indices for this edge are the same and - // sequenced in opposite order. So the edge is shared. - outResult[1] = iPolyVertA; - outResult[2] = iPolyVertB; - } - } - } - - if (outResult[1] == -1) - // No common edge, cannot merge. - return; - - /* - * Check to see if the merged polygon would be convex. - * - * Gets the vertices near the section where the merge would occur. - * Do they form a concave section? If so, the merge is invalid. - * - * Note that the following algorithm is only valid for clockwise - * wrapped convex polygons. - */ - - int pSharedVertMinus, pSharedVert, pSharedVertPlus; - - pSharedVertMinus = polys[polyAPointer - + getPreviousIndex(outResult[1], vertCountA)] * 3; - pSharedVert = polys[polyAPointer + outResult[1]] * 3; - pSharedVertPlus = polys[polyBPointer - + ((outResult[2]+2) % vertCountB)] * 3; - if (!isLeft(verts[pSharedVert] - , verts[pSharedVert+2] - , verts[pSharedVertMinus] - , verts[pSharedVertMinus+2] - , verts[pSharedVertPlus] - , verts[pSharedVertPlus+2])) - /* - * The shared vertex (center) is not to the left of segment - * vertMinus->vertPlus. For a clockwise wrapped polygon, this - * indicates a concave section. Merged polygon would be concave. - * Invalid merge. - */ - return; - - pSharedVertMinus = polys[polyBPointer - + getPreviousIndex(outResult[2], vertCountB)] * 3; - pSharedVert = polys[polyBPointer + outResult[2]] * 3; - pSharedVertPlus = polys[polyAPointer - + ((outResult[1]+2) % vertCountA)] * 3; - if (!isLeft(verts[pSharedVert] - , verts[pSharedVert+2] - , verts[pSharedVertMinus] - , verts[pSharedVertMinus+2] - , verts[pSharedVertPlus] - , verts[pSharedVertPlus+2])) - /* - * The shared vertex (center) is not to the left of segment - * vertMinus->vertPlus. For a clockwise wrapped polygon, this - * indicates a concave section. Merged polygon would be concave. - * Invalid merge. - */ - return; - - // Get the vertex indices that form the shared edge. - pSharedVertMinus = polys[polyAPointer + outResult[1]] * 3; - pSharedVert = polys[polyAPointer - + getNextIndex(outResult[1], vertCountA)] * 3; - - // Store the lengthSq of the shared edge. - final int deltaX = verts[pSharedVertMinus+0] - verts[pSharedVert+0]; - final int deltaZ = verts[pSharedVertMinus+2] - verts[pSharedVert+2]; - outResult[0] = deltaX*deltaX + deltaZ*deltaZ; - - } - - /** - * Returns the index decremented by one, or if the decrement causes an - * out of range low the maximum allowed index is returned. (e.g. Wrapping) - * @param i The index. - * @param n The size of the array the index belongs to. - * @return Returns the index decremented by one with wrapping. - */ - private static int getPreviousIndex(int i, int n) - { - return i-1 >= 0 ? i-1 : n-1; - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle defined by points (A, B, C). - *

      A positive value indicates:

      - *
        - *
      • Counterclockwise wrapping of the points.
      • - *
      • Point B lies to the right of line AC, looking from A to C.
      • - *
      - *

      A negative value indicates:

      - *
        - *
      • Clockwise wrapping of the points.
      • - *
      • Point B lies to the left of line AC, looking from A to C.
      • - *
      - *

      A value of zero indicates that all points are collinear or - * represent the same point.

      - *

      This is a fast operation.

      - * @param ax The x-value for point (ax, ay) for vertex A of the triangle. - * @param ay The y-value for point (ax, ay) for vertex A of the triangle. - * @param bx The x-value for point (bx, by) for vertex B of the triangle. - * @param by The y-value for point (bx, by) for vertex B of the triangle. - * @param cx The x-value for point (cx, cy) for vertex C of the triangle. - * @param cy The y-value for point (cx, cy) for vertex C of the triangle. - * @return The signed value of two times the area of the triangle defined - * by the points (A, B, C). - */ - private static int getSignedAreaX2(int ax, int ay - , int bx, int by - , int cx, int cy) - { - /* - * References: - * - * http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm - * #Modern%20Triangles - * http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - * - */ - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - - /** - * Returns TRUE if the line segment AB intersects any edges not already - * connected to one of the two vertices. - *

      The test is only performed on the xz-plane.

      - *

      Assumptions:

      - *
        - *
      • The vertices and indices arguments define a valid simple polygon - * with vertices wrapped clockwise.
      • - *
      • indexA != indexB
      • - *
      - *

      Behavior is undefined if the arguments to not meet these - * assumptions

      - * @param indexA An polygon index of a vertex that will form segment AB. - * @param indexB An polygon index of a vertex that will form segment AB. - * @param verts The vertices array in the form (x, y, z, id). The value - * stored at the id position is not relevant to this operation. - * @param indices A simplpe polygon wrapped clockwise. - * @return TRUE if the line segment AB intersects any edges not already - * connected to one of the two vertices. Otherwise FALSE. - */ - private static boolean hasIllegalEdgeIntersection(int indexA - , int indexB - , int[] verts - , ArrayList indices) - { - - // Get pointers to the primary vertices being tested. - int pVertA = (indices.get(indexA) & DEFLAG) * 4; - int pVertB = (indices.get(indexB) & DEFLAG) * 4; - - // Loop through the polygon edges. - for (int iPolyEdgeBegin = 0 - ; iPolyEdgeBegin < indices.size() - ; iPolyEdgeBegin++) - { - int iPolyEdgeEnd = getNextIndex(iPolyEdgeBegin, indices.size()); - if (!(iPolyEdgeBegin == indexA - || iPolyEdgeBegin == indexB - || iPolyEdgeEnd == indexA - || iPolyEdgeEnd == indexB)) - { - // Neither of the test indices are endpoints of this edge. - // Get pointers for this edge's verts. - int pEdgeVertBegin = (indices.get(iPolyEdgeBegin) & DEFLAG) * 4; - int pEdgeVertEnd = (indices.get(iPolyEdgeEnd) & DEFLAG) * 4; - if ((verts[pEdgeVertBegin] == verts[pVertA] - && verts[pEdgeVertBegin+2] == verts[pVertA+2]) - || (verts[pEdgeVertBegin] == verts[pVertB] - && verts[pEdgeVertBegin+2] == verts[pVertB+2]) - || (verts[pEdgeVertEnd] == verts[pVertA] - && verts[pEdgeVertEnd+2] == verts[pVertA+2]) - || (verts[pEdgeVertEnd] == verts[pVertB] - && verts[pEdgeVertEnd+2] == verts[pVertB+2])) - /* - * One of the test vertices is co-located on the xz plane - * with one of the endpoints of this edge. (This is a - * test of the actual position of the verts rather than - * simply the index check performed earlier.) - * Skip this edge. - */ - continue; - - /* - * This edge is not connected to either of the test vertices. - * If line segment AB intersects with this edge, then the - * intersection is illegal. - * I.e. New edges cannot cross existing edges. - */ - if (Geometry.segmentsIntersect(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pEdgeVertBegin] - , verts[pEdgeVertBegin+2] - , verts[pEdgeVertEnd] - , verts[pEdgeVertEnd+2])) - return true; - - } - } - - return false; - } - - /** - * Returns TRUE if point P is to the left of line AB when looking - * from A to B. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the left of line AB when looking - * from A to B. Otherwise FALSE. - */ - private static boolean isLeft(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) < 0; - } - - /** - * Returns TRUE if point P is to the left of line AB when looking - * from A to B or is collinear with line AB. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the left of line AB when looking - * from A to B, or is collinear with line AB. Otherwise FALSE. - */ - private static boolean isLeftOrCollinear(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) <= 0; - } - - /** - * Returns TRUE if point P is to the right of line AB when looking - * from A to B. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the right of line AB when looking - * from A to B. - */ - private static boolean isRight(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) > 0; - } - - /** - * Returns TRUE if point P is to the right of or on line AB when looking - * from A to B. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the right of or on line AB when looking - * from A to B. - */ - private static boolean isRightOrCollinear(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) >= 0; - } - - /** - * Returns TRUE if the line segment formed by vertex A and vertex B will - * form a valid partition of the polygon. - *

      I.e. New line segment AB is internal to the polygon and will not - * cross existing line segments.

      - *

      The test is only performed on the xz-plane.

      - *

      Assumptions:

      - *
        - *
      • The vertices and indices arguments define a valid simple polygon - * with vertices wrapped clockwise.
      • - *
      • indexA != indexB
      • - *
      - *

      Behavior is undefined if the arguments to not meet these - * assumptions

      - * @param indexA An polygon index of a vertex that will form segment AB. - * @param indexB An polygon index of a vertex that will form segment AB. - * @param verts The vertices array in the form (x, y, z, id). The value - * stored at the id position is not relevant to this operation. - * @param indices A simplpe polygon wrapped clockwise. - * @return TRUE if the line segment formed by vertex A and vertex B will - * form a valid partition of the polygon. Otherwise false. - */ - private static boolean isValidPartition(int indexA - , int indexB - , int[] verts - , ArrayList indices) - { - /* - * First check whether the segment AB lies within the internal - * angle formed at A. (This is the faster check.) - * If it does, then perform the more costly check. - */ - return liesWithinInternalAngle(indexA, indexB, verts, indices) - && !hasIllegalEdgeIntersection(indexA, indexB, verts, indices); - } - - /** - * Returns TRUE if vertex B lies within the internal angle of the polygon - * at vertex A. - * - *

      Vertex B does not have to be within the polygon border. It just has - * be be within the area encompassed by the internal angle formed at - * vertex A.

      - * - *

      This operation is a fast way of determining whether a line segment - * can possibly form a valid polygon partition. If this test returns - * FALSE, then more expensive checks can be skipped.

      - * Visualizations - *

      Special case: - * FALSE is returned if vertex B lies directly on either of the rays - * cast from vertex A along its associated polygon edges. So the test - * on vertex B is exclusive of the polygon edges.

      - *

      The test is only performed on the xz-plane.

      - *

      Assumptions:

      - *
        - *
      • The vertices and indices arguments define a valid simple polygon - * with vertices wrapped clockwise.
      • - *
      • indexA != indexB
      • - *
      - *

      Behavior is undefined if the arguments to not meet these - * assumptions

      - * @param indexA An polygon index of a vertex that will form segment AB. - * @param indexB An polygon index of a vertex that will form segment AB. - * @param verts The vertices array in the form (x, y, z, id). The value - * stored at the id position is not relevant to this operation. - * @param indices A simplpe polygon wrapped clockwise. - * @return Returns TRUE if vertex B lies within the internal angle of - * the polygon at vertex A. - */ - private static boolean liesWithinInternalAngle(int indexA - , int indexB - , int[] verts - , ArrayList indices) - { - - // Get pointers to the main vertices being tested. - int pVertA = (indices.get(indexA) & DEFLAG) * 4; - int pVertB = (indices.get(indexB) & DEFLAG) * 4; - - // Get poitners to the vertices just before and just after vertA. - int pVertAMinus // The vertex just before A. - = (indices.get(getPreviousIndex(indexA, indices.size())) & DEFLAG) - * 4; - int pVertAPlus // The vert just after A. - = (indices.get(getNextIndex(indexA, indices.size())) & DEFLAG) * 4; - - /* - * First, find which of the two angles formed by the line segments - * AMinus->A->APlus is internal to (pointing towards) the polygon. - * Then test to see if B lies within the area formed by that angle. - */ - - - // TRUE if A is left of or on line AMinus->APlus - if (isLeftOrCollinear(verts[pVertA] - , verts[pVertA+2] - , verts[pVertAMinus] - , verts[pVertAMinus+2] - , verts[pVertAPlus] - , verts[pVertAPlus+2])) - // The angle internal to the polygon is <= 180 degrees - // (non-reflex angle). - // Test to see if B lies within this angle. - - return isLeft( - // TRUE if B is left of line A->AMinus - verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - ,verts[pVertAMinus] - , verts[pVertAMinus+2]) - // TRUE if B is right of line A->APlus - && isRight(verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertAPlus] - , verts[pVertAPlus+2]); - - /* - * The angle internal to the polygon is > 180 degrees (reflex angle). - * Test to see if B lies within the external (<= 180 degree) angle and - * flip the result. (If B lies within the external angle, it can't - * lie within the internal angle.) - */ - - - return !( - // TRUE if B is left of or on line A->APlus - isLeftOrCollinear(verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertAPlus] - , verts[pVertAPlus+2]) - // TRUE if B is right of or on line A->AMinus - && isRightOrCollinear(verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertAMinus] - , verts[pVertAMinus+2])); - } - - /** - * Attempts to triangluate a polygon. - *

      Assumes the verts and indices arguments define a valid simple - * (concave or convex) polygon - * with vertices wrapped clockwise. Otherwise behavior is undefined.

      - * @param verts The vertices that make up the polygon in the format - * (x, y, z, id). The value stored at the id position is not relevant to - * this operation. - * @param inoutIndices A working array of indices that define the - * polygon to be triangluated. The content is manipulated during the - * operation and it will be left in an undefined state at the end of - * the operation. (I.e. Its content will no longer be of any use.) - * @param outTriangles The indices which define the triangles derived - * from the original polygon in the form - * (t1a, t1b, t1c, t2a, t2b, t2c, ..., tna, tnb, tnc). The original - * content of this argument is discarded prior to use. - * @return The number of triangles generated. Or, if triangluation - * failed, a negative number. - */ - private static int triangulate(int[] verts - , ArrayList inoutIndices - , ArrayList outTriangles) - { - - outTriangles.clear(); - - /* - * Terminology, concepts and such: - * - * This algorithm loops around the edges of a polygon looking for - * new internal edges to add that will partition the polygon into a - * new valid triangle internal to the starting polygon. During each - * iteration the shortest potential new edge is selected to form that - * iteration's new triangle. - * - * Triangles will only be formed if a single new edge will create - * a triangle. Two new edges will never be added during a single - * iteration. This means that the triangulated portions of the - * original polygon will only contain triangles and the only - * non-triangle polygon will exist in the untrianglulated portion - * of the original polygon. - * - * "Partition edge" refers to a potential new edge that will form a - * new valid triangle. - * - * "Center" vertex refers to the vertex in a potential new triangle - * which, if the triangle is formed, will be external to the - * remaining untriangulated portion of the polygon. Since is - * is now external to the polygon, it can't be used to form any - * new triangles. - * - * Some documentation refers to "iPlus2" even though the variable is - * not in scope or does not exist for that section of code. For - * documentation purposes, iPlus2 refers to the 2nd vertex after the - * primary vertex. - * E.g.: i, iPlus1, and iPlus2. - * - * Visualizations: http://www.critterai.org/nmgen_polygen#triangulation - */ - - // Loop through all vertices, flagging all indices that represent - // a center vertex of a valid new triangle. - for (int i = 0; i < inoutIndices.size(); i++) - { - final int iPlus1 = getNextIndex(i, inoutIndices.size()); - final int iPlus2 = getNextIndex(iPlus1, inoutIndices.size()); - if (isValidPartition(i, iPlus2, verts, inoutIndices)) - { - // A triangle formed by i, iPlus1, and iPlus2 will result - // in a valid internal triangle. - // Flag the center vertex (iPlus1) to indicate a valid triangle - // location. - inoutIndices.set(iPlus1, inoutIndices.get(iPlus1) | FLAG); - } - } - - /* - * Loop through the vertices creating triangles. When there is only a - * single triangle left, the operation is complete. - * - * When a valid triangle is formed, remove its center vertex. So for - * each loop, a single vertex will be removed. - * - * At the start of each iteration the indices list is in the following - * state: - * - Represents a simple polygon representing the un-triangulated - * portion of the original polygon. - * - All valid center vertices are flagged. - */ - while (inoutIndices.size() > 3) - { - - // Find the shortest new valid edge. - - // The minimum length found. - int minLengthSq = -1; - // The index for the start of the minimum length edge. - int iMinLengthSqVert = -1; - - // NOTE: i and iPlus1 are defined in two different scopes in - // this section. So be careful. - - // Loop through all indices in the remaining polygon. - for (int i = 0; i < inoutIndices.size(); i++) - { - final int iPlus1 = getNextIndex(i, inoutIndices.size()); - if ((inoutIndices.get(iPlus1) & FLAG) == FLAG) - { - // Indices i, iPlus1, and iPlus2 are known to form a - // valid triangle. - final int vert - = (inoutIndices.get(i) & DEFLAG) * 4; - final int vertPlus2 - = (inoutIndices.get(getNextIndex(iPlus1 - , inoutIndices.size())) & DEFLAG) * 4; - - // Determine the length of the partition edge. - // (i -> iPlus2) - int deltaX = verts[vertPlus2] - verts[vert]; - int deltaZ = verts[vertPlus2+2] - verts[vert+2]; - int lengthSq = deltaX * deltaX + deltaZ * deltaZ; - - if (minLengthSq < 0 || lengthSq < minLengthSq) - { - // This is either the first valid new edge, or an edge - // that is shorter than others previously found. - // Select it. - minLengthSq = lengthSq; - iMinLengthSqVert = i; - } - } - } - - if (iMinLengthSqVert == -1) - /* - * Could not find a new triangle. Triangulation failed. - * This happens if there are three or more vertices - * left, but none of them are flagged as being a - * potential center vertex. - */ - return -(outTriangles.size()/3); - - int i = iMinLengthSqVert; - int iPlus1 = getNextIndex(i, inoutIndices.size()); - - // Add the new triangle to the output. - outTriangles.add(inoutIndices.get(i) & DEFLAG); - outTriangles.add(inoutIndices.get(iPlus1) & DEFLAG); - outTriangles.add( - inoutIndices.get(getNextIndex(iPlus1 - , inoutIndices.size())) & DEFLAG); - - /* - * iPlus1, the "center" vert in the new triangle, is now external - * to the untriangulated portion of the polygon. Remove it from - * the indices list since it cannot be a member of any new - * triangles. - */ - inoutIndices.remove(iPlus1); - - if (iPlus1 == 0 || iPlus1 >= inoutIndices.size()) - { - /* - * The vertex removal has invalidated iPlus1 and/or i. So - * force a wrap, fixing the indices so they reference the - * correct indices again. This only occurs when the new - * triangle is formed across the wrap location of the polygon. - * Case 1: i = 14, iPlus1 = 15, iPlus2 = 0 - * Case 2: i = 15, iPlus1 = 0, iPlus2 = 1; - */ - i = inoutIndices.size() - 1; - iPlus1 = 0; - } - - /* - * At this point i and iPlus1 refer to the two indices from a - * successful triangluation that will be part of another new - * triangle. We now need to re-check these indices to see if they - * can now be the center index in a potential new partition. - */ - if (isValidPartition(getPreviousIndex(i , inoutIndices.size()) - , iPlus1 - , verts - , inoutIndices)) - inoutIndices.set(i, inoutIndices.get(i) | FLAG); - else - inoutIndices.set(i, inoutIndices.get(i) & DEFLAG); - - if (isValidPartition(i - , getNextIndex(iPlus1, inoutIndices.size()) - , verts - , inoutIndices)) - inoutIndices.set(iPlus1, inoutIndices.get(iPlus1) | FLAG); - else - inoutIndices.set(iPlus1, inoutIndices.get(iPlus1) & DEFLAG); - - } - - // Only three vertices remain. Add their triangle to the output list. - - outTriangles.add(inoutIndices.get(0) & DEFLAG); - outTriangles.add(inoutIndices.get(1) & DEFLAG); - outTriangles.add(inoutIndices.get(2) & DEFLAG); - - return outTriangles.size() / 3; - } - -} - diff --git a/critterai/.svn/pristine/b8/b8027d4d445caf5707fb4594a7f47fb6fae8c3bf.svn-base b/critterai/.svn/pristine/b8/b8027d4d445caf5707fb4594a7f47fb6fae8c3bf.svn-base deleted file mode 100644 index 2a85a83e..00000000 --- a/critterai/.svn/pristine/b8/b8027d4d445caf5707fb4594a7f47fb6fae8c3bf.svn-base +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nmgen; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmbuild -{ - /// - /// Applies to a - /// . - /// - public sealed class AreaCylinderMarker - : AreaMarker - { - private readonly Vector3 mCenterBase; - private readonly float mRadius; - private readonly float mHeight; - - private AreaCylinderMarker(string name, int priority, byte area - , Vector3 centerBase, float radius, float height) - : base(name, priority, area) - { - mCenterBase = centerBase; - mRadius = Math.Max(0, radius); - mHeight = Math.Max(0, height); - } - - /// - /// The center point of the cylinder base. - /// - public Vector3 GetCenterBase { get { return mCenterBase; } } - - /// - /// The radius of the cylinder. - /// - public float Radius { get { return mRadius; } } - - /// - /// The height of the cylinder. (From the base.) - /// - public float Height { get { return mHeight; } } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// The area will be applied during the - /// state. - /// - /// - /// The current build state. - /// The context to process. - /// False on error, otherwise true. - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - if (state != NMGenState.CompactFieldBuild) - return true; - - if (context.CompactField.MarkCylinderArea(context - , mCenterBase, mRadius, mHeight - , Area)) - { - context.Log(string.Format("{0} : Marked box area: Area: {1}, Priority: {2}" - , Name, Area, Priority) - , this); - return true; - } - - context.Log(Name + ": Failed to mark cylinder area.", this); - return false; - } - - /// - /// Creates a new marker. - /// - /// The processor name. - /// The processor priority. - /// The area to apply. - /// The center of the base of the cylinder. - /// The radius of the cylinder. - /// The height of the cylinder. (From the base.) - /// A new area marker, or null on error. - public static AreaCylinderMarker Create(string name, int priority, byte area - , Vector3 centerBase, float radius, float height) - { - // Implemented as a create method for consistency with other markers. - return new AreaCylinderMarker(name, priority, area, centerBase, radius, height); - } - } -} diff --git a/critterai/.svn/pristine/b8/b898fe5612415b924946bdfdccc24c8dd0eeb803.svn-base b/critterai/.svn/pristine/b8/b898fe5612415b924946bdfdccc24c8dd0eeb803.svn-base deleted file mode 100644 index 6d39d90b..00000000 --- a/critterai/.svn/pristine/b8/b898fe5612415b924946bdfdccc24c8dd0eeb803.svn-base +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using System.Runtime.Serialization; -using org.critterai.interop; -using org.critterai.nmgen.rcn; - -namespace org.critterai.nmgen -{ - /// - /// Contains triangle meshes that represent detailed height data - /// associated with the polygons in its associated - /// object. - /// - /// - /// - /// Warning: The serializable attribute and interface will be removed in v0.5. Use - /// instead. - /// - /// - /// The detail mesh is made up of triangle sub-meshes which provide extra height detail for - /// each polygon in its assoicated polygon mesh. - /// - /// - /// This class is moslty opaque. The class provides the - /// ability to inspect and update the content. - /// - /// - /// This class is not compatible with Unity serialization. The - /// method can be used for manual serialization within Unity. - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - [Serializable] - [StructLayout(LayoutKind.Sequential)] - public sealed class PolyMeshDetail - : IManagedObject, ISerializable - { - /* - * Design Notes: - * - * The internal structure of this class will have to be transformed to - * match the pattern used by PolyMesh in order to add the merge - * mesh functionality. (Can't pass arrays of pointers across the - * interop boundary.) Not changing the structure until then. - * - */ - - private const string DataKey = "d"; - - private IntPtr mMeshes; - private IntPtr mVerts; - private IntPtr mTris; - private int mMeshCount; - private int mVertCount; - private int mTriCount; - - private int mMaxMeshes; - private int mMaxVerts; - private int mMaxTris; - private readonly AllocType mResourceType; - - /// - /// The number of sub-meshes in the detail mesh. - /// - public int MeshCount { get { return mMeshCount; } } - - /// - /// The total number of vertices in the detail mesh. - /// - public int VertCount { get { return mVertCount; } } - - /// - /// The total number of triangles in the detail mesh. - /// - public int TriCount { get { return mTriCount; } } - - /// - /// The maximum number of sub-meshes the mesh buffers can hold. - /// - public int MaxMeshes { get { return mMaxMeshes; } } - - /// - /// The maximum number of vertices the vertex buffer can hold. - /// - public int MaxVerts { get { return mMaxVerts; } } - - /// - /// The maximum number of triangls the triangle buffers can hold. - /// - public int MaxTris { get { return mMaxTris; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return (mMeshes == IntPtr.Zero); } } - - /// - /// The type of unmanaged resources within the object. - /// - public AllocType ResourceType { get { return mResourceType; } } - - /// - /// Constructs an object with all buffers allocated and ready to load with data. - /// (See: ) - /// - /// - /// The maximum vertices the vertex buffer will hold. [Limit: >= 3] - /// - /// - /// The maximum triangles the triangle buffer will hold. [Limit: > 0] - /// - /// - /// The maximum sub-meshes the mesh buffer will hold. [Limit: > 0] - /// - private PolyMeshDetail(int maxVerts - , int maxTris - , int maxMeshes) - { - if (maxVerts < 3 || maxTris < 1 || maxMeshes < 1) - return; - - mResourceType = AllocType.Local; - - mMaxVerts = maxVerts; - mMaxTris = maxTris; - mMaxMeshes = maxMeshes; - - int size = sizeof(float) * mMaxVerts * 3; - mVerts = UtilEx.GetBuffer(size, true); - - size = sizeof(byte) * mMaxTris * 4; - mTris = UtilEx.GetBuffer(size, true); - - size = sizeof(uint) * mMaxMeshes * 4; - mMeshes = UtilEx.GetBuffer(size, true); - } - - private PolyMeshDetail(AllocType resourceType) - { - mResourceType = resourceType; - } - - private PolyMeshDetail(SerializationInfo info, StreamingContext context) - { - // Note: Version compatability is handled by the interop call. - if (info.MemberCount != 1) - return; - - byte[] rawData = (byte[])info.GetValue(DataKey, typeof(byte[])); - PolyMeshDetailEx.rcpdBuildFromMeshData(rawData, rawData.Length, this); - } - - /// - /// Destructor. - /// - ~PolyMeshDetail() - { - RequestDisposal(); - } - - /// - /// Loads the data into the mesh buffers, overwriting existing content. - /// - /// The data to load. - /// True if the load was successful. - public bool Load(PolyMeshDetailData data) - { - if (IsDisposed - || data == null - || data.meshes == null - || data.tris == null - || data.verts == null - || data.meshCount < 0 || data.meshCount > mMaxMeshes - || data.triCount < 0 || data.triCount > mMaxTris - || data.vertCount < 0 || data.vertCount > mMaxVerts - || data.meshes.Length < data.meshCount * 4 - || data.tris.Length < data.triCount * 4 - || data.verts.Length < data.vertCount) - { - return false; - } - - mMeshCount = data.meshCount; - mTriCount = data.triCount; - mVertCount = data.vertCount; - - UtilEx.Copy(data.meshes, 0, mMeshes, mMeshCount * 4); - Marshal.Copy(data.tris, 0, mTris, mTriCount * 4); - float[] fverts = Vector3Util.Flatten(data.verts, mVertCount); - Marshal.Copy(fverts, 0, mVerts, mVertCount * 3); - - return true; - } - - /// - /// Gets the data from the mesh buffers. - /// - /// - /// - /// This method is useful for extracting mesh data so it can be inspected or altered and - /// reloaded. - /// - /// - /// - /// If true, includes the unused buffer space. Otherwise only the used buffer data is - /// returned. - /// - /// The data from the mesh buffers. - public PolyMeshDetailData GetData(bool includeBuffer) - { - if (IsDisposed) - return null; - - PolyMeshDetailData result = new PolyMeshDetailData( - (includeBuffer ? mMaxVerts : mVertCount) - , (includeBuffer ? mMaxTris : mTriCount) - , (includeBuffer ? mMaxMeshes : mMeshCount)); - - FillData(result); - - return result; - } - - /// - /// Loads the data from the mesh buffers into the data object. - /// - /// - /// - /// If the buffer argument is null, a new buffer will be returned. If the buffer is too - /// small it will be resized. - /// - /// - /// Only the used portions of the mesh buffers are copied. - /// - /// - /// A buffer to load the data into. - /// A reference to the mesh data. - public PolyMeshDetailData GetData(PolyMeshDetailData buffer) - { - if (IsDisposed) - return null; - if (buffer == null) - return GetData(true); - - if (!buffer.CanFit(mVertCount, mTriCount, mMeshCount)) - buffer.Reset(mMaxVerts, mMaxTris, mMaxMeshes); - - FillData(buffer); - - return buffer; - - } - - private void FillData(PolyMeshDetailData buffer) - { - buffer.vertCount = mVertCount; - buffer.triCount = mTriCount; - buffer.meshCount = mMeshCount; - - float[] fverts = new float[mVertCount * 3]; - Marshal.Copy(mVerts, fverts, 0, mVertCount * 3); - buffer.verts = Vector3Util.GetVectors(fverts, 0, buffer.verts, 0, mVertCount); - Marshal.Copy(mTris, buffer.tris, 0, mTriCount * 4); - UtilEx.Copy(mMeshes, buffer.meshes, mMeshCount * 4); - } - - /// - /// Frees all resources and marks the object as disposed. - /// - public void RequestDisposal() - { - if (!IsDisposed) - { - if (ResourceType == AllocType.Local) - { - Marshal.FreeHGlobal(mMeshes); - Marshal.FreeHGlobal(mTris); - Marshal.FreeHGlobal(mVerts); - } - else if (ResourceType == AllocType.External) - PolyMeshDetailEx.rcpdFreeMeshData(this); - - mMeshes = IntPtr.Zero; - mTris = IntPtr.Zero; - mVerts = IntPtr.Zero; - mMeshCount = 0; - mVertCount = 0; - mTriCount = 0; - mMaxMeshes = 0; - mMaxTris = 0; - mMaxVerts = 0; - } - } - - /// - /// Gets a serialized version of the mesh that can be used to recreate it later. - /// - /// - /// True if serialized data should include the full buffer size. Otherwise the buffers will - /// be stripped and the smallest possible serialized data returned. - /// - /// A serialized version of the mesh. - public byte[] GetSerializedData(bool includeBuffer) - { - if (IsDisposed) - return null; - - // Design note: This is implemented using interop calls - // bacause it is so much easier and faster to serialize in C++ - // than in C#. - - IntPtr ptr = IntPtr.Zero; - int dataSize = 0; - - if (!PolyMeshDetailEx.rcpdGetSerializedData(this - , includeBuffer - , ref ptr - , ref dataSize)) - { - return null; - } - - byte[] result = UtilEx.ExtractArrayByte(ptr, dataSize); - - NMGenEx.nmgFreeSerializationData(ref ptr); - - return result; - } - - /// - /// Gets serialization data for the object. - /// - /// - /// - /// Will always include the unused buffer space. (No compression.) - /// - /// - /// Serialization information. - /// Serialization context. - public void GetObjectData(SerializationInfo info, StreamingContext context) - { - /* - * Design Notes: - * - * Default serialization security is OK. - * Validation and versioning is handled by GetSerializedData(). - */ - - byte[] rawData = GetSerializedData(true); - - if (rawData == null) - return; - - info.AddValue(DataKey, rawData); - } - - /// - /// Builds a detail mesh from the provided polygon mesh. - /// - /// The context to use for the operation. - /// The source polygon mesh. - /// The compact heightfield used to build the polygon mesh. - /// - /// The sample distance to use when sampling the surface height of the polygon mesh. - /// - /// - /// The maximum the surface of the detail mesh should deviate from the heightfield data. - /// - /// A new detail mesh, or null on error. - public static PolyMeshDetail Build(BuildContext context - , PolyMesh polyMesh, CompactHeightfield field - , float detailSampleDistance, float detailMaxDeviation) - { - if (context == null || polyMesh == null || polyMesh.IsDisposed - || field == null || field.IsDisposed - || detailSampleDistance < 0 - || detailMaxDeviation < 0) - { - return null; - } - - PolyMeshDetail result = new PolyMeshDetail(AllocType.External); - - if (PolyMeshDetailEx.rcpdBuildPolyMeshDetail(context.root - , ref polyMesh.root - , field - , detailSampleDistance - , detailMaxDeviation - , result)) - { - return result; - } - - return null; - } - - /// - /// Constructs an object with all buffers allocated and ready to load with data. - /// (See: ) - /// - /// - /// The maximum vertices the vertex buffer will hold. [Limit: >= 3] - /// - /// - /// The maximum triangles the triangle buffer will hold. [Limit: > 0] - /// - /// - /// The maximum sub-meshes the mesh buffer will hold. [Limit: > 0] - /// - /// The new detail mesh, or null on error. - public static PolyMeshDetail Create(int maxVerts - , int maxTris - , int maxMeshes) - { - if (maxVerts < 3 || maxTris < 1 || maxMeshes < 1) - return null; - - return new PolyMeshDetail(maxVerts, maxTris, maxMeshes); - } - - /// - /// Constructs a detail mesh from the data generated by the - /// method. - /// - /// The source data. - /// The new detail mesh, or null on error. - public static PolyMeshDetail Create(byte[] serializedMesh) - { - PolyMeshDetail result = new PolyMeshDetail(AllocType.External); - - if (PolyMeshDetailEx.rcpdBuildFromMeshData(serializedMesh - , serializedMesh.Length - , result)) - { - return result; - } - - return null; - } - } -} diff --git a/critterai/.svn/pristine/b9/b98f3073f812b721817e48d5b400fffcdd6834b4.svn-base b/critterai/.svn/pristine/b9/b98f3073f812b721817e48d5b400fffcdd6834b4.svn-base deleted file mode 100644 index 1097a1ad..00000000 --- a/critterai/.svn/pristine/b9/b98f3073f812b721817e48d5b400fffcdd6834b4.svn-base +++ /dev/null @@ -1,317 +0,0 @@ - - - - - - - - This topic covers the core process used by NMGen to create polygon data that will represent the navigation mesh surface. - There are many variations on the mesh generation process, but they all include these steps. - - - - The IncrementalBuilder extension implements this process. - - - - The high level process is as follows: - - - - - - - Voxelization - http://www.cs.sunysb.edu/~vislab/projects/volume/Papers/Voxel/index.html - _blank - : Create a solid heightfield from the source geometry representing obstructed space. - - - Generate Regions: Detect the upper surface of the solid heightfield and divide it up - into regions of contiguous spans. - - - Generate Contours: Detect the contours of the regions and form them into - - simple polygons - http://en.wikipedia.org/wiki/Polygon#Convexity_and_types_of_non-convexity - _blank - . - - - Generate Polygon Mesh: Sub-divide the contours into convex polygons. - - Generate Height Detail: - - Triangulate - http://mathworld.wolfram.com/Triangulation.html - _blank - the polygon mesh and add height detail. (Optional) - - - - - - -
      - - Voxelization - - - - - Core Class: T:org.critterai.nmgen.Heightfield - - - During voxelization the source geometry is abstracted into a heightfield which represents - obstructed space. Then some initial culling of un-walkable surfaces is performed. - - - - Each triangle in the source geometry is voxelized using conservative voxelization and - added to the field. Conservative voxelization is an algorithm that ensures the triangle surfaces - are completely encompassed by the the generated voxels. - - - - After voxelization, the solid heightfield contains spans that completely encompass the - surface of all polygons in the source geometry. - - - - - - -
      - -
      - - Region Generation - - - - - Core Class: T:org.critterai.nmgen.CompactHeightfield - - - - The goal of this stage is to further define what portion of the solid surface is - traversable, and to segregate the traversable areas into contiguous regions of spans - (surfaces) that can eventually be formed into simple polygons. - - - - The first step is to translate the solid heightfield into an open heightfield which - represents the potential traversable surfaces on top of the solid space. An open heightfield - represents the potential floor area on the surface of solid space. - - - - In the below example, the green area represents the floor defined by the open spans. - These correspond to the top of all traversable spans in the solid heightfield. Note that walls, - areas under the tables, and some thin areas such as the balcony banisters were culled during - the solid heightfield generation process. Some un-walkable areas such as table tops, the stair - banisters, and thin wall ledges still show as traversable at this point. - - - - - - Next, further culling of un-walkable spans occurs. At the end of the process, open spans - are only considered traversable if they pass the following tests: - - - - - The span is not too close to an obstruction. (Such as walls, furniture, etc.) - (WalkableRadius) - - The span has sufficient unobstructed space above its floor. - (Agents can legally walk on the span without colliding with objects above the span.) - (WalkableHeight) - - - - - Neighbor information is generated for all surviving open spans to help group them - together into true surface areas. The algorithm takes into account a maximum vertical step - threshold to determine which spans can connect. (WalkableStep) - This permits structures such as stairs, curbs, table tops, etc. to be properly taken into - account. For example, spans that make up different steps in a stairway will be connected - as neighbors. But spans on a table top will not be connected to spans that make - up the adjacent floor. - - - - Regions are generated using the neighbor information and the watershed algorithm. - Region size is optimized and island regions too small to be of use (e.g. table tops) - are culled. (MinRegionArea) - - - - The below example shows regions. Note that regions flow up the stairs, even though - the spans that make up stairways don't actually connect. Also note that the table tops, - stair banisters, and all other un-walkable surfaces that made it through the - solid heightfield generation process have been successfully culled. (Black indicates - culled spans.) - - - - - - At the end of this stage, the traversable surface is represented by regions of - connected spans. - - - - -
      - - -
      - - Contour Generation - - - - Core Class: T:org.critterai.nmgen.ContourSet - - - - The contours of the regions are 'walked', forming simple polygons. This is the - first step in the process of moving from voxel space back into vector space. - - - - First, highly detailed polygons are generated from the regions. - - - - - - Next, various algorithms are used to accomplish the following: - - - - - - Simplify the edges between adjacent polygons. (The portals between regions.) - - - - Simplify the border edges (Border edges are the contour edges that connect to - empty or obstructed space.) (EdgeMaxDeviation) - - - - Optimize the length of the border edges. (Borders that are too long can form - non-optimal triangles later in the process.) (MaxEdgeLength) - - - - - - This next example shows the contours after these algorithms have been run. - - - - - - At the end of this stage, the traversable surface is represented by simple polygons. - - - - -
      - -
      - - Convex Polygon Generation - - - - - Core Class: PolyMesh - - - - Many algorithms can only be used with convex polygons. So this step subdivides - the simple polygons that make up the contours into a mesh of convex polygons. - - - - - - - This is the mesh used for most pathfinding purposes. - - - - - - Below you can see that a mixture of concave polygons have been formed from the contours. - - - - - - At the end of this stage, the traversable surface is represented by a mesh of - convex polygons. - - - - -
      - -
      - - Height Detail Generation - - - - - Core Class: DetailMesh - - - - In the final stage, the convex polygon mesh is triangulated using - - Delaunay triangulation - http://en.wikipedia.org/wiki/Delaunay_triangulation - _blank - so that height detail can be added. Vertices are added internally and to the - edges of polygons to ensure the original geometry's surface is adequately followed. - (DetailSampleDistance and DetailMaxDeviation) - - - - - - - Technically, this is an optional step. The detail mesh is not required for - pathfinding. But certain queries will return more accurate height data if the - detail mesh is available. - - - - - - - - -
      - - - - T:org.critterai.nmbuild.IncrementalBuilder - T:org.critterai.nmgen.PolyMesh - T:org.critterai.nmgen.PolyMeshDetail - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/b9/b9b0737729710c266bf6f1fd9d2f7f2de235dc7b.svn-base b/critterai/.svn/pristine/b9/b9b0737729710c266bf6f1fd9d2f7f2de235dc7b.svn-base deleted file mode 100644 index b53743f0..00000000 --- a/critterai/.svn/pristine/b9/b9b0737729710c266bf6f1fd9d2f7f2de235dc7b.svn-base +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Loads and compiles all components in the scene, based on the -/// standard scene query behavior. (Editor Only) -/// -public sealed class OFMConnectionCompiler - : ScriptableObject, IInputBuildProcessor -{ - /// - /// The priority of the processor. - /// - public int Priority { get { return NMBuild.MinPriority; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// Duplicates not allowed. (Always false.) - /// - public bool DuplicatesAllowed { get { return false; } } - - /// - /// Processes the context. - /// - /// - /// - /// Processes during the - /// and states. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (context != null) - { - switch (state) - { - case InputBuildState.CompileInput: - - Compile(context); - break; - - case InputBuildState.LoadComponents: - - Load(context); - break; - } - } - - return true; - } - - private void Load(InputBuildContext context) - { - context.info.loaderCount++; - - int count = context.LoadFromScene(); - - context.Log(string.Format("Loaded {0} off-mesh connections.", count), this); - } - - private void Compile(InputBuildContext context) - { - context.info.compilerCount++; - - ConnectionSetCompiler compiler = context.connCompiler; - List items = context.components; - List areas = context.areas; - - int count = 0; - - for (int i = 0; i < items.Count; i++) - { - Component item = items[i]; - - if (item is OFMConnection) - { - OFMConnection conn = (OFMConnection)item; - byte area = (conn.OverrideArea ? conn.Area : areas[i]); - - compiler.Add(conn.StartPoint, conn.EndPoint - , conn.Radius - , conn.IsBidirectional - , area - , conn.Flags - , (uint)conn.UserId); - - count++; - } - } - - context.Log(string.Format("Compiled off-mesh connections: {0}", count), this); - } -} diff --git a/critterai/.svn/pristine/ba/ba2fe76ef11f50f462167eab89c0214c3499ae54.svn-base b/critterai/.svn/pristine/ba/ba2fe76ef11f50f462167eab89c0214c3499ae54.svn-base deleted file mode 100644 index 6e3c56cf..00000000 --- a/critterai/.svn/pristine/ba/ba2fe76ef11f50f462167eab89c0214c3499ae54.svn-base +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.*; -import static org.critterai.math.geom.Line2.*; - -import org.critterai.math.Vector2; -import org.critterai.math.geom.Line2; -import org.critterai.math.geom.LineRelType; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Line2} class. - */ -public class Line2Tests { - - private static final float AX = -5; - private static final float AY = 3; - private static final float BX = 1; - private static final float BY = 1; - private static final float CX = -3; - private static final float CY = 0; - private static final float DX = -1; - private static final float DY = 4; - private static final float EX = -2; - private static final float EY = 2; - private static final float FX = 4; - private static final float FY = 0; - private static final float GX = 0; - private static final float GY = 3; - private static final float HX = 2; - private static final float HY = -1; - private static final float JX = -4; - private static final float JY = 1; - private static final float KX = -4; - private static final float KY = -2; - - private static final int AXI = -5; - private static final int AYI = 3; - private static final int BXI = 1; - private static final int BYI = 1; - private static final int CXI = -3; - private static final int CYI = 0; - private static final int DXI = -1; - private static final int DYI = 4; - private static final int EXI = -2; - private static final int EYI = 2; - private static final int FXI = 4; - private static final int FYI = 0; - private static final int GXI = 0; - private static final int GYI = 3; - - @Before - public void setUp() throws Exception - { - } - - @Test - public void testLinesIntersectFloat() - { - // Standard. Cross within segments. - assertTrue(linesIntersect(AX, AY, BX, BY, CX, CY, DX, DY)); - assertTrue(linesIntersect(BX, BY, AX, AY, CX, CY, DX, DY)); - assertTrue(linesIntersect(BX, BY, AX, AY, DX, DY, CX, CY)); - assertTrue(linesIntersect(AX, AY, BX, BY, DX, DY, CX, CY)); - - // Standard. Cross outside segment. - assertTrue(linesIntersect(AX, AY, BX, BY, DX, DY, GX, GY)); - assertTrue(linesIntersect(BX, BY, AX, AY, DX, DY, GX, GY)); - assertTrue(linesIntersect(BX, BY, AX, AY, GX, GY, DX, DY)); - assertTrue(linesIntersect(AX, AY, BX, BY, GX, GY, DX, DY)); - - // Collinear - assertTrue(linesIntersect(AX, AY, BX, BY, EX, EY, FX, FY)); - assertTrue(linesIntersect(BX, BY, AX, AY, EX, EY, FX, FY)); - assertTrue(linesIntersect(BX, BY, AX, AY, FX, FY, EX, EY)); - assertTrue(linesIntersect(AX, AY, BX, BY, FX, FY, EX, EY)); - - // Parallel Diagonal - assertFalse(linesIntersect(AX, AY, BX, BY, EX-2, EY, FX-2, FY)); - assertFalse(linesIntersect(BX, BY, AX, AY, EX-2, EY, FX-2, FY)); - assertFalse(linesIntersect(BX, BY, AX, AY, FX-2, FY, EX-2, EY)); - assertFalse(linesIntersect(AX, AY, BX, BY, FX-2, FY, EX-2, EY)); - - // Parallel Vertical - assertFalse(linesIntersect(AX, 5, BX, 5, EX, 3, FX, 3)); - - // Parallel Horizontal - assertFalse(linesIntersect(5, AY, 5, BY, 2, CY, 2, DY)); - } - - @Test - public void testLinesIntersectInt() - { - // Standard. Cross within segments. - assertTrue(linesIntersect(AXI, AYI, BXI, BYI, CXI, CYI, DXI, DYI)); - - // Standard. Cross outside segment. - assertTrue(linesIntersect(AXI, AYI, BXI, BYI, DXI, DYI, GXI, GYI)); - - // Collinear - assertTrue(linesIntersect(AXI, AYI, BXI, BYI, EXI, EYI, FXI, FYI)); - - // Parallel Diagonal - assertFalse(linesIntersect(AXI, AYI, BXI, BYI, EXI-2, EYI, FXI-2, FYI)); - - // Parallel Vertical - assertFalse(linesIntersect(AXI, 5, BXI, 5, EXI, 3, FXI, 3)); - - // Parallel Horizontal - assertFalse(linesIntersect(5, AYI, 5, BYI, 2, CYI, 2, DYI)); - } - - @Test - public void testGetPointSegmentDistanceSqFloat() - { - // Closest to end point B. - float expected = Vector2.getDistanceSq(HX, HY, BX, BY); - assertTrue(getPointSegmentDistanceSq(HX, HY, EX, EY, BX, BY) == expected); - - // Closest to end point E. - expected = Vector2.getDistanceSq(JX, JY, EX, EY); - assertTrue(getPointSegmentDistanceSq(JX, JY, EX, EY, BX, BY) == expected); - - // Closest to mid-point of AB. (E) - expected = Vector2.getDistanceSq(-1, 5, EX, EY); - assertTrue(getPointSegmentDistanceSq(-1, 5, AX, AY, BX, BY) == expected); - expected = Vector2.getDistanceSq(-3, -1, EX, EY); - assertTrue(getPointSegmentDistanceSq(-3, -1, AX, AY, BX, BY) == expected); - } - - @Test - public void testGetPointLineDistanceSqFloat() - { - - float expected = Vector2.getDistanceSq(-3, -1, EX, EY); - float actual = getPointLineDistanceSq(-3, -1, AX, AY, BX, BY); - assertTrue(actual == expected); - expected = Vector2.getDistanceSq(-1, 5, EX, EY); - actual = getPointLineDistanceSq(-1, 5, AX, AY, BX, BY); - assertTrue(actual == expected); - expected = 0; - actual = getPointLineDistanceSq(FX, FY, AX, AY, BX, BY); - assertTrue(actual == expected); - - - } - - @Test - public void testGetNormalAB() - { - - // Diagonal - Vector2 v = new Vector2(); - Vector2 expected = new Vector2(-1, -3).normalize(); - assertTrue(v == getNormalAB(AX, AY, BX, BY, v)); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Reversed Diagonal - expected = new Vector2(1, 3).normalize(); - getNormalAB(BX, BY, AX, AY, v); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Vertical - expected = new Vector2(-1, 0); - getNormalAB(5, AY, 5, BY, v); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Horizontal - expected = new Vector2(0, -1); - getNormalAB(AX, 5, BX, 5, v); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Not a line. - getNormalAB(AX, AY, AX, AY, v); - assertTrue(v.equals(0, 0)); - - } - - @Test - public void testGetRelationship() - { - Vector2 v = new Vector2(); - assertTrue(LineRelType.SEGMENTS_INTERSECT - == getRelationship(AX, AY, BX, BY, CX, CY, DX, DY, v)); - assertTrue(v.sloppyEquals(EX, EY, 0.0001f)); - - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(AX, AY, EX, EY, GX, GY, HX, HY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - - // Line reversal checks. - v = new Vector2(); - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(EX, EY, AX, AY, GX, GY, HX, HY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - v = new Vector2(); - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(EX, EY, AX, AY, HX, HY, GX, GY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - v = new Vector2(); - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(AX, AY, EX, EY, HX, HY, GX, GY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - - assertTrue(LineRelType.BLINE_CROSSES_ASEG - == getRelationship(AX, AY, BX, BY, KX, KY, CX, CY, v)); - assertTrue(v.sloppyEquals(EX, EY, 0.0001f)); - - v = new Vector2(); - assertTrue(LineRelType.LINES_INTERSECT - == getRelationship(KX, KY, CX, CY, FX, FY, BX, BY, v)); - assertTrue(v.sloppyEquals(EX, EY, 0.0001f)); - - // NULL version. - assertTrue(LineRelType.SEGMENTS_INTERSECT - == getRelationship(AX, AY, BX, BY, CX, CY, DX, DY, null)); - - v = new Vector2(JX, JY); - - assertTrue(LineRelType.PARALLEL - == getRelationship(AX, AY, BX, BY, EX-2, EY, FX-2, FY, null)); - assertTrue(v.equals(JX, JY)); - - // Collinear - No segment overlap. - assertTrue(LineRelType.COLLINEAR - == getRelationship(AX, AY, EX, EY, BX, BY, FX, FY, null)); - assertTrue(v.equals(JX, JY)); - - // Collinear - Segment overlap. - assertTrue(LineRelType.COLLINEAR - == getRelationship(AX, AY, BX, BY, EX, EY, FX, FY, null)); - assertTrue(v.equals(JX, JY)); - - - - } - -} diff --git a/critterai/.svn/pristine/ba/ba9572125871806fe0bd4d661648e78c21833cea.svn-base b/critterai/.svn/pristine/ba/ba9572125871806fe0bd4d661648e78c21833cea.svn-base deleted file mode 100644 index 31d79d85..00000000 Binary files a/critterai/.svn/pristine/ba/ba9572125871806fe0bd4d661648e78c21833cea.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/bb/bb03dde0833403cb8090fb45a56de6e6c573c442.svn-base b/critterai/.svn/pristine/bb/bb03dde0833403cb8090fb45a56de6e6c573c442.svn-base deleted file mode 100644 index 39786201..00000000 --- a/critterai/.svn/pristine/bb/bb03dde0833403cb8090fb45a56de6e6c573c442.svn-base +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.u3d; - -/// -/// Provides data useful for marking an area using a cylinder shape. -/// -/// -/// -/// The data is in a format compatible with the CompactHeightfield.MarkCylinderArea() method. -/// -/// -/// The y- and x-scales are used to size the cylinder. The z-scale is ignored. -/// -/// -/// Rotation is ignored. -/// -/// -[ExecuteInEditMode] -public sealed class CylinderAreaMarker - : NMGenAreaMarker -{ - /// - /// Cylinder marker data. - /// - public struct MarkerData - { - /// - /// The area to apply. - /// - public byte area; - - /// - /// The marker priority. - /// - public int priority; - - /// - /// The world center point of the base of the cylinder. - /// - public Vector3 centerBase; - - /// - /// The world radius of the cylinder. - /// - public float radius; - - /// - /// The world height of the cylinder, relative to its base. - /// - public float height; - } - - /// - /// The marker data. - /// - /// The marker data. - public MarkerData GetMarkerData() - { - MarkerData result = new MarkerData(); - - Transform trans = transform; - Vector3 scale = trans.localScale; - - result.area = Area; - result.priority = Priority; - result.centerBase = trans.position - Vector3.up * scale.y * 0.5f; - result.radius = scale.x; - result.height = scale.y; - - return result; - } - - void OnRenderObject() - { - if (!debugEnabled && !debugEnabledLocal) - return; - - // The color for area zero is hard to see. So using black. - Color color = (Area == 0 ? new Color(0, 0, 0, 0.8f) : ColorUtil.IntToColor(Area, 0.8f)); - - Transform trans = transform; - Vector3 scale = trans.localScale; - - DebugDraw.Cylinder(trans.position - Vector3.up * scale.y * 0.5f - , scale.x, scale.y, false, color); - } -} diff --git a/critterai/.svn/pristine/bb/bb0e28909fc83b8e97da759f17a24597e809727f.svn-base b/critterai/.svn/pristine/bb/bb0e28909fc83b8e97da759f17a24597e809727f.svn-base deleted file mode 100644 index 98819dad..00000000 --- a/critterai/.svn/pristine/bb/bb0e28909fc83b8e97da759f17a24597e809727f.svn-base +++ /dev/null @@ -1,5 +0,0 @@ -This distribution contians libraries and documentation for a CritterAI project. - -CritterAI Home: http://www.critterai.org/ -CritterAI Code: http://code.google.com/p/critterai/ -License: http://www.critterai.org/cailic diff --git a/critterai/.svn/pristine/bb/bbbce5ea75f97b09fa581bcb7c618df7c0c4252c.svn-base b/critterai/.svn/pristine/bb/bbbce5ea75f97b09fa581bcb7c618df7c0c4252c.svn-base deleted file mode 100644 index c3df5f33..00000000 Binary files a/critterai/.svn/pristine/bb/bbbce5ea75f97b09fa581bcb7c618df7c0c4252c.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/bb/bbe7ec7cdfb7cdf235f0b0abac328d7a8714dcd9.svn-base b/critterai/.svn/pristine/bb/bbe7ec7cdfb7cdf235f0b0abac328d7a8714dcd9.svn-base deleted file mode 100644 index 59eb81b6..00000000 --- a/critterai/.svn/pristine/bb/bbe7ec7cdfb7cdf235f0b0abac328d7a8714dcd9.svn-base +++ /dev/null @@ -1,56 +0,0 @@ - - - - Download CAINav - http://code.google.com/p/critterai/downloads/list - - - Sample Pack - http://code.google.com/p/critterai/downloads/list - - -T:org.critterai.nmgen.CompactHeightfield - - -T:org.critterai.nmbuild.ConnectionSet - - -T:org.critterai.nav.CrowdManager - - -T:org.critterai.nmgen.PolyMeshDetail - - -T:org.critterai.nmbuild.IncrementalBuilder - - -T:org.critterai.nmbuild.INMGenProcessor - - -T:org.critterai.nmbuild.InputGeometry - - -T:org.critterai.nav.Navmesh - - -T:org.critterai.nav.NavmeshQuery - - -T:org.critterai.nav.NavmeshQueryFilter - - -T:org.critterai.nav.PathCorridor - - -T:org.critterai.nmgen.PolyMesh - - -T:org.critterai.nmbuild.ProcessorSet - - -T:org.critterai.nmbuild.TileSetDefinition - - -T:org.critterai.nmgen.NMGenParams - - \ No newline at end of file diff --git a/critterai/.svn/pristine/bc/bc3294482ef72495de35b53b575c5930b5fadc48.svn-base b/critterai/.svn/pristine/bc/bc3294482ef72495de35b53b575c5930b5fadc48.svn-base deleted file mode 100644 index b53a3639..00000000 --- a/critterai/.svn/pristine/bc/bc3294482ef72495de35b53b575c5930b5fadc48.svn-base +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nav -{ - /// - /// Polygon data for a polygon in a navigation mesh tile. - /// - /// - /// - /// This structure is provided for debug purposes. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct NavmeshPoly - { - /// - /// Index to first link in the linked list. - /// (Or if there is no link.) - /// - public uint firstLink; - - // Yes, the size has been confirmed as correct. The size is not - // effected by the maxVertsPerPoly used to construct the navmesh. - /// - /// Indices to the polygon's vertices. - /// [Length: ] - /// - /// - /// - /// The indices refer vertices in the polygon's tile. - /// - /// - [MarshalAs(UnmanagedType.ByValArray - , SizeConst = Navmesh.MaxAllowedVertsPerPoly)] - public ushort[] indices; - - /// - /// Packed data representing neighbor polygon ids and flags for each edge. - /// - /// - /// - /// Length: . - /// - /// Each entry represents data for the edge starting at the vertex of the same index. - /// E.g. The entry at index n represents the edge data for vertex[n] - /// to vertex[n+1]. - /// - /// - /// A value of zero indicates the edge has no polygon connection. - /// (It makes up the border of the navigation mesh.) - /// - /// - /// The polygon id can be found as follows: (int)neighborPolyRefs[n] & 0xff - /// - /// - /// The edge is an external (portal) edge if the following test is true: - /// (neighborPolyRefs[n] & Navmesh.ExternalLink) == 0 - /// - /// - [MarshalAs(UnmanagedType.ByValArray - , SizeConst = Navmesh.MaxAllowedVertsPerPoly)] - public ushort[] neighborPolyRefs; - - /// - /// The polygon flags. - /// - public ushort flags; - - /// - /// The number of vertices in the polygon. - /// - /// - /// - /// The value will be between 3 and inclusive - /// for standard polygons, and 2 for off-mesh connections. - /// - /// - public byte vertCount; - - /// - /// A packed value. See associated properties. - /// - private byte mAreaAndType; - - /// - /// The polygon's user defined area. - /// - public byte Area - { - get { return (byte)(mAreaAndType & 0x3f); } - } - - /// - /// The type of polygon. - /// - public NavmeshPolyType Type - { - get { return (NavmeshPolyType)(mAreaAndType >> 6); } - } - } -} diff --git a/critterai/.svn/pristine/bc/bc3a88f2ca95b0ea6a364331c9bb6a12b635aa1d.svn-base b/critterai/.svn/pristine/bc/bc3a88f2ca95b0ea6a364331c9bb6a12b635aa1d.svn-base deleted file mode 100644 index 74c8c6c1..00000000 --- a/critterai/.svn/pristine/bc/bc3a88f2ca95b0ea6a364331c9bb6a12b635aa1d.svn-base +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - CAINav is a navigation system for use with .NET and UnityPro on Windows. - It provides navigation mesh generation, pathfinding, and local steering functionality. - - - - At the core of CAINav is the well regarded RecastNavigation by - Mikko. This library is mostly about adapting Recast Navigation for use with .NET and Unity. - So most of the core features are courtesy of Mikko's work. - - - - - - This is an alpha release meant for use by early adopters. - - - Not all features have undergone rigorous testing. Some features have little documentation. - Expect frequent changes to the API and potentially breaking changed to Unity components. - E.g. Unity components may need to be deleted and re-created when migrating to a new release. - - - Feedback provided through the DiscussionGroup will be much appreciated. - - - - - CAINavDownload (Zip) - - - - -
      - - Navigation Mesh Generation - - - - - - Generates polygon meshes representing the traversable surface of arbitrary source geometry. - - - Core features are independent of the pathfinding and steering components, providing more options for work flow and distribution. - - - A highly extendable build process suitable for creating complex navigation meshes at design time. - - - Unity extensions that provide designer (non-coder) friendly build processes. - - - - - -
      - -
      - - Pathfinding - - - - - A* and Dijsktra searches. - Various local environment queries for fast, no search movement. - Easy management of path corridors. - - Custom connections between different areas of the mesh for non-standard movement. - (Off-mesh connections.) - - The ability to enable/disable polygons on a per agent basis. (Polygon filtering.) - The ability to define polygon traversal costs on a per agent basis. - Tiling of meshes to efficiently deal with large areas. - - - - -
      - -
      - - Local Steering - - - - - Local steering/collision avoidance for up to 20 agents. - Independent agents that respond to the presence of other agents. - Following behavior and moving as a group. - - - - -
      - -
      - - Miscellany - - - - - Core features available for use with Unity Pro and .NET-only implemenations. - Many ease-of-use extensions for Unity. - - Unity plug-in deployment restrictions - http://unity3d.com/support/documentation/Manual/Plugins.html - apply. E.g. Can't be deployed to the Unity web player. - - CAINav is not officially supported for use in the Unity Editor on the Mac OS, - or at runtime on any platform other than Windows. This is not a technical limitation, but is - due to the lack of non-Windows systems for builds and testing. - - - Does not support temporary obstacles. - - - - - -
      - -
      - - Sample Pack - - - - - The Sample Pack contains demos that will let you play around with various - the navigation features. Simply extract the contents and run the demos. They provides a lot of nice visualizations. - - - - - - Kaspersky Internet Security may report a PDM.Keylogger security warning - http://forum.unity3d.com/threads/36180-PDM.Keylogger-problem - when Feature Explorer is run. Kaspersky must not like the way - Unity detects keyboard input, because I certainly haven't included any viruses. Honest...really... - - - - The Sample Pack pre-compiled demos have been tested on 64-bit Windows 7 and 32-bit - Windows Vista. - - - - - - CAINavExplorerDownload (Download/Zip) - - - -
      - -
      -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/bc/bc5936afbd7ee3fd026c809a10e569e6350eaa64.svn-base b/critterai/.svn/pristine/bc/bc5936afbd7ee3fd026c809a10e569e6350eaa64.svn-base deleted file mode 100644 index 0d753694..00000000 --- a/critterai/.svn/pristine/bc/bc5936afbd7ee3fd026c809a10e569e6350eaa64.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Provides utilities useful for Contour tests. - */ -public final class ContourUtil -{ - private ContourUtil() { } - - /** - * Shifts the vertices one position higher in the list and - * inserts the last vertex into the first position. - * @param list The contour to shift. (Expecting a stride of 4.) - */ - public static void shiftContour(ArrayList list) - { - int size = list.size(); - - int entry0 = list.get(size-4); - int entry1 = list.get(size-3); - int entry2 = list.get(size-2); - int entry3 = list.get(size-1); - - for (int p = size - 5; p >= 0; p--) - { - list.set(p+4, list.get(p)); - } - - list.set(0, entry0); - list.set(1, entry1); - list.set(2, entry2); - list.set(3, entry3); - - } - -} diff --git a/critterai/.svn/pristine/bc/bc6beb9e77af8a8e96dd16cd0c4776eb6654d793.svn-base b/critterai/.svn/pristine/bc/bc6beb9e77af8a8e96dd16cd0c4776eb6654d793.svn-base deleted file mode 100644 index 2ea35cfe..00000000 --- a/critterai/.svn/pristine/bc/bc6beb9e77af8a8e96dd16cd0c4776eb6654d793.svn-base +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using System.Collections.Generic; -using UnityEditor; -using System.IO; - -namespace org.critterai.u3d.editor -{ - /// - /// Provides general purpose utility functions for the Unity Editor. - /// - public static class EditorUtil - { - /// - /// The base priority for the CAI asset creation menu. - /// - public const int AssetGroup = 100; - - /// - /// The base priority for the CAI game object creation menu. - /// - public const int GameObjectGroup = 1000; - - /// - /// The base priority for the CAI view menu. - /// - public const int ViewGroup = 2000; - - /// - /// The base priority for the CAI manager menu group. - /// - public const int ManagerGroup = 3000; - - /// - /// The base priority for the global menu group. - /// - public const int GlobalGroup = 4000; - - /// - /// The root CAI menu name. - /// - public const string MainMenu = "CritterAI/"; - - /// - /// The navigation asset menu name. - /// - public const string NavAssetMenu = MainMenu + "Create Nav Asset/"; - - /// - /// The NMGen asset menu name. - /// - public const string NMGenAssetMenu = MainMenu + "Create NMGen Asset/"; - - /// - /// The NMGen GameObject menu name. - /// - public const string NMGenGameObjectMenu = MainMenu + "Create NMGen/"; - - /// - /// The navigation GameObject menu name. - /// - public const string NavGameObjectMenu = MainMenu + "Create Nav/"; - - /// - /// The CAI view menu name. - /// - public const string ViewMenu = MainMenu + "View/"; - - private static GUIStyle mHelpStyle; - private static GUIStyle mWarningStyle; - private static GUIStyle mErrorStyle; - - /// - /// A general purpose error text box. - /// - public static GUIStyle ErrorStyle - { - get - { - if (mErrorStyle == null) - { - mErrorStyle = new GUIStyle(GUI.skin.box); - mErrorStyle.wordWrap = true; - mErrorStyle.alignment = TextAnchor.UpperLeft; - - Color c = Color.red; - c.a = 0.75f; - mErrorStyle.normal.textColor = c; - } - return mErrorStyle; - } - } - - /// - /// A general purpose warning text box. - /// - public static GUIStyle WarningStyle - { - get - { - if (mWarningStyle == null) - { - mWarningStyle = new GUIStyle(GUI.skin.box); - mWarningStyle.wordWrap = true; - mWarningStyle.alignment = TextAnchor.UpperLeft; - - Color c = Color.yellow; - c.a = 0.75f; - mWarningStyle.normal.textColor = c; - } - return mWarningStyle; - } - } - - /// - /// A general purpose help text box. - /// - public static GUIStyle HelpStyle - { - get - { - if (mHelpStyle == null) - { - mHelpStyle = new GUIStyle(GUI.skin.box); - mHelpStyle.wordWrap = true; - mHelpStyle.alignment = TextAnchor.UpperLeft; - - Color c = Color.white; - c.a = 0.75f; - mHelpStyle.normal.textColor = c; - - } - return mHelpStyle; - } - } - - /// - /// Provides an editor GUI for adding/removing objects from a list based on object type. - /// - /// The object type. - /// The GUI label. (Type description.) - /// The list of items to manage. - /// Allow scene objects in the list. - /// True if the GUI changed within the method. - public static bool OnGUIManageObjectList(string label, List items, bool allowScene) - where T : UnityEngine.Object - { - if (items == null) - return false; - - bool origChanged = GUI.changed; - GUI.changed = false; - - // Never allow nulls. So get rid of them first. - for (int i = items.Count - 1; i >= 0; i--) - { - if (items[i] == null) - { - items.RemoveAt(i); - GUI.changed = true; - } - } - - GUILayout.Label(label); - - if (items.Count > 0) - { - int delChoice = -1; - - for (int i = 0; i < items.Count; i++) - { - EditorGUILayout.BeginHorizontal(); - - T item = (T)EditorGUILayout.ObjectField(items[i], typeof(T), allowScene); - - if (item == items[i] || !items.Contains(item)) - items[i] = item; - - if (GUILayout.Button("X", GUILayout.Width(30))) - delChoice = i; - - EditorGUILayout.EndHorizontal(); - } - - if (delChoice >= 0) - { - GUI.changed = true; - items.RemoveAt(delChoice); - } - } - - EditorGUILayout.Separator(); - - T nitem = (T)EditorGUILayout.ObjectField("Add", null, typeof(T), allowScene); - - if (nitem != null) - { - if (!items.Contains(nitem)) - { - items.Add(nitem); - GUI.changed = true; - } - } - - bool result = GUI.changed; - GUI.changed = GUI.changed || origChanged; - - return result; - } - - /// - /// Provides an editor GUI for adding/removing strings from a list. - /// - /// The list of strings to manage. - /// True if the strings represent tags. - /// True if the GUI changed within the method. - public static bool OnGUIManageStringList(List items, bool isTags) - { - if (items == null) - return false; - - bool origChanged = GUI.changed; - GUI.changed = false; - - if (items.Count > 0) - { - GUILayout.Label((isTags ? "Tags" : "Items")); - - int delChoice = -1; - - for (int i = 0; i < items.Count; i++) - { - EditorGUILayout.BeginHorizontal(); - - string item; - - if (isTags) - item = EditorGUILayout.TagField(items[i]); - else - item = EditorGUILayout.TextField(items[i]); - - if (item == items[i] || !items.Contains(item)) - items[i] = item; - - if (GUILayout.Button("X", GUILayout.Width(30))) - delChoice = i; - - EditorGUILayout.EndHorizontal(); - } - - if (delChoice >= 0) - { - GUI.changed = true; - items.RemoveAt(delChoice); - } - } - - EditorGUILayout.Separator(); - - string ntag = EditorGUILayout.TagField("Add", ""); - - if (ntag.Length > 0) - { - if (!items.Contains(ntag)) - { - GUI.changed = true; - items.Add(ntag); - } - } - - bool result = GUI.changed; - GUI.changed = GUI.changed || origChanged; - - return result; - } - - /// - /// Creates a new asset in the same directory as the specified asset. - /// - /// The type of asse to create. - /// The asset where the new asset should be colocated. - /// The asset label. - /// The new asset. - public static T CreateAsset(ScriptableObject atAsset, string label) - where T : ScriptableObject - { - string name = typeof(T).ToString(); - string path = GenerateStandardPath(atAsset, name); - - T result = ScriptableObject.CreateInstance(); - result.name = name; - - AssetDatabase.CreateAsset(result, path); - - if (label.Length > 0) - AssetDatabase.SetLabels(result, new string[1] { label }); - - AssetDatabase.SaveAssets(); - AssetDatabase.ImportAsset(path); - - return result; - } - - /// - /// Creates a new asset at the standard path. - /// - /// - /// - /// This method tries to detect the directory of the currently selected asset. If it - /// can't, it will place the new asset in the root asset directory. - /// - /// - /// The type of asse to create. - /// The asset label. - /// The new asset. - public static T CreateAsset(string label) - where T : ScriptableObject - { - string name = typeof(T).Name; - string path = GenerateStandardPath(Selection.activeObject, name); - - T result = ScriptableObject.CreateInstance(); - result.name = name; - - AssetDatabase.CreateAsset(result, path); - - if (label.Length > 0) - AssetDatabase.SetLabels(result, new string[1] { label }); - - AssetDatabase.SaveAssets(); - AssetDatabase.ImportAsset(path); - - return result; - } - - /// - /// Gets the specified global asset. - /// - /// - /// - /// Global assets are singleton assets that exist in a well known path within the project. - /// - /// - /// If the global asset does not exist a new one will be created. So this method will - /// return null only on error. - /// - /// - /// The type of global asset. - /// The global asset. - public static T GetGlobalAsset() - where T : ScriptableObject - { - string name = typeof(T).Name; - - const string rootPath = "Assets/CAI/GlobalAssets/"; - - if (!Directory.Exists(rootPath)) - { - Debug.LogError("Global assets path does not exist: " + rootPath); - return null; - } - - string path = rootPath + name + ".asset"; - - T result = (T)AssetDatabase.LoadMainAssetAtPath(path); - - if (!result) - { - result = ScriptableObject.CreateInstance(); - result.name = name; - - AssetDatabase.CreateAsset(result, path); - AssetDatabase.ImportAsset(path); - } - - return result; - } - - /// - /// Attempts to get a scene position based on the current SceneView camera. - /// - /// - /// - /// This method is useful for creating game objects in the scene via script. - /// - /// - /// The returned position will be one of the following. (In order of priority.) - /// - ///
        - ///
      1. The hit position of a ray cast from the SceneView camera.
      2. - ///
      3. A position aproximately 15 units forward from the SceneView camera.
      4. - ///
      5. The zero vector.
      6. - ///
      - ///
      - /// The recommended position in the scene. - public static Vector3 GetCreatePosition() - { - Camera cam = SceneView.lastActiveSceneView.camera; - - if (!cam) - return Vector3.zero; - - RaycastHit hit; - Ray ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0)); - - if (Physics.Raycast(ray, out hit, 500)) - return hit.point; - - return cam.transform.position + cam.transform.forward * 15; - } - - private static string GenerateStandardPath(Object atAsset, string name) - { - string dir = AssetDatabase.GetAssetPath(atAsset); - - if (dir.Length == 0) - // Selection must not be an asset. - dir = "Assets"; - else if (!Directory.Exists(dir)) - // Selection must be a file asset. - dir = Path.GetDirectoryName(dir); - - return AssetDatabase.GenerateUniqueAssetPath(dir + "/" + name + ".asset"); - } - } -} diff --git a/critterai/.svn/pristine/bc/bcc2140ce3dc7372d0dc7188d71c0ea8d1025003.svn-base b/critterai/.svn/pristine/bc/bcc2140ce3dc7372d0dc7188d71c0ea8d1025003.svn-base deleted file mode 100644 index c2ecc981..00000000 --- a/critterai/.svn/pristine/bc/bcc2140ce3dc7372d0dc7188d71c0ea8d1025003.svn-base +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using Math = System.Math; // Used for rounding. -using org.critterai.nmgen; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Represents a configuration for a navigation mesh build in Unity. (Editor Only) - /// - /// - /// - /// See for details on the various properties. The primary difference - /// between this class and see cref="NMGenParams"/> is that some values in this class are in - /// world units rather than cell units. - /// - /// - [System.Serializable] - internal sealed class NMGenConfig - { - public const NMGenBuildFlag DefaultBuildFlags = - NMGenBuildFlag.LowHeightSpansNotWalkable - | NMGenBuildFlag.LowObstaclesWalkable - | NMGenBuildFlag.ApplyPolyFlags - | NMGenBuildFlag.BVTreeEnabled; - - #region Standard Param Labels - - public const string TileSizeLabel = "Tile Size (vx)"; - - public const string XZSizeLabel = "XZ Cell Size"; - - public const string YSizeLabel = "Y Cell Size"; - - public const string HeightLabel = "Walkable Height"; - - public const string StepLabel = "Walkable Step"; - - public const string SlopeLabel = "Walkable Slope"; - - public const string RadiusLabel = "Walkable Radius"; - - public const string EdgeLenLabel = "Max Edge Length"; - - public const string EdgeDevLabel = "Edge Max Deviation"; - - public const string DetailSampleLabel = "Detail Sample Dist"; - - public const string DetailDevLabel = "Detail Max Deviation"; - - public const string IslandRegionLabel = "Min Island Area"; - - public const string MaxPolyVertLabel = "Max Vertices Per Polygon"; - - public const string HFBorderLabel = "Border Size (vx)"; - - public const string TileBorderLabel = "Tile Border Size (vx)"; - - public const string MergeSizeLabel = "Merge Region Area"; - - public const string LedgeSpansLabel = "Ledges Not Walkable"; - - public const string BVTreeLabel = "BVTreeEnabled"; - - public const string LowHeightLabel = "Low Height Not Walkable"; - - public const string LowObstacleLabel = "Low Obstacles Walkable"; - - public const string TessAreasLabel = "Tessellate Area Edges"; - - public const string TessWallsLabel = "Tessellate Wall Edges"; - - public const string UseMonoLabel = "Use Monotone Partitioning"; - - public const string FlagPolysLabel = "Apply Poly Flag"; - - #endregion - - private static int mXZResolution = 1000; - private static int mYResolution = 1000; - private static int mDeviationFactor = 20; - private static int mSampleResolution = 100; - private static int mMaxCells = 1500; - private static int mStandardCells = 1000; - - public static int MaxCells - { - get { return mMaxCells; } - set { mMaxCells = Mathf.Max(4, value); } - } - - public static int StandardCells - { - get { return mStandardCells; } - set { mStandardCells = Mathf.Max(4, value); } - } - - /// - /// The xz-plane resolution to use when deriving a configuration. - /// - public static int XZResolution - { - get { return mXZResolution; } - set { mXZResolution = Mathf.Max(1, value); } - } - - /// - /// The y-axis resolution to use when deriving a configuration. - /// - public static int YResolution - { - get { return mYResolution; } - set { mYResolution = Mathf.Max(1, value); } - } - - /// - /// The detail deviation factor to use when deriving a configuration. - /// - public static int DetailDeviation - { - get { return mDeviationFactor; } - set { mDeviationFactor = Mathf.Max(0, value); } - } - - /// - /// The sample resolution to use when deriving a configuration. - /// - public static int DetailSampleResolution - { - get { return mSampleResolution; } - set { mSampleResolution = Mathf.Max(1, value); } - } - - // Remember: All locally stored fields are ignored - // in the root. So the root is not valid until the local - // data is transferred into it. - [SerializeField] - private NMGenParams mRoot; - - // World unit parameters. - [SerializeField] - private float mWalkableRadius; - [SerializeField] - private float mMaxEdgeLength; - [SerializeField] - private float mMinRegionArea; - [SerializeField] - private float mMergeRegionArea; - [SerializeField] - private float mWalkableHeight; - [SerializeField] - private float mWalkableStep; - - [SerializeField] - private NMGenBuildFlag mBuildFlags; - - [SerializeField] - private NMGenAssetFlag mResultOptions = NMGenAssetFlag.DetailMesh | NMGenAssetFlag.PolyMesh; - - public NMGenAssetFlag ResultOptions - { - get { return mResultOptions; } - set { mResultOptions = value; } - } - - public ContourBuildFlags ContourOptions - { - get { return mRoot.ContourOptions; } - set { mRoot.ContourOptions = value; } - } - - public bool UseMonotone - { - get { return mRoot.UseMonotone; } - set { mRoot.UseMonotone = value; } - } - - /// - /// The width/depth size of the tile on the xz-plane. - /// - public int TileSize - { - get { return mRoot.TileSize; } - set { mRoot.TileSize = value; } - } - - public float TileWorldSize - { - get { return mRoot.TileWorldSize; } - } - - /// - /// The xz-plane voxel size to use when sampling the source geometry. - /// - /// - /// Also the 'grid size' or 'voxel size'. - /// - public float XZCellSize - { - get { return mRoot.XZCellSize; } - set { mRoot.XZCellSize = value; } - } - - /// - /// The y-axis voxel size to use when sampling the source geometry. - /// [Limit: >= ] - /// - /// - /// Also the 'voxel size' for the y-axis. - /// - public float YCellSize - { - get { return mRoot.YCellSize; } - set { mRoot.YCellSize = value; } - } - - /// - /// Minimum floor to 'ceiling' height that will still allow the - /// floor area to be considered traversable. - /// - /// - /// Usually the maximum client height. - /// - public float WalkableHeight - { - get { return mWalkableHeight; } - set - { - mWalkableHeight = Mathf.Max( - NMGen.MinWalkableHeight * NMGen.MinCellSize, value); - } - } - - /// - /// Maximum ledge height that is considered to still be - /// traversable. - /// - /// - /// Usually set to how far up/down the client can step. - /// - public float WalkableStep - { - get { return mWalkableStep; } - set { mWalkableStep = Mathf.Max(0, value); } - } - - /// - /// The maximum slope that is considered walkable. - /// - public float WalkableSlope - { - get { return mRoot.WalkableSlope; } - set { mRoot.WalkableSlope = value; } - } - - /// - /// Represents the closest any part of a mesh should get to an - /// obstruction in the source geometry. - /// - /// - /// Usually the client radius. - /// - public float WalkableRadius - { - get { return mWalkableRadius; } - set { mWalkableRadius = Mathf.Max(0, value); } - } - - /// - /// The closest the mesh should come to the xz-plane AABB of the - /// source geometry. - /// - public int BorderSize - { - get { return mRoot.BorderSize; } - set { mRoot.BorderSize = value; } - } - - /// - /// The maximum allowed length of triangle edges on the border of the - /// mesh. - /// - /// - /// Extra vertices will be inserted if needed. - /// A value of zero disabled this feature. - /// - public float MaxEdgeLength - { - get { return mMaxEdgeLength; } - set { mMaxEdgeLength = Mathf.Max(0, value); } - } - - /// - /// The maximum distance the edges of the mesh should deviate from - /// the source geometry. - /// - /// - /// Applies only to the xz-plane. - /// - public float EdgeMaxDeviation - { - get { return mRoot.EdgeMaxDeviation; } - set { mRoot.EdgeMaxDeviation = value; } - } - - /// - /// Sets the sampling distance to use when matching the - /// mesh surface to the source geometry. - /// [Limits: 0 or >= 0.9] - /// - public float DetailSampleDistance - { - get { return mRoot.DetailSampleDistance; } - set { mRoot.DetailSampleDistance = value; } - } - - /// - /// The maximum distance the mesh surface should deviate from the - /// surface of the source geometry. - /// [Limit: >= 0] - /// - public float DetailMaxDeviation - { - get { return mRoot.DetailMaxDeviation; } - set { mRoot.DetailMaxDeviation = value; } - } - - /// - /// The minimum number of cells allowed to form isolated island meshes. - /// [Limit: >= 0] - /// - /// - /// Prevents the formation of meshes that are too small to be - /// of use. - /// - public float MinRegionArea - { - get { return mMinRegionArea; } - set { mMinRegionArea = Mathf.Max(0, value); } - } - - /// - /// Any regions with an cell count smaller than this value will, - /// if possible, be merged with larger regions. - /// [Limit: >= 0] - /// - public float MergeRegionArea - { - get { return mMergeRegionArea; } - set { mMergeRegionArea = Mathf.Max(0, value); } - } - - /// - /// The maximum number of vertices allowed for polygons - /// generated during the contour to polygon conversion process. - /// - public int MaxVertsPerPoly - { - get { return mRoot.MaxVertsPerPoly; } - set - { - mRoot.MaxVertsPerPoly = value; - } - } - - /// - /// Flags used to control optional build steps. - /// - public NMGenBuildFlag BuildFlags - { - get { return mBuildFlags; } - set { mBuildFlags = value; } - } - - /// - /// Constructor. - /// - public NMGenConfig() - { - Reset(); - } - - public void Reset() - { - mRoot = new NMGenParams(); - UpdateLocalsFrom(mRoot); - mBuildFlags = DefaultBuildFlags; - } - - /// - /// Sets the configuration to match the provided configuration. - /// - /// - /// - /// The parameter will be cleaned during this operation. - /// - /// - /// The configuration to match. - public void SetConfig(NMGenParams config) - { - if (config == null) - return; - - mRoot = config.Clone(); - mRoot.Clean(); - UpdateLocalsFrom(mRoot); - } - - private void UpdateLocalsFrom(NMGenParams config) - { - mMaxEdgeLength = config.WorldMaxEdgeLength; - mMergeRegionArea = config.WorldMergeRegionArea; - mMinRegionArea = config.WorldMinRegionArea; - - mWalkableHeight = config.WorldWalkableHeight; - mWalkableRadius = config.WorldWalkableRadius; - mWalkableStep = config.WorldWalkableStep; - } - - private void ApplyLocalsTo(NMGenParams config) - { - config.SetMaxEdgeLength(mMaxEdgeLength); - config.SetMergeRegionArea(mMergeRegionArea); - config.SetMinRegionArea(mMinRegionArea); - - config.SetWalkableHeight(mWalkableHeight); - config.SetWalkableRadius(mWalkableRadius); - config.SetWalkableStep(mWalkableStep); - } - - /// - /// Attempts the derive the best configuration for the provided source geometry AABB. - /// - /// The minimum bounds of the source geometry. - /// The maximum bounds of the source geometry. - public void Derive(Vector3 boundsMin, Vector3 boundsMax) - { - // Order is important. - XZCellSize = DeriveXZCellSize(this); - YCellSize = DeriveYCellSize(this); - TileSize = DeriveTileSize(this, boundsMin, boundsMax); - BorderSize = DeriveBorderSize(this); - DetailSampleDistance = - DeriveDetailSampleDistance(this, boundsMin, boundsMax); - - DetailMaxDeviation = DeriveDetailMaxDeviation(this); - } - - public static float DeriveXZCellSize(NMGenConfig config) - { - return (float)Math.Round(Mathf.Max(0.05f, config.WalkableRadius / 2), 2); - } - - public static float DeriveYCellSize(NMGenConfig config) - { - return (float)Math.Round(Mathf.Max(0.05f, config.WalkableStep / 3), 2); - } - - public static float DeriveDetailMaxDeviation(NMGenConfig config) - { - return (float)Math.Round(config.YCellSize * mDeviationFactor, 2); - } - - public static int DeriveBorderSize(NMGenConfig config) - { - if (config.TileSize > 0) - { - return (int)Mathf.Ceil( - config.WalkableRadius / config.mRoot.xzCellSize) + 3; - } - return 0; - } - - public static float DeriveDetailSampleDistance( - NMGenConfig config - , Vector3 boundsMin - , Vector3 boundsMax) - { - Vector3 diff = boundsMax - boundsMin; - - float maxXZLength = Mathf.Max(diff.x, diff.z); - - int maxCells = Mathf.CeilToInt(maxXZLength / config.XZCellSize); - - if (config.TileSize == 0 || maxCells <= MaxCells) - { - return (float)Math.Round( - Mathf.Max(0.9f, maxXZLength / mSampleResolution), 2); - } - else - return (float)Math.Round(Mathf.Max(0.9f - , config.TileSize * config.XZCellSize / mSampleResolution), 2); - } - - public static int DeriveTileSize( - NMGenConfig config - , Vector3 boundsMin - , Vector3 boundsMax) - { - Vector3 diff = boundsMax - boundsMin; - - float maxXZLength = Mathf.Max(diff.x, diff.z); - - int maxCells = Mathf.CeilToInt(maxXZLength / config.XZCellSize); - - if (maxCells <= MaxCells) - return 0; - else - return Mathf.Min(mStandardCells, maxCells / 2); - } - - /// - /// Generates a based on the the object - /// values. - /// - /// A configuration based on the object values. - public NMGenParams GetConfig() - { - NMGenParams result = mRoot.Clone(); - - ApplyLocalsTo(result); - - return result; - } - - /// - /// Duplicates the object. - /// - /// A duplicate of the object. - public NMGenConfig Clone() - { - NMGenConfig result = new NMGenConfig(); - result.mRoot = mRoot; - result.mMaxEdgeLength = mMaxEdgeLength; - result.mMergeRegionArea = mMergeRegionArea; - result.mMinRegionArea = mMinRegionArea; - result.mWalkableHeight = mWalkableHeight; - result.mWalkableRadius = mWalkableRadius; - result.mWalkableStep = mWalkableStep; - result.mBuildFlags = mBuildFlags; - return result; - } - - public void Clean() - { - mRoot.Clean(); - UpdateLocalsFrom(mRoot); - } - - public void ApplyDecimalLimits() - { - XZCellSize = (float)Math.Round(XZCellSize, 2); - YCellSize = (float)Math.Round(YCellSize, 2); - - DetailMaxDeviation = - (float)Math.Round(DetailMaxDeviation, 2); - DetailSampleDistance = - (float)Math.Round(DetailSampleDistance, 2); - EdgeMaxDeviation = - (float)Math.Round(EdgeMaxDeviation, 2); - - MaxEdgeLength = (float)Math.Round(MaxEdgeLength, 2); - MergeRegionArea = (float)Math.Round(MergeRegionArea, 2); - MinRegionArea = (float)Math.Round(MinRegionArea, 2); - WalkableHeight = (float)Math.Round(WalkableHeight, 2); - WalkableRadius = (float)Math.Round(WalkableRadius, 2); - WalkableSlope = (float)Math.Round(WalkableSlope, 2); - WalkableStep = (float)Math.Round(WalkableStep, 2); - } - } -} diff --git a/critterai/.svn/pristine/bd/bdcaf7d51d59fe2528b73e09fe809e9181582f44.svn-base b/critterai/.svn/pristine/bd/bdcaf7d51d59fe2528b73e09fe809e9181582f44.svn-base deleted file mode 100644 index 85c5353c..00000000 --- a/critterai/.svn/pristine/bd/bdcaf7d51d59fe2528b73e09fe809e9181582f44.svn-base +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; - -namespace org.critterai.interop -{ - /// - /// Provides various interop related utility methods. - /// - public static class UtilEx - { - /// - /// Copies data from an unmanaged memory pointer to a ushort array. - /// - /// - /// - /// This method behaves the same as the Marshal.Copy methods. - /// - /// - /// A memory pointer to copy from. - /// The array to copy to. - /// The length of the copy. - public static void Copy(IntPtr source, ushort[] destination, int length) - { - int byteLength = sizeof(ushort) * length; - byte[] tmp = new byte[byteLength]; - Marshal.Copy(source, tmp, 0, byteLength); - Buffer.BlockCopy(tmp, 0, destination, 0, byteLength); - } - - /// - /// Copies data from an unmanaged memory pointer to a uint array. - /// - /// - /// - /// This method behaves the same as the Marshal.Copy methods. - /// - /// - /// A memory pointer to copy from. - /// The array to copy to. - /// The length of the copy. - public static void Copy(IntPtr source, uint[] destination, int length) - { - int byteLength = sizeof(uint) * length; - byte[] tmp = new byte[byteLength]; - Marshal.Copy(source, tmp, 0, byteLength); - Buffer.BlockCopy(tmp, 0, destination, 0, byteLength); - } - - /// - /// Copies the content of a one-dimentional array to an unmanaged memory pointer. - /// - /// - /// - /// This method behaves the same as the Marshal.Copy methods. - /// - /// - /// An array to copy from. - /// The index where the copy should start. - /// The memory pointer to copy to. - /// The length of the copy. - public static void Copy(ushort[] source, int startIndex, IntPtr destination, int length) - { - int size = sizeof(ushort); - int byteLength = size * length; - int byteStart = size * startIndex; - byte[] tmp = new byte[byteLength]; - Buffer.BlockCopy(source, byteStart, tmp, 0, byteLength); - Marshal.Copy(tmp, 0, destination, byteLength); - } - - /// - /// Copies the content of a one-dimentional array to an unmanaged memory pointer. - /// - /// - /// - /// This method behaves the same as the Marshal.Copy methods. - /// - /// - /// An array to copy from. - /// The index where the copy should start. - /// The memory pointer to copy to. - /// The length of the copy. - public static void Copy(uint[] source, int startIndex, IntPtr destination, int length) - { - int size = sizeof(uint); - int byteLength = size * length; - int byteStart = size * startIndex; - byte[] tmp = new byte[byteLength]; - Buffer.BlockCopy(source, byteStart, tmp, 0, byteLength); - Marshal.Copy(tmp, 0, destination, byteLength); - } - - /// - /// Gets a pointer to an allocated umanaged memory buffer. - /// - /// The size, in bytes, of the buffer. - /// If true the the content of the buffer will be zeroed. - /// A pointer to an allocated unmanaged memory butter. - public static IntPtr GetBuffer(int size, bool zeroMemory) - { - IntPtr result = Marshal.AllocHGlobal(size); - if (zeroMemory) - ZeroMemory(result, size); - return result; - } - - /// - /// Gets a pointer to an unmanaged memory buffer filled from an array. - /// - /// The array used to build the buffer. - /// The number of elements to copy from the source. - /// A pointer to an unmanaged memory buffer filled from the source array. - public static IntPtr GetFilledBuffer(ushort[] source, int length) - { - int size = sizeof(ushort) * length; - IntPtr result = Marshal.AllocHGlobal(size); - Copy(source, 0, result, length); - return result; - } - - /// - /// Gets a pointer to an unmanaged memory buffer filled from an array. - /// - /// The array used to build the buffer. - /// The number of elements to copy from the source. - /// A pointer to an unmanaged memory buffer filled from the source array. - public static IntPtr GetFilledBuffer(uint[] source, int length) - { - int size = sizeof(uint) * length; - IntPtr result = Marshal.AllocHGlobal(size); - Copy(source, 0, result, length); - return result; - } - /// - /// Gets a pointer to an unmanaged memory buffer filled from an array. - /// - /// The array used to build the buffer. - /// The number of elements to copy from the source. - /// A pointer to an unmanaged memory buffer filled from the source array. - public static IntPtr GetFilledBuffer(float[] source, int length) - { - int size = sizeof(float) * length; - IntPtr result = Marshal.AllocHGlobal(size); - Marshal.Copy(source, 0, result, length); - return result; - } - - /// - /// Gets a pointer to an unmanaged memory buffer filled from an array. - /// - /// The array used to build the buffer. - /// The number of elements to copy from the source. - /// A pointer to an unmanaged memory buffer filled from the source array. - public static IntPtr GetFilledBuffer(int[] source, int length) - { - int size = sizeof(int) * length; - IntPtr result = Marshal.AllocHGlobal(size); - Marshal.Copy(source, 0, result, length); - return result; - } - - /// - /// Gets a pointer to an unmanaged memory buffer filled from an array. - /// - /// The array used to build the buffer. - /// The number of elements to copy from the source. - /// A pointer to an unmanaged memory buffer filled from the source array. - public static IntPtr GetFilledBuffer(byte[] source, int length) - { - IntPtr result = Marshal.AllocHGlobal(length); - Marshal.Copy(source, 0, result, length); - return result; - } - - /// - /// Returns an array filled from an unmanaged memory buffer. - /// - /// The pointer to an allocated unmanaged memory buffer. - /// The number of elements to copy into the return array. - /// A ushort array filled from the unmanaged memory buffer. - public static ushort[] ExtractArrayUShort(IntPtr source, int length) - { - ushort[] result = new ushort[length]; - Copy(source, result, length); - return result; - } - - /// - /// Returns an array filled from an unmanaged memory buffer. - /// - /// The pointer to an allocated unmanagedmemory buffer. - /// The number of elements to copy into the return array. - /// A uint array filled from the unmanaged memory buffer. - public static uint[] ExtractArrayUInt(IntPtr source, int length) - { - uint[] result = new uint[length]; - Copy(source, result, length); - return result; - } - - /// - /// Returns an array filled from an unmanaged memory buffer. - /// - /// The pointer to an allocated unmanagedmemory buffer. - /// The number of elements to copy into the return array. - /// An int array filled from the unmanaged memory buffer. - public static int[] ExtractArrayInt(IntPtr source, int length) - { - int[] result = new int[length]; - Marshal.Copy(source, result, 0, length); - return result; - } - - /// - /// Returns an array filled from an unmanaged memory buffer. - /// - /// The pointer to an allocated unmanaged memory buffer. - /// The number of elements to copy into the return array. - /// A byte array filled from the unmanaged memory buffer. - public static byte[] ExtractArrayByte(IntPtr source, int length) - { - byte[] result = new byte[length]; - Marshal.Copy(source, result, 0, length); - return result; - } - - /// - /// Returns an array filled from an unmanaged memory buffer. - /// - /// The pointer to an allocated unmanaged memory buffer. - /// The number of elements to copy into the return array. - /// A float array filled from the unmanaged memory buffer. - public static float[] ExtractArrayFloat(IntPtr source, int length) - { - float[] result = new float[length]; - Marshal.Copy(source, result, 0, length); - return result; - } - - /// - /// Zeros the memory of an allocated unmanaged memory buffer. - /// - /// A pointer to an allocated unmanaged memory buffer. - /// The number of bytes to zero. - public static void ZeroMemory(IntPtr target, int size) - { - byte[] tmp = new byte[size]; - Marshal.Copy(tmp, 0, target, size); - } - } -} diff --git a/critterai/.svn/pristine/be/beb860a09a1cbcf80ef1b3fea3c361e260cf7d90.svn-base b/critterai/.svn/pristine/be/beb860a09a1cbcf80ef1b3fea3c361e260cf7d90.svn-base deleted file mode 100644 index a9ba45d5..00000000 --- a/critterai/.svn/pristine/be/beb860a09a1cbcf80ef1b3fea3c361e260cf7d90.svn-base +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Adds vertices to a contour such that no null region edge segment exceeds - * the allowed edge length. - *

      Only null region edges are operated on.

      - *

      - * - * - *

      - *

      - * - * - *

      - */ -public final class NullRegionMaxEdge - implements IContourAlgorithm -{ - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * The maximum length allowed for line segments that are part of a null - * region edge. - */ - private final int mMaxEdgeLength; - - /** - * Constructor - * @param maxEdgeLength The maximum length of polygon edges that - * represent the border of the navmesh. - *

      More vertices will be added to navmesh border edges if this value - * is exceeded for a particular edge. In certain cases this will reduce - * the number of thin, long triangles in the navmesh.

      - *

      A value of zero will disable this feature.

      - *

      Constraints: >= 0

      - */ - public NullRegionMaxEdge(int maxEdgeLength) - { - mMaxEdgeLength = Math.max(maxEdgeLength, 0); - } - - /** - * {@inheritDoc} - *

      The resultVerts argument is expected to be seeded with at least - * one edge.

      - */ - @Override - public void apply(ArrayList sourceVerts - , ArrayList resultVerts) - { - - // See the interface documentation for details on what the argument - // lists contain. - - if (mMaxEdgeLength <= 0) - return; - - final int sourceVertCount = sourceVerts.size() / 4; - int resultVertCount = resultVerts.size() / 4; - int iVertA = 0; - - /* - * Insert verts into null-region edges that are two long. - * - * The basic process is to look at each edge in the result list. - * If it connects to the null region and exceeds the allowed length - * then insert a vertex from the source vertices list that is - * closest to the middle of the current edge, splitting it in half. - * - * Note: The number of result vertices may increase, which is why a - * while loop is being used. - */ - while (iVertA < resultVertCount) - { - - // Get vertices for the current edge. - - // Wrap if necessary. - final int iVertB = (iVertA + 1) % resultVertCount; - - final int ax = resultVerts.get(iVertA * 4); - final int az = resultVerts.get(iVertA * 4 + 2); - final int iVertASource = resultVerts.get(iVertA * 4 + 3); - - final int bx = resultVerts.get(iVertB * 4); - final int bz = resultVerts.get(iVertB * 4 + 2); - final int iVertBSource = resultVerts.get(iVertB * 4 + 3); - - int iNewVert = -1; // -1 indicates no need to add new vertex. - // Wrap if necessary. - final int iTestVert = (iVertASource + 1) % sourceVertCount; - - // Find maximum deviation from the edge. - - if (sourceVerts.get(iTestVert * 4 + 3) == NULL_REGION) - { - // This is a null-region edge. Check its length against - // the maximum allowed. - final int dx = bx - ax; - final int dz = bz - az; - if (dx * dx + dz * dz > mMaxEdgeLength * mMaxEdgeLength) - { - // The current edge is too long and needs to be split. - // Find original number of vertices between the vertA - // and vertB. - final int indexDistance = iVertBSource < iVertASource - ? (iVertBSource + (sourceVertCount - iVertASource)) - : (iVertBSource - iVertASource); - // Choose the vertex that is half way between vertA - // and vertB. Not distance wise, but step wise. - // More wrapping. - iNewVert = - (iVertASource + indexDistance/2) % sourceVertCount; - } - } - - if (iNewVert != -1) - { - // A new vertex needs to be inserted. Do it. - resultVerts.add((iVertA + 1) * 4 - , sourceVerts.get(iNewVert * 4)); - resultVerts.add((iVertA + 1) * 4 + 1 - , sourceVerts.get(iNewVert * 4 + 1)); - resultVerts.add((iVertA + 1) * 4 + 2 - , sourceVerts.get(iNewVert * 4 + 2)); - resultVerts.add((iVertA + 1) * 4 + 3 - , iNewVert); - // Update the vertex count since a new vertex was added. - resultVertCount = resultVerts.size() / 4; - // The vertex index is not being incremented because on the - // next loop we want to perform the check from iVertA to - // the newly inserted vertex. - } - else - // This edge is finished. Move to the next vertex. - iVertA++; - } - } - -} diff --git a/critterai/.svn/pristine/be/bef6e44386a7c5b4c191239acab6a150aff0acc5.svn-base b/critterai/.svn/pristine/be/bef6e44386a7c5b4c191239acab6a150aff0acc5.svn-base deleted file mode 100644 index b0e9f827..00000000 --- a/critterai/.svn/pristine/be/bef6e44386a7c5b4c191239acab6a150aff0acc5.svn-base +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Text; -using System.Globalization; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.geom -{ - /// - /// Provides limited Wavefront utility methods. (Very limited.) - /// - /// - /// - /// Only a small subset of Wavefront information is supported. - /// - /// - /// Only the "v" and "f" entries are recognized. All others are ignored. - /// - /// - /// The v entries are expected to be in one of the following forms: - /// - ///
      - /// "v x y z w"
      - /// "v x y z" - ///
      - /// - /// The f entries are expected to be in one of the following forms: - /// - /// - /// (Note that only triangles are supported. Quads are not supported.) - /// - ///
      - /// "f v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3"
      - /// "f v1 v2 v3" - ///
      - /// - /// Only the vertex portions of the entries are recognized, and only positive indices - /// supported. - /// - /// - /// Static methods are thread safe. - /// - ///
      - public static class Wavefront - { - /// - /// Creates a Wavefront format string from a triangle mesh. - /// - /// A valid triangle mesh. - /// Reverse the wrap direction of the triangles. - /// Invert the x-axis values. - /// A string representing the mesh in Wavefront format. - public static string TranslateTo(TriangleMesh mesh , bool reverseWrap , bool invertXAxis) - { - StringBuilder sb = new StringBuilder(); - - float xFactor = (invertXAxis ? -1 : 1); - - for (int i = 0; i < mesh.vertCount; i += 1) - { - sb.Append("v " - + (mesh.verts[i].x * xFactor).ToString(CultureInfo.InvariantCulture) + " " - + mesh.verts[i].y.ToString(CultureInfo.InvariantCulture) + " " - + mesh.verts[i].z.ToString(CultureInfo.InvariantCulture) + "\n"); - } - - for (int p = 0; p < mesh.triCount * 3; p += 3) - { - // The +1 converts to a 1-based index. - if (reverseWrap) - { - sb.Append("f " - + (mesh.tris[p + 0] + 1).ToString(CultureInfo.InvariantCulture) + " " - + (mesh.tris[p + 2] + 1).ToString(CultureInfo.InvariantCulture) + " " - + (mesh.tris[p + 1] + 1).ToString(CultureInfo.InvariantCulture) + "\n"); - } - else - { - sb.Append("f " - + (mesh.tris[p + 0] + 1).ToString(CultureInfo.InvariantCulture) + " " - + (mesh.tris[p + 1] + 1).ToString(CultureInfo.InvariantCulture) + " " - + (mesh.tris[p + 2] + 1).ToString(CultureInfo.InvariantCulture) + "\n"); - } - } - - return sb.ToString(); - } - - /// - /// Translates a string in Wavefront format into a triangle mesh. - /// - /// - /// Valid wavefront format text defining the vertices and indices. - /// - /// A loaded triangle mesh. - public static TriangleMesh TranslateFrom(string wavefrontText) - { - List lverts = new List(); - List lindices = new List(); - - Regex nl = new Regex(@"\n"); - Regex r = new Regex(@"\s+"); - Regex rs = new Regex(@"\/"); - - string[] lines = nl.Split(wavefrontText); - int lineCount = 0; - foreach (string line in lines) - { - lineCount++; - string s = line.Trim(); - string[] tokens = null; - if (s.StartsWith("v ")) - { - tokens = r.Split(s); - float x = float.Parse(tokens[1], CultureInfo.InvariantCulture); - float y = float.Parse(tokens[2], CultureInfo.InvariantCulture); - float z = float.Parse(tokens[3], CultureInfo.InvariantCulture); - lverts.Add(new Vector3(x, y, z)); - } - else if (s.StartsWith("f ")) - { - // This is a face entry. Expecting one of: - // F v1/vt1/vn1 v2/vt2/vn2 v3/vt3/vn3 - // F v1 v2 v3 - tokens = r.Split(s); - for (int i = 1; i < 4; i++) - { - string token = tokens[i]; - string[] subtokens = rs.Split(token); - // Subtraction converts from 1-based index to - // zero-based index. - lindices.Add(int.Parse(subtokens[0], CultureInfo.InvariantCulture) - 1); - } - } - } - - return new TriangleMesh(lverts.ToArray(), lverts.Count - , lindices.ToArray(), lindices.Count / 3); - } - } -} diff --git a/critterai/.svn/pristine/bf/bf83efd3d9118d8225d704a35b2d76387042db1f.svn-base b/critterai/.svn/pristine/bf/bf83efd3d9118d8225d704a35b2d76387042db1f.svn-base deleted file mode 100644 index 5ea43db1..00000000 --- a/critterai/.svn/pristine/bf/bf83efd3d9118d8225d704a35b2d76387042db1f.svn-base +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using org.critterai.interop; -using org.critterai.geom; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Represents a triangle mesh with area data, spatially divided into nodes for more efficient - /// querying. - /// - /// - /// - /// Objects of this type are created using the class. - /// - /// - /// Storage is optimized for use by the NMGen build process across muliple threads. - /// It is not efficient for other uses. - /// - /// - /// The content of a node can be inspected as follows: - /// - /// - /// // Where lmesh is a TriangleMesh object and lareas is a byte array obtained - /// // from ChunkyTriMesh.ExtractMesh. - /// for (int j = 0; j < node.count; j++, i++) - /// { - /// int pTri = (node.i + j) * 3; - /// - /// int iVertA = lmesh.tris[pTri + 0]; - /// int iVertB = lmesh.tris[pTri + 1]; - /// int iVertC = lmesh.tris[pTri + 2]; - /// - /// byte triArea = lareas[node.i + j]; - /// - /// Vector3 vertA = new Vector3(lmesh.verts[iVertA] - /// , lmesh.verts[iVertA] - /// , lmesh.verts[iVertA]); - /// - /// // Repeat for vertB and vertC... - /// - /// // Use the vertices... - /// } - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - public sealed class ChunkyTriMesh - { - internal IntPtr verts; - internal IntPtr tris; - internal IntPtr areas; - - private ChunkyTriMeshNode[] mNodes; - private readonly int mNodeCount; - private readonly int mTriCount; - private readonly int mVertCount; - - /// - /// The number of spacial nodes in the mesh. - /// - public int NodeCount { get { return mNodeCount; } } - - /// - /// The number of triangles in the mesh. - /// - /// - /// - /// Will always be > 0. Empty meshes cannot be created. - /// - /// - public int TriCount { get { return mTriCount; } } - - internal ChunkyTriMesh(Vector3[] verts - , int vertCount - , int[] tris - , byte[] areas - , int triCount - , ChunkyTriMeshNode[] nodes - , int nodeCount) - { - int size = sizeof(float) * vertCount * 3; - this.verts = UtilEx.GetBuffer(size, false); - float[] fverts = Vector3Util.Flatten(verts, vertCount); // Bleh. - Marshal.Copy(fverts, 0, this.verts, vertCount * 3); - - size = sizeof(int) * tris.Length; - this.tris = UtilEx.GetBuffer(size, false); - Marshal.Copy(tris, 0, this.tris, tris.Length); - - size = sizeof(byte) * areas.Length; - this.areas = UtilEx.GetBuffer(size, false); - Marshal.Copy(areas, 0, this.areas, areas.Length); - - mTriCount = triCount; - mVertCount = vertCount; - mNodes = nodes; - mNodeCount = nodeCount; - } - - /// - /// Destructor. - /// - ~ChunkyTriMesh() - { - Dispose(); - } - - /// - /// Gets all nodes overlapped by the specified bounds. - /// - /// The minimum x-bounds. - /// The minimum z-bounds. - /// The maximum x-bounds. - /// The maximum z-bounds. - /// The list to append the result to. - /// The number of result nodes appended to the result list. - public int GetChunks(float xmin, float zmin, float xmax, float zmax - , List resultNodes) - { - if (tris == IntPtr.Zero || resultNodes == null) - return 0; - - int result = 0; - int i = 0; - while (i < mNodeCount) - { - ChunkyTriMeshNode node = mNodes[i]; - - bool overlap = node.Overlaps(xmin, zmin, xmax, zmax); - - bool isLeafNode = node.i >= 0; - - if (isLeafNode && overlap) - { - resultNodes.Add(node); - result += node.count; - } - - if (overlap || isLeafNode) - i++; - else - { - int escapeIndex = -node.i; - i += escapeIndex; - } - } - - return result; - } - - /// - /// Extracts all triangles from the mesh. (Not efficient.) - /// - /// The areas for each triangle. - /// The triangle mesh data. - public TriangleMesh ExtractMesh(out byte[] areas) - { - if (this.tris == IntPtr.Zero) - { - areas = null; - return null; - } - - TriangleMesh result = new TriangleMesh(); - result.triCount = mTriCount; - result.vertCount = mVertCount; - - float[] lverts = new float[mVertCount * 3]; - Marshal.Copy(this.verts, lverts, 0, mVertCount * 3); - result.verts = Vector3Util.GetVectors(lverts); - - result.tris = new int[mTriCount * 3]; - Marshal.Copy(this.tris, result.tris, 0, mTriCount * 3); - - areas = new byte[mTriCount]; - Marshal.Copy(this.areas, areas, 0, mTriCount); - - return result; - } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return (tris == IntPtr.Zero); } } - - /// - /// Frees all resources and marks object as disposed. - /// - public void Dispose() - { - if (tris != IntPtr.Zero) - { - Marshal.FreeHGlobal(verts); - Marshal.FreeHGlobal(tris); - Marshal.FreeHGlobal(areas); - verts = IntPtr.Zero; - tris = IntPtr.Zero; - areas = IntPtr.Zero; - } - } - } -} diff --git a/critterai/.svn/pristine/bf/bf9c2fa31919c5d06feef95d7e477cd1b1af8bd4.svn-base b/critterai/.svn/pristine/bf/bf9c2fa31919c5d06feef95d7e477cd1b1af8bd4.svn-base deleted file mode 100644 index 266522d1..00000000 --- a/critterai/.svn/pristine/bf/bf9c2fa31919c5d06feef95d7e477cd1b1af8bd4.svn-base +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; -using UnityEditor; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// A generic unity build context. (Editor Only) - /// - public class UnityBuildContext - : BuildContext - { - internal const string TraceKey = "org.critterai.nmbuild.TraceMessages"; - - private static bool mTraceEnabled; - - /// - /// True if the owner of the context should periodically post trace messages. - /// - public static bool TraceEnabled - { - get { return mTraceEnabled; } - set - { - if (mTraceEnabled != value) - { - mTraceEnabled = value; - EditorPrefs.SetBool(TraceKey, mTraceEnabled); - } - } - } - - /// - /// Flushes all log messages to the console as an error. - /// - /// - /// - /// The log will be reset. - /// - /// - /// This method should only be used by the owner of the context. Other context users, - /// such as build processors, should use the method. - /// - /// - /// The error summary. - /// The Unity object context. (Optional) - internal void PostError(string summary, Object context) - { - Debug.LogError(string.Format("{0}\n{1}" - , summary - , GetMessagesFlat()) - , context); - ResetLog(); - } - - /// - /// Appends the specified messages to the log then flushes all log messages to the console - /// as an error. - /// - /// - /// - /// The log will be reset. - /// - /// - /// This method should only be used by the owner of the context. Other context users, - /// such as build processors, should use the method. - /// - /// - /// The error summary. - /// - /// Messages to append to the log before posting to the console. (Optional) - /// - /// The Unity object context. (Optional) - internal void PostError(string summary, string[] messages, Object context) - { - Log(messages); - PostError(summary, context); - } - - /// - /// Flushes all log messages to the console. - /// - /// - /// - /// The log will be reset. - /// - /// - /// This method should only be used by the owner of the context. Other context users, - /// such as build processors, should use the standard log methods. - /// - /// - /// The trace summary. - /// The Unity object context. (Optional) - internal void PostTrace(string summary, Object context) - { - if (mTraceEnabled) - { - Debug.Log(string.Format("{0}\n{1}" - , summary - , GetMessagesFlat()) - , context); - } - ResetLog(); - } - - /// - /// Appends the specified messages to the log then flushes all log messages to the console. - /// - /// - /// - /// The log will be reset. - /// - /// - /// This method should only be used by the owner of the context. Other context users, - /// such as build processors, should use the standard log methods. - /// - /// - /// The trace summary. - /// - /// Messages to append to the log before posting to the console. (Optional) - /// - /// The Unity object context. (Optional) - internal void PostTrace(string summary, string[] messages, Object context) - { - if (mTraceEnabled) - { - Log(messages); - PostTrace(summary, context); - } - } - } -} diff --git a/critterai/.svn/pristine/c0/c00d7de068615e58d951f3aa78f756a2875cd453.svn-base b/critterai/.svn/pristine/c0/c00d7de068615e58d951f3aa78f756a2875cd453.svn-base deleted file mode 100644 index 478af374..00000000 --- a/critterai/.svn/pristine/c0/c00d7de068615e58d951f3aa78f756a2875cd453.svn-base +++ /dev/null @@ -1,19 +0,0 @@ -version=snapshot -project.name=cai-nmgen -project.fullname=${project.name}-${version} - -lib.dir=../../lib/java -misc.resources.dir=../../misc - -src.dir=src - -local.misc.dir=misc -dist.scm.dir=${lib.dir} - -test.src.dir=test -test.classes.dir=${build.dir}/test - -build.dir=build -classes.dir=${build.dir}/classes -dist.dir=${build.dir}/dist -doc.dir=${build.dir}/docs \ No newline at end of file diff --git a/critterai/.svn/pristine/c0/c0765823fc4122a0e205a4515774ae934b8ab176.svn-base b/critterai/.svn/pristine/c0/c0765823fc4122a0e205a4515774ae934b8ab176.svn-base deleted file mode 100644 index 3cb69880..00000000 Binary files a/critterai/.svn/pristine/c0/c0765823fc4122a0e205a4515774ae934b8ab176.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/c0/c0886abe76d23717952dd685ad8289bd81a5a206.svn-base b/critterai/.svn/pristine/c0/c0886abe76d23717952dd685ad8289bd81a5a206.svn-base deleted file mode 100644 index 344bac57..00000000 Binary files a/critterai/.svn/pristine/c0/c0886abe76d23717952dd685ad8289bd81a5a206.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/c1/c1ba1d17d471504376e3b0ef855f2dab666751f1.svn-base b/critterai/.svn/pristine/c1/c1ba1d17d471504376e3b0ef855f2dab666751f1.svn-base deleted file mode 100644 index 8103fafe..00000000 --- a/critterai/.svn/pristine/c1/c1ba1d17d471504376e3b0ef855f2dab666751f1.svn-base +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nav; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// Represents the result of a tile build. - /// - public struct TileBuildAssets - { - private readonly int mTileX; - private readonly int mTileZ; - - private readonly NavmeshTileData mTile; - private readonly int mPolyCount; - - /// - /// Constructor - /// - /// - /// - /// A 'no result' object will be created if the parameter - /// is null or polygon count is less than one. - /// - /// - /// The x-index of the tile within the tile grid. (tx, tz) - /// The z-index of the tile within the tile grid. (tx, tz) - /// The tile data. - /// The polygons in the tile. - public TileBuildAssets(int tx, int tz, NavmeshTileData tile, int polyCount) - { - mTileX = tx; - mTileZ = tz; - - if (tile == null || polyCount < 1) - { - mTile = null; - mPolyCount = 0; - } - else - { - mTile = tile; - mPolyCount = polyCount; - } - } - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int TileX { get { return mTileX; } } - - /// - /// The z-index of the tile within the tile grid. (x, z) - /// - public int TileZ { get { return mTileZ; } } - - /// - /// The tile data. - /// - public NavmeshTileData Tile { get { return mTile; } } - - /// - /// The number of polygons in the tile. - /// - public int PolyCount { get { return mPolyCount; } } - - /// - /// There are no results for the tile. (Polygon count is zero.) - /// - public bool NoResult { get { return (mTile == null); } } - } -} diff --git a/critterai/.svn/pristine/c1/c1d633850b54b109c11e4e6ba1e47727a7ac7ab0.svn-base b/critterai/.svn/pristine/c1/c1d633850b54b109c11e4e6ba1e47727a7ac7ab0.svn-base deleted file mode 100644 index d8982f9a..00000000 Binary files a/critterai/.svn/pristine/c1/c1d633850b54b109c11e4e6ba1e47727a7ac7ab0.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/c2/c2106535cd5a64f5bc6e394a01202aea7eed7afc.svn-base b/critterai/.svn/pristine/c2/c2106535cd5a64f5bc6e394a01202aea7eed7afc.svn-base deleted file mode 100644 index fcc097d2..00000000 --- a/critterai/.svn/pristine/c2/c2106535cd5a64f5bc6e394a01202aea7eed7afc.svn-base +++ /dev/null @@ -1,2560 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.logging.Logger; - -/** - * Builds an triangle mesh from {@link OpenHeightfield } and - * {@link PolyMeshField} data. The polygon mesh field is triangulated and - * detail added as needed to match the surface of the mesh to the surface - * defined in the open heightfield. - *

      - * - * - *

      - * @see Detail Mesh Generation - * @see TriangleMesh - */ -public final class DetailMeshBuilder -{ - - /* - * Design notes: - * - * Recast Reference: rcBuildPolyMeshDetail in RecastMeshDetail.cpp - * - * Not adding configuration getters until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - */ - - /* - * TODO: EVAL: Need to review the process of loading and getting values - * from the height patch. - * - * Current design assumes that there are natural special cases that - * result in vertices improperly showing as outside of the patch. But - * it may be a design issue that needs fixing rather than true special - * cases such as floating point errors. See getHeightWithinField() for - * descriptions of the special cases currently being taken into account. - */ - - /** - * Represents height information for a portion (or patch) of a larger - * heightfield. - *

      Various fields indicate which portion of the source heightfield is - * represented.

      - *

      Unlike normal heightfields, this class cannot represent overlaps. - * Each grid location can only hold a single data point.

      - *

      Data is filled using a flood method. I.e. Start at a particular - * span in the source height field, and flood outward to the patch's - * boundaries.

      - *

      Since the value {@link #UNSET} is used to indicate the lack of - * data at a particular location, the effective maximum height value - * is {@link Integer#MAX_VALUE} - 1.

      - *

      WARNING: It is critical that public fields be set correctly. - * Otherwise operation exceptions may be thrown.

      - */ - private class HeightPatch - { - /** - * Indicates that data at a particular grid location has not been set. - * (Has no value.) After data has been loaded, this means - * that there is no valid height information for the particular grid - * location. - */ - public static final int UNSET = Integer.MAX_VALUE; - - /** - * The width index for the origin of this patch. - * (Should be a valid width index within the larger height field.) - */ - int minWidthIndex; - - /** - * The depth index for the origin of this patch. - * (Should be a valid depth index within the larger height field.) - */ - int minDepthIndex; - - /** - * The width of this patch as measured from the patch's origin. - */ - int width; - - /** - * The depth of this patch as measured from the patch's origin. - */ - int depth; - - /** - * Height data for this patch. - *

      Should normally use the {@link #setData(int, int, int) setData} - * and {@link #getData(int, int) getData} operations to access data - * in this array.

      - *

      Storage: [(Depth Data) (Depth Data) ... (Depth Data)] - * So the location of a particular data point is - * widthIndex * {@link #depth} + depthIndex

      - *

      Array should be sized such that it can hold at least - * {@link #width} x {@link #depth} worth of data.

      - */ - int[] data; - - /** - * Gets the height data for the patch location. - *

      The indices are auto-clamped.

      - * @param globalWidthIndex The width index of the grid location - * from the source height field. - * @param globalDepthIndex The depth index of the grid location - * from the source height field. - * @return The data stored a the grid location. - */ - public int getData(int globalWidthIndex, int globalDepthIndex) - { - // Do not remove auto-clamping. It is an important feature. - // See special case comments in getHeightWithinField() for - // details on why. - int idx = Math.min(Math.max( - globalWidthIndex - minWidthIndex, 0) - , width - 1) * depth - + Math.min(Math.max( - globalDepthIndex - minDepthIndex, 0) - , depth - 1); - return data[idx]; - } - - /** - * Indicates whether or not a global index (width, height) is - * within the bounds of the patch. - * @param globalWidthIndex The width index from the patch's - * source heightfield. - * @param globalDepthIndex The depth index from the patch's - * source heightfield. - * @return If the global index (width, height) is within the - * bounds of the patch. - */ - public boolean isInPatch(int globalWidthIndex, int globalDepthIndex) - { - return (globalWidthIndex >= minWidthIndex - && globalDepthIndex >= minDepthIndex - && globalWidthIndex < minWidthIndex + width - && globalDepthIndex < minDepthIndex + depth); - } - - /** - * Sets all values in the data array to {@link #UNSET}. - */ - public void resetData() - { - if (data == null) - return; - for (int i = 0; i < data.length; i++) - data[i] = UNSET; - } - - /** - * Sets the height data for the patch location. - *

      WARNING: No argument validation is performed. Calling code - * should perform all needed validations prior to calling this - * operation.

      - * @param globalWidthIndex The width index of the grid location - * from the source height field. - * @param globalDepthIndex The depth index of the grid location - * from the source height field. - * @param value The data to store at the grid location. - */ - public void setData(int globalWidthIndex - , int globalDepthIndex - , int value) - { - data[(globalWidthIndex - minWidthIndex)*depth - +globalDepthIndex-minDepthIndex] = value; - } - - } - - private static final Logger logger = - Logger.getLogger(DetailMeshBuilder.class.getName()); - - /** - * Information is undefined. (Not yet set.) - */ - private static final int UNDEFINED = -1; - - /** - * This side of the edge is external to the main polygon. (It is part - * of the polygon's hull.) - *

      Edges internal to the polygon (i.e. those created during - * triangulation) should never have this value.

      - */ - private static final int HULL = -2; - - /** - * The maximum number of vertices allowed for a triangulated polygon mesh. - *

      This value is arbitrary.

      - */ - private static final int MAX_VERTS = 256; - - /** - * The maximum number of edges that a single edge can be broken into - * during edge sampling. - *

      This value is arbitrary.

      - */ - private static final int MAX_EDGES = 64; - - /** - * Contour matching sample resolution. - *

      Impacts how well the final mesh conforms to surface data in the - * {@link OpenHeightfield} Higher values, closer conforming, higher - * final triangle count.

      - */ - private final float mContourSampleDistance; - - /** - * Contour matching maximum deviation. - *

      Impacts how well the final mesh conforms to the original meshes - * surface contour. Lower values, closer conforming, higher final - * triangle count.

      - */ - private final float mContourMaxDeviation; - - /** - * - * @param contourSampleDistance Sets the sampling distance to use when - * matching the final mesh to the surface defined by the - * {@link OpenHeightfield}. - *

      Impacts how well the final mesh conforms to surface data in the - * {@link OpenHeightfield} Higher values, closer conforming, higher - * final triangle count.

      - *

      Setting this argument to zero will disable this functionality.

      - *

      Constraints: >= 0

      - * - * @param contourMaxDeviation The maximum distance the surface of the - * navmesh may deviate from the surface data in the {@link OpenHeightfield}. - *

      The accuracy of the algorithm which uses this value is impacted by - * the value of the contour sample distance argument.

      - *

      The value of this argument has no meaning if the contour sample - * distance argument is set to zero.

      - *

      Setting the value to zero is not recommended since it can result - * in a large increase in the number of triangles in the final navmesh - * at a high processing cost.

      - *

      Constraints: >= 0

      - */ - public DetailMeshBuilder(float contourSampleDistance - , float contourMaxDeviation) - { - mContourSampleDistance = Math.max(0, contourSampleDistance); - mContourMaxDeviation = Math.max(0, contourMaxDeviation); - } - - /** - * Build a triangle mesh with detailed height information from the - * provided polygon mesh. - *

      Concerning sampling: Sampling functionality will only work - * correctly if the y-values in the source mesh are accurate to within - * {@link OpenHeightfield#cellHeight()} of an associated span within the - * provided height field. Otherwise the algorithms used by - * this operation may not be able to find accurate height information - * from the {@link OpenHeightfield}. - * @param sourceMesh The source polygon mesh to build the triangle - * mesh from. - * @param heightField The heightfield from which the {@link PolyMeshField} - * was derived. - * @return The generated triangle mesh. Or null if there were errors - * which prevented triangulation. - */ - public TriangleMesh build(PolyMeshField sourceMesh - , OpenHeightfield heightField) - { - if (sourceMesh == null - || sourceMesh.vertCount() == 0 - || sourceMesh.polyCount() == 0) - return null; - - // Create result object. - final TriangleMesh mesh = new TriangleMesh(); - - // Saves on divisions within loops. - final int sourcePolyCount = sourceMesh.polyCount(); - - // Convenience variables. - final float cellSize = sourceMesh.cellSize(); - final float cellHeight = sourceMesh.cellHeight(); - final float[] minBounds = sourceMesh.boundsMin(); - final int maxVertsPerPoly = sourceMesh.maxVertsPerPoly(); - final int[] sourceVerts = sourceMesh.verts; - final int[] sourcePolys = sourceMesh.polys; - - /* - * Contains the xz-plane bounds of each polygon. - * Entry format: (xmin, xmax, zmin, zmax) - * Uses the same index as sourcePolys. - */ - final int[] polyXZBounds = new int[sourcePolyCount * 4]; - - // The total number of polygon vertices. - // Needs to be calculated since the vertex count of the source - // polygons vary. - int totalPolyVertCount = 0; - - // The maximum width and depth found for the source polygons. - int maxPolyWidth = 0; - int maxPolyDepth = 0; - - /* - * Gather data. - * Loop through each polygon and find its xz bounds, the number of - * vertices, and the overall maximum polygon width and depth. - */ - for (int iPoly = 0; iPoly < sourcePolyCount; iPoly++) - { - final int pPoly = iPoly * maxVertsPerPoly * 2; - // These next variables are pointers to this poly's bound fields - // in polyXZBounds. - final int pxmin = iPoly*4; - final int pxmax = iPoly*4+1; - final int pzmin = iPoly*4+2; - final int pzmax = iPoly*4+3; - // Initialize the bounds fields to their extremes. - polyXZBounds[pxmin] = heightField.width(); - polyXZBounds[pxmax] = 0; - polyXZBounds[pzmin] = heightField.depth(); - polyXZBounds[pzmax] = 0; - // Loop through each vertex in the polygon, searching for - // minimum/maximum vertex values. - for (int vertOffset = 0; vertOffset < maxVertsPerPoly; vertOffset++) - { - if(sourcePolys[pPoly+vertOffset] == PolyMeshField.NULL_INDEX) - // Reached the end of this polygon's vertices. - break; - final int pVert = sourcePolys[pPoly+vertOffset]*3; - // Adjust the values of the bounds if this vertex - // represents a new min/max. - polyXZBounds[pxmin] = Math.min(polyXZBounds[pxmin] - , sourceVerts[pVert]); - polyXZBounds[pxmax] = Math.max(polyXZBounds[pxmax] - , sourceVerts[pVert]); - polyXZBounds[pzmin] = Math.min(polyXZBounds[pzmin] - , sourceVerts[pVert+2]); - polyXZBounds[pzmax] = Math.max(polyXZBounds[pzmax] - , sourceVerts[pVert+2]); - // Increment the total vertex count. - totalPolyVertCount++; - } - /* - * Clamp the values to one less than the minimum and one more - * than the maximum while staying within the valid field bounds. - * This ensures that when a height patch is created later, it is - * guaranteed to encompass the entire polygon. - */ - polyXZBounds[pxmin] = Math.max(0,polyXZBounds[pxmin] - 1); - polyXZBounds[pxmax] = Math.min(heightField.width() - ,polyXZBounds[pxmax] + 1); - polyXZBounds[pzmin] = Math.max(0,polyXZBounds[pzmin] - 1); - polyXZBounds[pzmax] = Math.min(heightField.depth() - ,polyXZBounds[pzmax] + 1); - if (polyXZBounds[pxmin] >= polyXZBounds[pxmax] - || polyXZBounds[pzmin] >= polyXZBounds[pzmax]) - // NO chance of this polygon being the max width/depth polygon. - continue; - // Record whether this polygon has the largest width of depth - // found so far. - maxPolyWidth = Math.max(maxPolyWidth - , polyXZBounds[pxmax] - polyXZBounds[pxmin]); - maxPolyDepth = Math.max(maxPolyDepth - , polyXZBounds[pzmax] - polyXZBounds[pzmin]); - } - - // Holds the vertices of the current polygon to be triangulated. - final float[] poly = new float[maxVertsPerPoly*3]; - int polyVertCount = 0; - - /* - * Holds the triangle indices generated for the current polygon. - * Form: (vertAIndex, vertBIndex, vertCIndex) - * Initialized to allow for an increase in vertices during sampling. - */ - ArrayList polyTriangles - = new ArrayList(maxVertsPerPoly * 2 * 3); - - /* - * Hold the vertex information for the triangles. - * If sampling occurs, there will be more vertices in this array - * than in the polygon array. Otherwise the content will be the same. - */ - final float[] polyTriangleVerts = new float[MAX_VERTS*3]; - int polyTriangleVertCount = 0; - - final HeightPatch hfPatch = new HeightPatch(); - if (mContourSampleDistance > 0) - /* - * The height patch is only used in the polygon detail - * operation if the sample distance is > 0. - * Set the bounds of the patch to be searched. - * Sized to hold the largest possible polygon. - */ - hfPatch.data = new int[maxPolyWidth * maxPolyDepth]; - - /* - * Values within working variables are irrelevant outside the - * operations in which they are used. Their only purpose is to - * save on object creation cost during loop iterations. - * Most initialization sizes are arbitrary. - */ - final ArrayDeque workingStack = - new ArrayDeque(256); - final ArrayDeque workingSpanStack = - new ArrayDeque(128); - final ArrayList workingEdges = - new ArrayList(MAX_EDGES * 4); - final ArrayList workingSamples = new ArrayList(512); - - /* - * A working array used while building the height path. - * Its data is not used within this operation. - */ - final int[] workingWidthDepth = new int[2]; - - /* - * Holds the aggregate vertices for the entire mesh. - * Form: (x, y, z) - */ - final ArrayList globalVerts = - new ArrayList(totalPolyVertCount * 2 * 3); - - /* - * Holds the aggregate triangles for the entire mesh. - * Format (vertAIndex, vertBIndex, vertCIndex, regionID) - * where vertices are wrapped clockwise and regionID is the region - * id of the source polygon the triangles were generated from. - */ - final ArrayList globalTriangles = - new ArrayList(totalPolyVertCount * 2 * 4); - - // Triangluate all polygons. - for (int iPoly = 0; iPoly < sourcePolyCount; iPoly++) - { - final int pPoly = iPoly*maxVertsPerPoly*2; - - // Loop through all vertices in the current polygon and - // load the working polygon array. - polyVertCount = 0; - for (int vertOffset = 0; vertOffset < maxVertsPerPoly; vertOffset++) - { - if(sourcePolys[pPoly+vertOffset] == PolyMeshField.NULL_INDEX) - // Reached the end of the polygon's verts. - break; - - final int pVert = sourcePolys[pPoly+vertOffset]*3; - - // Load the vertex information for the current polygon - // into the working poly array. - poly[vertOffset*3+0] = sourceVerts[pVert] * cellSize; - poly[vertOffset*3+1] = sourceVerts[pVert+1] * cellHeight; - poly[vertOffset*3+2] = sourceVerts[pVert+2] * cellSize; - - polyVertCount++; - - } - - if (mContourSampleDistance > 0) - { - // The height patch is only used if the sample - // distance is > 0. - - // Load height patch data for this polygon. - - // Set the bounds to the min/max for current polygon. - hfPatch.minWidthIndex = polyXZBounds[iPoly*4]; - hfPatch.minDepthIndex = polyXZBounds[iPoly*4+2]; - hfPatch.width = - polyXZBounds[iPoly*4+1] - polyXZBounds[iPoly*4+0]; - hfPatch.depth = - polyXZBounds[iPoly*4+3] - polyXZBounds[iPoly*4+2]; - - // Load the height data. - loadHeightPatch(pPoly - , polyVertCount - , sourcePolys - , sourceVerts - , heightField - , hfPatch - , workingStack - , workingSpanStack - , workingWidthDepth); - } - - // Triangulate this polygon. - polyTriangleVertCount = buildPolyDetail(poly - , polyVertCount - , heightField - , hfPatch - , polyTriangleVerts - , polyTriangles - , workingEdges - , workingSamples); - - if (polyTriangleVertCount < 3) - { - logger.severe("Generation of detail polygon failed:" - + " Polygon lost. Region: " - + sourceMesh.getPolyRegion(iPoly) - + ", Polygon index: " + iPoly); - continue; - } - - // Make sure the global lists are able to handle the new data. - globalVerts.ensureCapacity( - globalVerts.size() + polyTriangleVertCount * 3); - globalTriangles.ensureCapacity( - globalTriangles.size() + polyTriangles.size() * 4 / 3); - - // Represents the next available vertex index. - final int indexOffset = globalVerts.size() / 3; - - // Add all new vertices to the global vertices list. - for (int iVert = 0; iVert < polyTriangleVertCount; iVert++) - { - // Note: Converting from height field to world coordinates. - globalVerts.add(polyTriangleVerts[iVert*3] + minBounds[0]); - globalVerts.add(polyTriangleVerts[iVert*3+1] + minBounds[1]); - globalVerts.add(polyTriangleVerts[iVert*3+2] + minBounds[2]); - } - - // Add all new triangles to the global triangles list. - for (int pTriangle = 0 - ; pTriangle < polyTriangles.size() - ; pTriangle += 3) - { - // Offset the original vertex index to match the index in - // the global vertex list. - globalTriangles.add( - polyTriangles.get(pTriangle) + indexOffset); - globalTriangles.add( - polyTriangles.get(pTriangle+1) + indexOffset); - globalTriangles.add( - polyTriangles.get(pTriangle+2) + indexOffset); - // Record the region. - globalTriangles.add(sourceMesh.getPolyRegion(iPoly)); - } - } - - // Transfer the final results to the mesh object. - - // Load mesh object with vertex data. - mesh.vertices = new float[globalVerts.size()]; - for (int i = 0; i < globalVerts.size(); i++) - mesh.vertices[i] = globalVerts.get(i); - - // Load mesh object with the triangle indices and region information. - mesh.indices = new int[globalTriangles.size() * 3 / 4]; - final int tcount = globalTriangles.size() / 4; - mesh.triangleRegions = new int[tcount]; - for (int i = 0; i < tcount; i++) - { - // The index and region information is split and set to two - // different locations in the mesh object. - final int sourcePointer = i*4; - final int destinationPointer = i*3; - mesh.indices[destinationPointer] = - globalTriangles.get(sourcePointer); - mesh.indices[destinationPointer+1] = - globalTriangles.get(sourcePointer+1); - mesh.indices[destinationPointer+2] = - globalTriangles.get(sourcePointer+2); - mesh.triangleRegions[i] = globalTriangles.get(sourcePointer+3); - } - - return mesh; - - } - - /** - * Performs sampling and triangulation of the polygon. - *

      Sampling increases the detail of the polygon so that the height of - * the final triangle mesh better follows the height of its section of - * the heightfield.

      - *

      If the sample distance is > 0, sampling will occur. Otherwise - * sampling will not occur and the number of vertices in the final mesh - * will equal the number of vertices in the source polygon.

      - * @param sourcePoly Represents a list of vertices in the format - * (x, y, z) that represent a clockwise wrapped convex polygon. - * @param sourceVertCount The number of vertices in the source polygon. - * @param heightField The height field from which the polygon was derived. - * @param patch The loaded height patch to use for sample vertex - * height data. - *

      This parameter can be null if the the sample distance is <= 0.

      - * @param outVerts The vertices for the triangle mesh generated from - * the polygon. - *

      The array must be sized to be able to fit the maximum number of - * vertices that can be generated.

      - *

      The output may contain trash information. Only vertex locations - * which have an associated index in the output triangles list represent - * real vertices. - * @param outTriangles The indices of the triangle mesh generated from - * the polygon. Its content is cleared before use. - * @param workingEdges A working list used by this operation. Its - * content is undefined outside of this operation. Its content is - * cleared prior to use. - * @param workingSamples A working list used by this operation. Its - * content is undefined outside of this operation. Its content is - * cleared prior to use. - * @return The number of vertices in the outVerts array. - *

      For successful completion: Will equal the source vertex - * count if not new vertices were added. Otherwise be greater - * than the source vertex count by the number of vertices added.

      - *

      For a failure: The value will be zero. The polygon should be - * discarded.

      - */ - private int buildPolyDetail(float[] sourcePoly - , int sourceVertCount - , OpenHeightfield heightField - , HeightPatch patch - , float[] outVerts - , ArrayList outTriangles - , ArrayList workingEdges - , ArrayList workingSamples) - { - - // There is no early exit for a source vertex count of 3 - // (a triangle) since sampling may increase the vertex count. - - // TODO: EVAL: There is a lot of array object creation going on here. - // Investigate optimization. - - // TODO: EVAL: Should the height field reference be removed in favor - // of integer parameters for cell size and such? Parameter count is - // getting a bit unruly. Then again, this is a private operation. - - // Holds potential vertices for an edge that may be broken up into - // smaller edges. - final float[] workingVerts = new float[(MAX_EDGES+1)*3]; - - // Holds the indices to the actual smoothed edge definition. - // The indices reference vertices in the working vertices array. - final int[] workingIndices = new int[MAX_EDGES]; - int workingIndicesCount = 0; - - /* Contains indices of vertices that represent the hull of the - * polygon which the triangulation cannot alter. The content can be - * considered as "seed" edges for the triangulation and is not - * used unless the sample distance is > zero. - * Points to vertices in the output vertex array. - */ - final int[] hullIndices = new int[MAX_VERTS]; - int hullIndicesCount = 0; - - // Convenience variable and a variable to reduce number of divisions. - final float cellSize = heightField.cellSize(); - final float inverseCellSize = 1.0f/heightField.cellSize(); - - // Seed the output vertices array with the source vertices. - System.arraycopy(sourcePoly, 0, outVerts, 0, sourceVertCount*3); - - // The number of vertices in the final detail polygon. Will equal - // the source vertex count if no new vertices are added. This is - // the return value. - int outVertCount = sourceVertCount; - - // Any value sample vertex height value equal to or greater than - // this value means a height could not be found in the patch. - final float heightPathLimit = - HeightPatch.UNSET * heightField.cellHeight(); - - if (mContourSampleDistance > 0) - { - - /* - * Create the mandatory hull edges. - * - * The purpose of this algorithm is to better match the height - * of the polygon edges to the height of the source field. - * Vertices are added to edges so that the polygon's edges - * better fit the contour of the height field. - * - * This is the first of two sampling passes. In this pass only - * the edges are sampled. In the second pass, the inside of the - * polygon is sampled. - * - * See: http://www.critterai.org/nmgen_detailgen#edgedetail - */ - - // Loop through all source polygon edges. - for (int iSourceVertB = 0, iSourceVertA = sourceVertCount - 1 - ; iSourceVertB < sourceVertCount - ; iSourceVertA = iSourceVertB++) - { - int pSourceVertA = iSourceVertA*3; - int pSourceVertB = iSourceVertB*3; - boolean swapped = false; - /* - * Next section applies a consistent sort to the vertices so - * that segments are always processed in the same order. - * - * I.e. If VertexA and VertexB represent an edge shared - * between two polygons, then when this operation is called - * for each polygon, the edge vertices are processed in the - * same order no matter the order they are defined within - * each polygon. - * - * This prevents seams from forming between polygons due to - * floating point errors. - */ - if (Math.abs(sourcePoly[pSourceVertA] - - sourcePoly[pSourceVertB]) < Float.MIN_VALUE) - { - if (sourcePoly[pSourceVertA+2] > sourcePoly[pSourceVertB+2]) - { - pSourceVertA = iSourceVertB*3; - pSourceVertB = iSourceVertA*3; - swapped = true; - } - } - else if (sourcePoly[pSourceVertA] > sourcePoly[pSourceVertB]) - { - pSourceVertA = iSourceVertB*3; - pSourceVertB = iSourceVertA*3; - swapped = true; - } - - // Note: The ordering of the subtraction in these deltas - // is important. Later code depends on this ordering. - final float deltaX = - sourcePoly[pSourceVertB] - sourcePoly[pSourceVertA]; - final float deltaZ = - sourcePoly[pSourceVertB+2] - sourcePoly[pSourceVertA+2]; - final float edgeXZLength = - (float)Math.sqrt(deltaX * deltaX + deltaZ * deltaZ); - - // Get the maximum edge index. (This is purposely not an - // edge count.) This value is based on how many edge's this - // edge is allowed to be broken into. - int iMaxEdge = - 1 + (int)Math.floor(edgeXZLength/mContourSampleDistance); - // Clamp to max allowed edges. - iMaxEdge = Math.min(iMaxEdge, MAX_EDGES); - if (iMaxEdge + outVertCount >= MAX_VERTS) - // The addition of these new edges would result in - // too many vertices in the polygon. Adjust edge count - // so we don't exceed maximum allowed verts. - iMaxEdge = MAX_VERTS - 1 - outVertCount; - - /* - * Split the source edge into equally sized segments based - * on the maximum number of new edges allowed. - * - * The edge is being build from vertex A toward vertex B. - */ - for (int iEdgeVert = 0; iEdgeVert <= iMaxEdge; iEdgeVert++) - { - // This section of code depends on the delta's being A->B. - final float percentOffset = (float)iEdgeVert/iMaxEdge; - final int pEdge = iEdgeVert * 3; - workingVerts[pEdge] = - sourcePoly[pSourceVertA] + (deltaX * percentOffset); - workingVerts[pEdge+2] = - sourcePoly[pSourceVertA+2] + (deltaZ * percentOffset); - // Snap the y-value to a valid height in the height field. - workingVerts[pEdge+1] - = getHeightWithinField(workingVerts[pEdge] - , workingVerts[pEdge+2] - , cellSize - , inverseCellSize, patch) - * heightField.cellHeight(); - } - - /* - * The edges array now has a list of vertices that would - * represent the new edges if the source edge was to be - * broken up into the maximum number of edges allowed. - */ - - // Seed with the first and last vertices. - // The source edge's vertex A. - workingIndices[0] = 0; - // The sample vertex just before vertex B. - workingIndices[1] = iMaxEdge; - workingIndicesCount = 2; - - /* - * This loop incrementally inserts vertices into the - * working indices array when one is found to exceed the - * maximum allowed distance from the edge. Since the - * initialization of the working vertices array ensures - * that x and z-values will not deviate from the edge, this - * process only acts based on the y-value. - * - * Note that the increment for this loop happens internal - * to the loop. - */ - for (int iWorkingIndex = 0 - ; iWorkingIndex < workingIndicesCount - 1 - ; ) - { - // Define the end points of the current working segment. - final int iWorkingVertA = workingIndices[iWorkingIndex]; - final int iWorkingVertB = workingIndices[iWorkingIndex+1]; - final int pWorkingVertA = iWorkingVertA*3; - final int pWorkingVertB = iWorkingVertB*3; - // Search the vertices that are between these end points. - // Find the vertex that is farthest from the segment. - // (Has the maximum deviation from the segment.) - float maxDistanceSq = 0; - int iMaxDistanceVert = -1; - for (int iTestVert = iWorkingVertA + 1 - ; iTestVert < iWorkingVertB - ; iTestVert++) - { - if (workingVerts[iTestVert*3+1] >= heightPathLimit) - { - /* - * This vertex cannot be used. - * - * Special case: No valid height could be derived - * for the point. This is not necessarily an error, - * though it does indicate a potential problem - * with the configuration used for generation - * of the navigation mesh. - * - * Several potential causes: - * - The line segment crosses through a true null - * region (a region with no spans). E.g. - * polygon mesh doesn't have enough detail - * at null region border. - * - Error in input data. - * - Error in height patch build process. - */ - logger.warning("Potential loss of polygon height" - + "detail on polygon edge: Could not" - + "determine height for sample vertex at (" - + workingVerts[iTestVert*3+0] + ", " - + workingVerts[iTestVert*3+2] + ")." - + " Heightpatch data not availalable."); - continue; - } - float distanceSq = Geometry.getPointSegmentDistanceSq( - workingVerts[iTestVert*3] - , workingVerts[iTestVert*3+1] - , workingVerts[iTestVert*3+2] - , workingVerts[pWorkingVertA] - , workingVerts[pWorkingVertA+1] - , workingVerts[pWorkingVertA+2] - , workingVerts[pWorkingVertB] - , workingVerts[pWorkingVertB+1] - , workingVerts[pWorkingVertB+2]); - if (distanceSq > maxDistanceSq) - { - // Found a new maximum. - maxDistanceSq = distanceSq; - iMaxDistanceVert = iTestVert; - } - } - if (iMaxDistanceVert != -1 - && maxDistanceSq - > mContourMaxDeviation * mContourMaxDeviation) - { - // A vertex was found which exceeded the maximum - // allowed deviation from the current segment. - // Insert the vertex. - for (int i = workingIndicesCount - ; i > iWorkingIndex - ; i--) - workingIndices[i] = workingIndices[i-1]; - workingIndices[iWorkingIndex+1] = iMaxDistanceVert; - workingIndicesCount++; - } - else - iWorkingIndex++; - } - - // The working indices array now contains a list of vertex - // indices for an edge smoothed based on height. - - /* - * Add new vertices to the polygon. - * Build the hull. - * - * Notes: - * - * Remember that the output vertices array has already been - * seeded with the source indices in the same order as the - * source indices array. So the indices match between - * the source and output arrays for all original vertices. - * - * The new vertices are not added to the output vertex array - * in any particular order. That is why the hull array is - * required to determine proper ordering for the polygon. - */ - - // First add the start vertex for this new group of edges. - hullIndices[hullIndicesCount++] = iSourceVertA; - if (swapped) - { - // The original vertices for this edge had to be - // reversed for the previous calculations. So they need - // to be added to the hull array in reverse order. - for (int iWorkingIndex = workingIndicesCount - 2 - ; iWorkingIndex > 0 - ; iWorkingIndex--) - { - outVerts[outVertCount*3] = - workingVerts[workingIndices[iWorkingIndex]*3]; - outVerts[outVertCount*3+1] = - workingVerts[workingIndices[iWorkingIndex]*3+1]; - outVerts[outVertCount*3+2] = - workingVerts[workingIndices[iWorkingIndex]*3+2]; - hullIndices[hullIndicesCount++] = outVertCount; - outVertCount++; - } - } - else - { - for (int iWorkingIndex = 1 - ; iWorkingIndex < workingIndicesCount-1 - ; iWorkingIndex++) - { - outVerts[outVertCount*3] = - workingVerts[workingIndices[iWorkingIndex]*3]; - outVerts[outVertCount*3+1] = - workingVerts[workingIndices[iWorkingIndex]*3+1]; - outVerts[outVertCount*3+2] = - workingVerts[workingIndices[iWorkingIndex]*3+2]; - hullIndices[hullIndicesCount++] = outVertCount; - outVertCount++; - } - } - } - } - else - { - // There will be no adjustment to the edges of the polygon. - // Just use the order of the output vertices array since it - // contains a duplicate of the source polygon. - for (int i = 0; i < outVertCount ; i++) - hullIndices[i] = i; - hullIndicesCount = outVertCount; - } - - if (outVertCount > 3) - { - /* - * Perform the triangulation. - * Note: The only output expected is outTriangles. - * The rest of the variables with the prefix "out" are only inputs - * to this operation. - */ - performDelaunayTriangulation(outVerts - , outVertCount - , hullIndices - , hullIndicesCount - , workingEdges, outTriangles); - } - else if (outVertCount == 3) - { - // The output vertices form a triangle. - // Just copy it over. - outTriangles.clear(); - outTriangles.add(0); - outTriangles.add(1); - outTriangles.add(2); - } - else - { - // Invalid output polygon due to bad input data. - // Logging is handled by the caller. - outTriangles.clear(); - return 0; - } - - // Check validity of indices. - int badIndicesCount = - getInvalidIndicesCount(outTriangles, outVertCount); - if (badIndicesCount > 0) - { - logger.severe("Delaunay triangulation failure: Invalid indices" - + " detected edge detail step. Bad indices" - + " detected: " + badIndicesCount); - outTriangles.clear(); - return 0; - } - - if (mContourSampleDistance > 0) - { - - /* - * The purpose of this second pass is to sample the inside of - * the polygon and add internal triangles where the height field - * deviates too far from the mesh. - * - * This process has to be performed after the initial - * triangulation in order to get accurate mesh distance values. - */ - - // TODO: EVAL: Can time be saved by using the patch bounds instead - // of running these bounds calculations? - - // Get the bounds of the polygon in polygon space. - float minX = sourcePoly[0]; - float minZ = sourcePoly[2]; - float maxX = minX; - float maxZ = minZ; - for (int iVert = 1; iVert < sourceVertCount; iVert++) - { - int pVert = iVert*3; - minX = Math.min(minX, sourcePoly[pVert]); - minZ = Math.min(minZ, sourcePoly[pVert+2]); - maxX = Math.max(maxX, sourcePoly[pVert]); - maxZ = Math.max(maxZ, sourcePoly[pVert+2]); - } - - /* - * Build the sample grid. - * The next looping process builds a grid of points (x, y, z). - * The x and z-values are snapped to a grid that encompasses - * the entire source polygon and is incremented by the sample - * distance. - * The y-value is snapped to the closest height found in the - * height patch at the grid's (x, z) location. - */ - - // Convert the polygon bounds to sample grid space bounds. - final int x0 = (int)Math.floor(minX/mContourSampleDistance); - final int z0 = (int)Math.floor(minZ/mContourSampleDistance); - final int x1 = (int)Math.ceil(maxX/mContourSampleDistance); - final int z1 = (int)Math.ceil(maxZ/mContourSampleDistance); - - workingSamples.clear(); - - // Loop through all locations within the sample grid space - // and create a vertex for each location that is inside the - // source polygon. - for (int z = z0; z < z1; z++) - { - for (int x = x0; x < x1; x++) - { - // Need to figure out whether this grid location is - // outside or very close to the edge of the actual polygon. - // Converts back to polygon space. - final float vx = x * mContourSampleDistance; - // Converts back to polygon space. - final float vz = z * mContourSampleDistance; - - if (getSignedDistanceToPolygonSq(vx - , vz, sourcePoly - , sourceVertCount) - > -mContourSampleDistance/2) - // This location is either outside the polygon or - // very close to the the internal edge. Skip it. - continue; - - // Add the sample vertex to the grid. - workingSamples.add(x); - workingSamples.add(getHeightWithinField(vx - , vz - , cellSize - , inverseCellSize - , patch)); - workingSamples.add(z); - } - } - - final int sampleCount = workingSamples.size() / 3; - - // The only purpose of this outer loop is to provide a certain - // number of iterations. The inner loop does not depend in any way - // on the iteration count of the outer loop. - for (int iterationCount = 0 - ; iterationCount < sampleCount - ; iterationCount++) - { - - float selectedX = 0; - float selectedY = 0; - float selectedZ = 0; - float maxDistance = 0; - - // Loop through all sample vertices. - for (int iSampleVert = 0 - ; iSampleVert < sampleCount - ; iSampleVert++) - { - /* - * Design note: - * - * There is a potential that the y-value for a sample - * vertex will be > Integer.MAX_VALUE because a height - * value for the vertex could not be found in the height - * patch. - * - * Unlike for the edge vertices earlier, there is no known - * valid reason for this to occur, so it is not being - * checked and handled here. - * - * If it does occur, the symptom will be the insertion of - * a vertex with a very high y-value that will disrupt - * the mesh at its location. - */ - // Get the position of the sample in polygon space and - // its distance from the current mesh. - final float sampleX = - workingSamples.get(iSampleVert*3) - * mContourSampleDistance; - final float sampleY = - workingSamples.get(iSampleVert*3+1) - * heightField.cellHeight(); - final float sampleZ = - workingSamples.get(iSampleVert*3+2) - * mContourSampleDistance; - final float sampleDistance = getInternalDistanceToMesh( - sampleX - , sampleY - , sampleZ - , outVerts - , outTriangles); - - if (sampleDistance == UNDEFINED) - // This sample vertex is outside of the triangle mesh. - continue; - - if (sampleDistance > maxDistance) - { - // This sample vertex is farther from the mesh than - // any other found so far. - maxDistance = sampleDistance; - selectedX = sampleX; - selectedY = sampleY; - selectedZ = sampleZ; - } - } - - if (maxDistance <= mContourMaxDeviation) - // No sample vertex was found to be too far from the mesh. - // Can stop iterating early. - break; - - // Add this vertex to the output vertices. - // Note that since this is an internal vertex it is not part of - // a mandatory edge. (Not part of the hull.) - outVerts[outVertCount*3] = selectedX; - outVerts[outVertCount*3+1] = selectedY; - outVerts[outVertCount*3+2] = selectedZ; - outVertCount++; - - // Re-perform the triangulation with the new vertex. - // TODO: EVAL: A good candidate for optimizing. - // E.g. Insert rather than full rebuild. - performDelaunayTriangulation(outVerts - , outVertCount - , hullIndices - , hullIndicesCount - , workingEdges - , outTriangles); - - // Check validity of indices. - badIndicesCount = - getInvalidIndicesCount(outTriangles, outVertCount); - if (badIndicesCount > 0) - { - logger.severe("Delaunay triangulation failure: Invalid " - + "indices detected during internal detail" - + " iteration. Iteration: " + iterationCount - + ", Bad indices detected: "+ badIndicesCount); - outTriangles.clear(); - return 0; - } - - } - } - - return outVertCount; - } - - /** - * Generates data which represents the circumcircle of the triangle - * formed by the three points (A, B, C). - * @param triangleAreaX2 2x the area of the triangle formed by the - * points. The only reason for this parameter is for optimization. - * The only operation that calls this operation has already performed - * the area calculation, so why repeat it? - * @param outCircle The definition of the circumcircle in the form - * (x, y, r) where (x, y) is the center point and r is the radius. - * The value of (x, y) will be (0, 0) and r will be {@link #UNDEFINED} if - * this operation returns FALSE. - * @return TRUE if the circumcircle was successfully created. - * Otherwise FALSE. - */ - private static boolean buildCircumcircle(float ax - , float ay - , float bx - , float by - , float cx - , float cy - , float triangleAreaX2 - , float[] outCircle) - { - - /* - * References: - * http://en.wikipedia.org/wiki/Circumcenter#Coordinates_of_circumcenter - * http://mathworld.wolfram.com/Circumcircle.html - */ - - final float epsilon = 1e-6f; - - if (Math.abs(triangleAreaX2) > epsilon) - { - // Triangle has an area. Calculate center point of circle. - final float aLenSq = ax * ax + ay * ay; - final float bLenSq = bx * bx + by * by; - final float cLenSq = cx * cx + cy * cy; - outCircle[0] = (aLenSq * (by - cy) + bLenSq - * (cy - ay) + cLenSq * (ay - by)) / (2* triangleAreaX2); - outCircle[1] = (aLenSq * (cx - bx) + bLenSq - * (ax - cx) + cLenSq * (bx - ax)) / (2* triangleAreaX2); - // Calculate the radius of the circle. (Distance from center to - // one of the supplied points.) - outCircle[2] = (float)Math.sqrt( - getDistanceSq(outCircle[0], outCircle[1], ax, ay)); - return true; - } - - // Invalid triangle. - outCircle[0] = 0; - outCircle[1] = 0; - outCircle[2] = UNDEFINED; - return false; - } - - /** - * Attempts to form a new triangle on an UNDEFINED side of the specified - * edge. - *

      Will only attempt to form a new triangle for the first UNDEFINED - * side that is found.

      - *

      If a new triangle cannot be formed for the selected UNDEFINED side, - * then that side will be set to the value HULL.

      - *

      If a new triangle is formed, it is guaranteed to be complete. - * (I.e. All necessary data to form the triangle will exist in the - * edges list.)

      - * @param iEdge The index of the edge to perform the operation on. - * @param verts The available vertices in the format: (x, y, z) - * @param vertCount The number of vertices in the vertices array. - * @param currentTriangleCount The current number of triangles in the - * edges list. - * @param edges The edges list in the form: - * (vertA, vertB, valueA, valueB) where valueA is the side to the left - * of line segment vertA->vertB and valueB is the side to the left of - * line segment vertB->vertA. - * @return The new triangle count. If the return value is the same as - * currentTriangleCount then no new triangle could be formed. - */ - private static int completeTriangle(int iEdge - , float[] verts - , int vertCount - , int currentTriangleCount - , ArrayList edges) - { - - int iVertA; - int iVertB; - - if (edges.get(iEdge*4+2) == UNDEFINED) - { - // The side to the left of segment A->B is undefined. - iVertA = edges.get(iEdge*4); - iVertB = edges.get(iEdge*4+1); - } - else if (edges.get(iEdge*4+3) == UNDEFINED) - { - // The side to the left of segment B-A is undefined. - iVertA = edges.get(iEdge*4+1); - iVertB = edges.get(iEdge*4); - } - else - // Edge is already completed. No new faces. - return currentTriangleCount; - - final int pVertA = iVertA * 3; - final int pVertB = iVertB * 3; - - // The index of the best vertex on the left side of the edge. - int iSelectedVert = UNDEFINED; - - /* - * The definition of the selected circle in the format (x, z, r) - * where (x, z) is the center point and r is the radius. - * TODO: EVAL: Object creation. Convert to a working parameter? - */ - final float[] selectedCircle = { 0, 0, -1 }; - - // Values used to take into account floating point errors. - final float tolerance = 0.001f; - final float epsilon = 1e-5f; - - /* - * Loop through all the vertices. Find the vertex that is to the - * left of the edge (vertA->vertB) and forms the triangle with the - * smallest circumcircle. - * - * This process is difficult to optimize due to floating point - * errors. Especially when the source polygon is small in area. - * So the optimizations were abandoned. - */ - for (int iPotentialVert = 0 - ; iPotentialVert < vertCount - ; iPotentialVert++) - { - if (iPotentialVert == iVertA || iPotentialVert == iVertB) - // This vertex is one of the edge's vertices. Skip it. - continue; - - final int pPotentialVert = iPotentialVert * 3; - - final float area - = getSignedAreaX2(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pPotentialVert] - , verts[pPotentialVert+2]); - - if (area > epsilon) - { - // The three vertices form a triangle of adequate size AND the - // current vertex is to the left of the line segment - // vertA->vertB. - - if (selectedCircle[2] < 0) - { - // This is the first potentially valid vertex combination - // found so far. - if (overlapsExistingEdge(iVertA - , iPotentialVert - , verts - , edges) - || overlapsExistingEdge(iVertB - , iPotentialVert - , verts - , edges)) - // An overlap was found. Can't use this vertex. - continue; - // Vertex combination is valid. Try to use it. - if (buildCircumcircle(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pPotentialVert] - , verts[pPotentialVert+2] - , area - , selectedCircle)) - // Successfully created a circumcircle. - // Select this vertex. - iSelectedVert = iPotentialVert; - continue; - } - - // This is not the first valid combination found. - // Is it better than the existing? - - // Get the distance from the origin of the current - // circumcircle to this vertex. - final float distanceToOrigin = - (float)Math.sqrt(getDistanceSq(selectedCircle[0] - , selectedCircle[1] - , verts[pPotentialVert] - , verts[pPotentialVert+2])); - if (distanceToOrigin > selectedCircle[2] * (1 + tolerance)) - { - // This vertex is outside the current circumcircle and - // can be ignored. - continue; - } - else - { - /* - * The vertex is within, on, or almost on, the current - * circumcircle. - * - * If it were not for floating point errors, we could - * automatically accept all vertices that showed as - * within the current circumcircle. But floating point - * errors for small polygons prevent such a shortcut. - * - * Need to check if new edges formed by the use of this - * vertex will conflict with other edges already created. - */ - if (overlapsExistingEdge(iVertA - , iPotentialVert - , verts - , edges) - || overlapsExistingEdge(iVertB - , iPotentialVert - , verts - , edges)) - // An overlap was found. Can't use this vertex. - continue; - // Using this vertex is valid. - if (buildCircumcircle(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pPotentialVert] - , verts[pPotentialVert+2] - , area - , selectedCircle)) - // Successfully created a circumcircle. - // Select this vertex. - iSelectedVert = iPotentialVert; - } - } - } - - if (iSelectedVert != UNDEFINED) - { - // A new triangle can be formed. - - // Update triangle information of edge being completed. - updateLeftFace(iEdge, iVertA, currentTriangleCount, edges); - - // Add a new edge (selectedVert->vertA) or update face info - // of existing edge. - int iSelectedEdge = getEdgeIndex(edges, iSelectedVert, iVertA); - if (iSelectedEdge == UNDEFINED) - { - // This is a new edge. - edges.add(iSelectedVert); - edges.add(iVertA); - edges.add(currentTriangleCount); - edges.add(UNDEFINED); - } - else - // Update the existing edge. - updateLeftFace(iSelectedEdge - , iSelectedVert - , currentTriangleCount - , edges); - - // Add a new edge (vertB->selectedVert) or update face info - // of existing edge. - iSelectedEdge = getEdgeIndex(edges, iVertB, iSelectedVert); - if (iSelectedEdge == UNDEFINED) - { - // This is a new edge. - edges.add(iVertB); - edges.add(iSelectedVert); - edges.add(currentTriangleCount); - edges.add(UNDEFINED); - } - else - // Update the existing edge. - updateLeftFace(iSelectedEdge - , iVertB - , currentTriangleCount - , edges); - - // Indicate a new face was created. - currentTriangleCount++; - } - else - { - // A new face cannot be formed. Set the indicate the side of - // the edge is a hull. - updateLeftFace(iEdge, iVertA, HULL, edges); - } - - return currentTriangleCount; - } - - /** - * Attempts to find a span in the heightfield associated with the - * provided vertex. - *

      Spans that are within {@link OpenHeightfield#cellHeight()} of - * the vertices y-value take precedence in the search. Otherwise the - * span closest in height is returned.

      - * @param vertX The x-value of the vertex (x, y, z). - * @param vertY The y-value of the vertex (x, y, z). - * @param vertZ The z-value of the vertex (x, y, z). - * @param heightField The heightfield to search. - * @param outWidthDepth The actual width and depth index of the selected - * span in the form: (widthIndex, depthIndex). The array must be - * at least 2 in size. Content is undefined if the return value - * of the operation is null. - * @return The span in the feightfield that is best associated with - * the provided vertex. - */ - private static OpenHeightSpan getBestSpan(int vertX - , int vertY - , int vertZ - , OpenHeightfield heightField - , int[] outWidthDepth) - { - /* - * There are special cases which can result in the wrong span being - * returned by a simple column search. These special cases are what - * result in this a more complex search algorithm. - * - * In the best case search: Search up the height field column - * corresponding to the vertices x and z-values and return the - * span whose floor is within the correct tolerance of the y-value. - * - * While, technically, the best case search should always be - * successful, floating point errors and other special cases can - * result in a search failure. In such cases the search is expanded - * to the 8-neighbor cells, resulting in a slower search. - * - * If a search if forced to include neighbors, the search will - * always be a full 8-neighbor search. (No early exists.) - * - * Known special case when this occurs: - * - * The vertex lies on the outer edge of a border span. (The span - * edge across which there is no other span, at any height.) - * - * The vertex lies on the outer edge of a span without a connected - * neighbor. (The cell across the span edge contains spans, but - * none are connected as a neighbor to the span.) - * - * The scope of these special cases may not be fully known since - * a search failure can be hidden. E.g. When building a height - * patch, as long as one vertex in a polygon gets a good result, - * the flood fill algoritm can still succeed. The search failures - * will never be visible. There may be other special cases - * which are hidden in a similar manner. - * - * The known special cases are much less likely to exhibit when - * the source height field contains null (zero) region borders. - * This is because a border forces all vertices in from the region - * edges, which is where problems occur. - */ - - /* - * Search order starts with zero offset. - */ - final int[] targetOffset = - { 0,0, -1,0, 0,-1, -1,-1, 1,-1, -1,1, 1,0, 1,1, 0,1 }; - - OpenHeightSpan resultSpan = null; - int minDistance = Integer.MAX_VALUE; - // Loop through the offsets trying to find the best span match. - // Priority and potential early exit is given to spans at zero offset. - for (int p = 0; p < 17; p += 2) - { - int widthIndex = vertX + targetOffset[p]; - int depthIndex = vertZ + targetOffset[p+1]; - if (!heightField.isInBounds(widthIndex, depthIndex)) - // This neighbor is outside of the height field. - continue; - // Get the base span for this vertex from the height field. - OpenHeightSpan span = heightField.getData(widthIndex, depthIndex); - // Find the best span in the column. (Closest height match.) - span = getBestSpan(span, vertY); - if (span == null) - // No spans at the target location. - continue; - else - { - // Found a span. - int distance = Math.abs(vertY - span.floor()); - if (p == 0 && (distance <= heightField.cellHeight())) - { - // Found a span at a good height at the zero offset - // grid location. Don't search further. (Early exit.) - outWidthDepth[0] = widthIndex; - outWidthDepth[1] = depthIndex; - return span; - } - else if (distance < minDistance) - { - /* - * Could not find the "perfect" match. So dropping back - * to the best possible match. - * This span's floor is the closest to the vertex found - * so far. - */ - resultSpan = span; - outWidthDepth[0] = widthIndex; - outWidthDepth[1] = depthIndex; - minDistance = distance; - } - } - } - return resultSpan; - } - - /** - * Returns the span within the column whose floor is closest to the - * provided height. - * @param baseSpan Where to start the search. - * @param targetHeight The height to find the closest match for. - * @return The span whose floor is closest to the target height, or null - * if no base span was provided. - */ - private static OpenHeightSpan getBestSpan(OpenHeightSpan baseSpan - , int targetHeight) - { - int minDistance = Integer.MAX_VALUE; - OpenHeightSpan result = null; - // Loop up the column, starting at the base span. - for (OpenHeightSpan span = baseSpan; span != null; span = span.next()) - { - final int distance = Math.abs(targetHeight - span.floor()); - if (distance < minDistance) - { - // This span's floor is the closest to the vertex found so far. - result = span; - minDistance = distance; - } - } - return result; - } - - /** - * Returns the square of the distance between two points. - * @param ax The x-value of point (ax, ay). - * @param ay The y-value of point (ax, ay). - * @param bx The x-value of point (bx, by). - * @param by The y-value of point (bx, by). - * @return The square of the distance between two points. - */ - private static float getDistanceSq(float ax, float ay, float bx, float by) - { - final float deltaX = (ax - bx); - final float deltaY = (ay - by); - return deltaX * deltaX + deltaY * deltaY; - } - - /** - * Gets the index of the edge defined by two indices. - * @param edges The edge list where each edge is in the form: - * (vertIndex, vertIndex, value, value) - * @param vertAIndex The index of one of the edge's vertices. - * @param vertBIndex The index of the other of the edge's vertices. - * @return The index of the edge in the edges list which matches the - * provided vertices. Or {@link #UNDEFINED} if there is no corresponding - * edge. - */ - private static int getEdgeIndex(ArrayList edges - , int vertAIndex - , int vertBIndex) - { - final int edgeCount = edges.size() / 4; - for (int i = 0; i < edgeCount; i++) - { - final int u = edges.get(i*4); - final int v = edges.get(i*4+1); - if ((u == vertAIndex && v == vertBIndex) - || (u == vertBIndex && v == vertAIndex)) - return i; - } - return UNDEFINED; - } - - /** - * Get the height of the point within the height patch. - * @param x The world x position. - * @param z The world y position. - * @param minBounds The minimum bounds of the source field. - * @param cellSize The cell size of the source field. - * @param inverseCellSize The inverse of the cell size of the source - * field. (Included only to improve performance by avoiding a division - * within this operation.) - * @param patch The height patch to search. - * @return The height of the location within the patch. Or - * {@link Float#MAX_VALUE} if the - * search for a height fails. - */ - private static int getHeightWithinField(float x - , float z - , float cellSize - , float inverseCellSize - , HeightPatch patch) - { - /* - * There are two special cases when getting the height value: - * - * The x value is on the upper width edge of the source height field. - * The z value is on the upper depth edge of the source height field. - * - * In these cases this algorithm will create invalid indices for - * the height patch. (Out of bounds high.) Since the height patch - * is a private class (under strict control) it is being left up to - * the height patch class to clamp the index values so no exceptions - * are thrown. - * - * Note that these special cases refer to the source height field - * edges, not the height patch edges. This is because the height - * patch creation process always creates the patch to be slightly - * larger than the polygon being processed. The problem is that - * this slight expansion cannot occur when the height patch is up - * against the edges of source height field. - * - * The impact of these special cases is as follows: - * - * If x is on the upper width edge, then the same height value - * will be returned as is returned for (x - cellSize). - * - * If z is on the upper height edge, then the same value will be - * returned as is returned for (z - cellSize). - * - * This is not a significant issue. - */ - - // Convert world coordinates to height field indices. - final int widthIndex = (int)Math.floor(x * inverseCellSize + 0.01f); - final int depthIndex = (int)Math.floor(z * inverseCellSize + 0.01f); - // Get the height. - int height = patch.getData(widthIndex, depthIndex); - if (height == HeightPatch.UNSET) - { - /* - * One of the following special cases exist: - * - Data is bad. - * - Floating point calculation errors. - * - The vertex is in a true null region. (A region without - * any spans.) This can happen since sloppiness is permitted - * around null regions. - * Find nearest neighbor which has valid height. - * This is an 8 neighbor search. - */ - final int[] neighborOffset = - { -1,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1}; - float minNeighborDistanceSq = Float.MAX_VALUE; - for (int p = 0; p < 16; p += 2) - { - int nWidthIndex = widthIndex + neighborOffset[p]; - int nDepthIndex = depthIndex + neighborOffset[p+1]; - if (!patch.isInPatch(nWidthIndex, nDepthIndex)) - // This neighbor is outside of the height patch. - continue; - int nNeighborHeight = patch.getData(nWidthIndex, nDepthIndex); - if (nNeighborHeight == HeightPatch.UNSET) - // This neighbor doesn't have a value either. - continue; - // Get distance from this neighbor to the target location. - float deltaWidth = (nWidthIndex + 0.5f) * cellSize - x; - float deltaDepth = (nDepthIndex + 0.5f) * cellSize - z; - float neighborDistanceSq = - deltaWidth*deltaWidth + deltaDepth*deltaDepth; - if (neighborDistanceSq < minNeighborDistanceSq) - { - // This is the closest neighbor found so far. - height = nNeighborHeight; - minNeighborDistanceSq = neighborDistanceSq; - } - } - } - return height; - } - - /** - * Returns the approximate y-axis distance of a point from the triangle - * mesh. - *

      If the point is not within the (x, z) plane projection of the - * mesh then {@link #UNDEFINED} will be returned.

      - * @param px The x-value of the point to be tested. (px, py, pz) - * @param py The y-value of the point to be tested. (px, py, pz) - * @param pz The z-value of the point to be tested. (px, py, pz) - * @param verts The vertices of the mesh to test against. - * @param indices The indices for the mesh to test against. - * @return The approximate y-axis distance of a point from the - * triangle mesh. - */ - private static float getInternalDistanceToMesh(float px - , float py - , float pz - , float[] verts - , ArrayList indices) - { - - float minDistance = Float.MAX_VALUE; - - final int triangleCount = indices.size() / 3; - // Loop through all triangles in the mesh and get the point's y-distance - // from any triangles the point lies within. The goal is to find - // the minimum (closest to the mesh) y-distance. - for (int iTriangle = 0; iTriangle < triangleCount; iTriangle++) - { - final int pVertA = indices.get(iTriangle*3)*3; - final int pVertB = indices.get(iTriangle*3+1)*3; - final int pVertC = indices.get(iTriangle*3+2)*3; - - float distance = Float.MAX_VALUE; - - final float deltaACx = verts[pVertC] - verts[pVertA]; - final float deltaACy = verts[pVertC+1] - verts[pVertA+1]; - final float deltaACz = verts[pVertC+2] - verts[pVertA+2]; - - final float deltaABx = verts[pVertB] - verts[pVertA]; - final float deltaABy = verts[pVertB+1] - verts[pVertA+1]; - final float deltaABz = verts[pVertB+2] - verts[pVertA+2]; - - final float deltaAPx = px - verts[pVertA]; - final float deltaAPz = pz - verts[pVertA+2]; - - final float dotACAC = deltaACx * deltaACx + deltaACz * deltaACz; - final float dotACAB = deltaACx * deltaABx + deltaACz * deltaABz; - final float dotACAP = deltaACx * deltaAPx + deltaACz * deltaAPz; - final float dotABAB = deltaABx * deltaABx + deltaABz * deltaABz; - final float dotABAP = deltaABx * deltaAPx + deltaABz * deltaAPz; - - // Compute barycentric coordinates - final float inverseDenominator = 1.0f - / (dotACAC * dotABAB - dotACAB * dotACAB); - final float u = (dotABAB * dotACAP - dotACAB * dotABAP) - * inverseDenominator; - final float v = (dotACAC * dotABAP - dotACAB * dotACAP) - * inverseDenominator; - - final float tolerance = 1e-4f; - if (u >= -tolerance && v >= -tolerance && (u + v) <= 1 + tolerance) - { - // The point lies inside the (x, z) plane projection of - // the triangle. Interpolate the y value. - final float y = verts[pVertA+1] + deltaACy * u + deltaABy * v; - distance = Math.abs(y - py); - } - - if (distance < minDistance) - minDistance = distance; - } - if (minDistance == Float.MAX_VALUE) - // The point does not lie within the (x, z) plane projection - // of the mesh. So it is invalid. - return UNDEFINED; - - return minDistance; - } - - /** - * Detects whether an indices list contains any obviously invalid - * values. - *

      An invalid index: index < 0 or index >= vertCount. - *

      - * This check exists because the triangulation can be a bit dodgy when - * dealing with very small triangles. It helps detect these issues so - * crashes can be avoided. - *

      - * @param indices The detailed polygon indices in the form: - * (vertA, vertB, vertC) - * @param vertCount The number of vertices in the vertices array - * which the indices refer to. - * @return The number of invalid indices detected. - */ - private static int getInvalidIndicesCount(ArrayList indices - , int vertCount) - { - int badIndicesCount = 0; - for (int i = 0; i < indices.size(); i++) - { - int index = indices.get(i); - if (index < 0 || index >= vertCount) - badIndicesCount++; - } - return badIndicesCount; - } - - /** - * Returns the distance squared from the point to the line segment. - * @param px The x-value of point (px, py). - * @param py The y-value of point (px, py) - * @param ax The x-value of the line segment's vertex A. - * @param ay The y-value of the line segment's vertex A. - * @param bx The x-value of the line segment's vertex B. - * @param by The y-value of the line segment's vertex B. - * @return The distance squared from the point (px, py) to line segment AB. - */ - private static float getPointSegmentDistanceSq(float px - , float py - , float ax - , float ay - , float bx - , float by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line segment - * AB that is closest to P and then calculate the distance between - * P and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = deltaABx * deltaABx - + deltaABy * deltaABy; - - if (segmentABLengthSq == 0) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = (deltaAPx * deltaABx + deltaAPy * deltaABy) - / segmentABLengthSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and - // closer to A. So return distanceSq from P to A. - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) + (py - by)*(py - by); - - // Closest point on lineAB is inside segment AB. So find the exact - // point on AB and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on - // the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle defined by points (A, B, C). - *

      A positive value indicates:

      - *
        - *
      • Counterclockwise wrapping of the points.
      • - *
      • Point B lies to the right of line AC, looking from A to C.
      • - *
      - *

      A negative value indicates:

      - *
        - *
      • Clockwise wrapping of the points.
      • - *
      • Point B lies to the left of line AC, looking from A to C.
      • - *
      - *

      A value of zero indicates that all points are collinear or - * represent the same point. - *

      Each call to this operation results in 2 multiplications and 5 - * subtractions.

      - * @param ax The x-value for point (ax, ay) for vertex A of the triangle. - * @param ay The y-value for point (ax, ay) for vertex A of the triangle. - * @param bx The x-value for point (bx, by) for vertex B of the triangle. - * @param by The y-value for point (bx, by) for vertex B of the triangle. - * @param cx The x-value for point (cx, cy) for vertex C of the triangle. - * @param cy The y-value for point (cx, cy) for vertex C of the triangle. - * @return The signed value of two times the area of the triangle defined - * by the points (A, B, C). - */ - private static float getSignedAreaX2(float ax - , float ay - , float bx - , float by - , float cx - , float cy) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm - // #Modern%20Triangles - // http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - - /** - * Returns the distance squared from the point to the closest polygon - * segment on the (x, z) plane. - * If the return value is positive, the point is outside the polygon. - * @param x The x-value of the test point (x, z). - * @param z The y-value of the test point (x, z). - * @param verts The polygon vertices in the form - * (ax, ay, az, bx, by, bz, ..., nx, ny, nz, trash) - * @param vertCount The number of vertices in the polygon. - * @return The distanceSq from the point to the closest polygon - * segment on the (x, z) plane. - */ - private static float getSignedDistanceToPolygonSq(float x - , float z - , float[] verts - , int vertCount) - { - float minDistance = Float.MAX_VALUE; - int iVertB; - int iVertA; - boolean isInside = false; - // Loop through all edges of the polygon and determine the distance - // from (x, y) to the edge. - for (iVertB = 0, iVertA = vertCount-1 - ; iVertB < vertCount - ; iVertA = iVertB++) - { - final int pVertB = iVertB*3; - final int pVertA = iVertA*3; - if (((verts[pVertB+2] > z) != (verts[pVertA+2] > z)) - && (x < (verts[pVertA]-verts[pVertB]) * (z-verts[pVertB+2]) - / (verts[pVertA+2]-verts[pVertB+2]) - + verts[pVertB]) ) - // The point is inside the polygons (x,z) plane's column. - isInside = true; - // Get the distance from the point to this edge and compare it - // to the current minimum distance. - minDistance = Math.min(minDistance - , getPointSegmentDistanceSq(x - , z - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2])); - } - return isInside ? -minDistance : minDistance; - } - - /** - * Fills the data array of a height patch with height data. Height - * data is chosen from the heightfield based on the provided polygon's - * vertices. - *

      The closest floor for each vertex is recorded, then this - * operation floods fills outward to all neighbors, recording neighbor - * floor heights, out to the edges of the height patch. - * @param polyPointer A pointer to the polygon whose vertices will be - * used as seed information when building the height data. - * @param vertCount The number of vertices in the polygon. - * @param indices Polygon indices data. - * @param verts Vertex data. - * @param inoutPatch The section of the height field to find height - * data for. Expects that the bounds data has been set. - * Expects data array to be pre-sized such that it can fit the maximum - * possible data. The data array values will be initialized to UNSET - * before being filled. - * @param gridIndexStack A working stack. Its data will be discarded - * prior to use. Content after the operation completes is undefined. - * @param spanStack A working stack. Its data will be discarded prior - * to use. Content after the operation completes is undefined. - * @param widthDepth A working array. Expected to be of size 2. - * Its content is undefined after operation completes. - */ - private static void loadHeightPatch(int polyPointer - , int vertCount - , int[] indices - , int[] verts - , OpenHeightfield heightField - , HeightPatch inoutPatch - , ArrayDeque gridIndexStack - , ArrayDeque spanStack - , int[] widthDepth) - { - // Initialization - inoutPatch.resetData(); - gridIndexStack.clear(); - spanStack.clear(); - - /* - * For each vertex, locate the span in the height field that is - * closest to it. Push the spans onto the stack. - * Only searching spans at the grid location of the vertex. - * (E.g. In the height column of the vertex.) - */ - - for (int vertOffset = 0; vertOffset < vertCount; vertOffset++) - { - // The width within the height field. - final int vertX = verts[indices[polyPointer+vertOffset]*3]; - // The height within the height field. - final int vertY = verts[indices[polyPointer+vertOffset]*3+1]; - // The depth within the height field. - final int vertZ = verts[indices[polyPointer+vertOffset]*3+2]; - - // Search for the best span in the height field for this vertex. - // Best span is the span whose floor area is closest to the - // vertex location. - final OpenHeightSpan selectedSpan = - getBestSpan(vertX, vertY, vertZ, heightField, widthDepth); - - if (selectedSpan != null) - { - // Found a span for this vertex. Push in onto the stack. - gridIndexStack.push(widthDepth[0]); - gridIndexStack.push(widthDepth[1]); - spanStack.push(selectedSpan); - } - } - - // NOTE: If the polygon mesh was properly built, the stack should - // always have a size greater than zero. - - /* - * Using the spans that have been seeded into the stacks, flood - * outward, recording the heights found for each grid location - * within the bounds of the patch. - */ - while(spanStack.size() > 0) - { - final int depthIndex = gridIndexStack.pop(); - final int widthIndex = gridIndexStack.pop(); - OpenHeightSpan span = spanStack.pop(); - - if (inoutPatch.getData(widthIndex, depthIndex) != HeightPatch.UNSET) - // This grid location was processed in an earlier iteration. - continue; - - if (inoutPatch.isInPatch(widthIndex, depthIndex)) - { - /* - * This span is in the height patch. Record the span's height. - * - * Note: It is a valid situation for the span to NOT be in - * the height patch. This can occur in the special cases - * described in detail in getHeightWithinField(). When this - * occurs, the algorithm depends on the neighbor search - * below to ensure the necessary flooding succeeds. - * E.g. One of the neighbors should end up within the - * bounds of the patch and continue the flooding. - */ - inoutPatch.setData(widthIndex, depthIndex, span.floor()); - } - - // "Flood" to the neighbors of this span. If a neighbor is within - // the patch's grid, then put it in the stacks for processing. - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null) - // No neighbor in this direction. - continue; - - final int nWidthIndex = - widthIndex + BoundedField.getDirOffsetWidth(dir); - final int nDepthIndex = - depthIndex + BoundedField.getDirOffsetDepth(dir); - - if (!inoutPatch.isInPatch(nWidthIndex, nDepthIndex)) - // This neighbor is outside the bounds of the patch. - // So skip it. - continue; - - if (inoutPatch.getData(nWidthIndex, nDepthIndex) != - HeightPatch.UNSET) - // This grid location was processed in an earlier iteration. - continue; - - // Need to process this neighbor. - gridIndexStack.push(nWidthIndex); - gridIndexStack.push(nDepthIndex); - spanStack.push(nSpan); - - } - } - } - - /** - * Checks whether or not a potential new edge intersects with any - * existing edge. Same and connected edges are ignored. - * @param iVertA The first vertex index of the potential new edge. - * @param iVertB The second vertex index of the potential new edge. - * @param verts The available vertices in the form (x, y, z) - * @param edges The edge definitions in the form - * (vertAIndex, vertBIndex, valueA, valueB) - * (valueA and valueB are not used by this operation.) - * @return TRUE if the potential new edge inappropriately intersects - * with an existing edge. - * Otherwise FALSE. - */ - private static boolean overlapsExistingEdge(int iVertA - , int iVertB - , float verts[] - , ArrayList edges) - { - // Loop through all edges. - for (int pEdge = 0; pEdge < edges.size(); pEdge += 4) - { - final int iEdgeVertA = edges.get(pEdge); - final int iEdgeVertB = edges.get(pEdge+1); - if (iEdgeVertA == iVertA - || iEdgeVertA == iVertB - || iEdgeVertB == iVertA - || iEdgeVertB == iVertB) - // Is same or connected edge. Ignore this edge. - continue; - if (segmentsOverlap(verts[iEdgeVertA*3] - , verts[iEdgeVertA*3+2] - , verts[iEdgeVertB*3] - , verts[iEdgeVertB*3+2] - , verts[iVertA*3] - , verts[iVertA*3+2] - , verts[iVertB*3] - , verts[iVertB*3+2])) - // The new edge overlaps this edge. - return true; - } - // No intersections detected. - return false; - } - - /** - * Attempts to perform a Delaunay triangulation on a group of vertices, - * potentially restricted by the content of the hull argument. - * @param verts The vertices to triangulate in the form (x, y, z). - * @param vertCount The number of vertices in the vertices array. - * @param immutableHull The indices that make up the required hull - * edges. These edges are guaranteed to be in the final triangulation. - *

      The indices in the hull array are expected to define a clockwise - * wrapped convex polygon. Behavior of the operation is undefined if - * this is not the case.

      - * @param hullEdgeCount The number of indices in the hull array. - * If zero, then there will be no guaranteed edges. - * @param workingEdges A working list used for internal purposes. Its - * only purpose as an argument is to save on object creation time. - * Its content is cleared before use. - * @param outTriangles The indices of the output triangle mesh in the - * form (vertAIndex, vertBIndex, vertCIndex). The indices refer to - * vertices in the vertices array. - *

      The list is cleared prior to use by this operation.

      - */ - private static void performDelaunayTriangulation(float[] verts - , int vertCount - , int[] immutableHull - , int hullEdgeCount - , ArrayList workingEdges - , ArrayList outTriangles) - { - - int triangleCount = 0; - workingEdges.clear(); - - /* - * General reference: - * http://en.wikipedia.org/wiki/Delaunay_triangulation - * More references at: - * http://digestingduck.blogspot.com/2009/10/ - * delaunay-triangulations.html - */ - - /* - * Entries in the working edges list is as follows: - * (vertA, vertB, valueA, valueB) - * where valueA is the side to the left of line segment vertA->vertB - * and valueB is the side to the left of line segment vertB->vertA - */ - - // Create an working edge entry for each hull edge. - for (int iHullVertB = 0, iHullVertA = hullEdgeCount-1 - ; iHullVertB < hullEdgeCount - ; iHullVertA = iHullVertB++) - { - workingEdges.add(immutableHull[iHullVertA]); - workingEdges.add(immutableHull[iHullVertB]); - // Since hull is expected to be clockwise wrapped, mark the - // left side of the edge as a hull. - workingEdges.add(HULL); - // Don't know what is on the right side of the edge yet. - // So default to undefined. - workingEdges.add(UNDEFINED); - } - - /* - * Loop through edges until all UNDEFINED sides have been defined. - * Notes: - * - The looping is expected to continue for longer than the original - * edge count since new edges will be created by the triangle - * completion operation. - * - No edge will ever be added to the edge list without at least - * one side already defined. So each edge will, at most, need a - * single triangle built for it. - */ - int iCurrentEdge = 0; - while (iCurrentEdge * 4 < workingEdges.size()) - { - if (workingEdges.get(iCurrentEdge*4+2) == UNDEFINED - || workingEdges.get(iCurrentEdge*4+3) == UNDEFINED) - // Need to create a triangle for one of the sides. - triangleCount = completeTriangle(iCurrentEdge - , verts - , vertCount - , triangleCount - , workingEdges); - iCurrentEdge++; - } - - /* - * Unless there is a logic error, at this point no side value in the - * edges array should have a value of UNDEFINED. They should all - * either be set to a triangle index or HULL. - * The strict HULL equality tests below, rather than just testing - * for >= 0, are meant to force logic errors to the surface. - */ - - // Fill the triangle list with the UNDEFINED value for each - // expected entry. - outTriangles.clear(); - outTriangles.ensureCapacity(triangleCount*3); - for (int i = 0; i < triangleCount * 3; i++) - outTriangles.add(UNDEFINED); - - // Loop through all edges. - for (int pEdge = 0; pEdge < workingEdges.size(); pEdge += 4) - { - - /* - * This algorithm is based on the following assumptions: - * - * Two of the three triangle vertices are known as soon as a - * triangle is first detected. Only the third vertex needs to - * be found. - * - * The edge building process guarantees that no partial - * triangles exist in the data. - */ - - // This strict test is meant to force logic errors to the surface. - // E.g. If an UNDEFINED value creeps into the working edges list. - if (workingEdges.get(pEdge+3) != HULL) - { - /* - * The right side of edge A->B has a associated triangle. - * This will always be the case for hull edges. - * Also indicates that A->B is the clockwise wrapping direction. - */ - - // Get a pointer to the triangle. - final int pTriangle = workingEdges.get(pEdge+3)*3; - - if (outTriangles.get(pTriangle) == UNDEFINED) - { - - /* - * This is the first time this triangle has been seen. - * - * Initialize this triangle by adding the edge's vertices - * to the triangle definition. - * - * Wrap A->B for clockwise. - */ - outTriangles.set(pTriangle, workingEdges.get(pEdge)); - outTriangles.set(pTriangle+1, workingEdges.get(pEdge+1)); - } - else if (outTriangles.get(pTriangle+2) == UNDEFINED) - { - // This triangle's first two vertices have already been - // set. Need to figure out which vertex in this edge - // is the final vertex. - if (workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle)) - || workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle+1))) - // The first vertex of this edge is already in the - // triangle. Add the second vertex of this edge to - // the triangle. - outTriangles.set(pTriangle+2 - , workingEdges.get(pEdge+1)); - else - /* - * The first vertex of this edge is NOT already in - * the triangle, so the 2nd vertex must already be - * in it. Add the first vertex of this edge to the - * triangle. - */ - outTriangles.set(pTriangle+2, workingEdges.get(pEdge)); - } - } - if (workingEdges.get(pEdge+2) != HULL) - { - /* - * The left side of edge A->B has an associated triangle. - * - * Indicates that B->A is the clockwise wrapping direction. - * - * This will never be the case for an original edge since - * original edges always have their left sides set to HULL. - */ - - final int pTriangle = workingEdges.get(pEdge+2)*3; - - if (outTriangles.get(pTriangle) == UNDEFINED) - { - - /* - * This is the first time this triangle has been seen. - * - * Trivia: Will only get here for internal triangles that - * don't have a hull edge. - * - * Initialize this triangle by adding the edge's vertices - * to the triangle definition. - * - * Wrap B->A for clockwise. - */ - outTriangles.set(pTriangle, workingEdges.get(pEdge+1)); - outTriangles.set(pTriangle+1, workingEdges.get(pEdge)); - } - else if (outTriangles.get(pTriangle+2) == UNDEFINED) - { - // This triangle's first two vertices have already been - // set. Need to figure out which vertex in this edge - // is the final vertex. - if (workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle)) - || workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle+1))) - // The first vertex of this edge is already in the - // triangle. Add the second vertex of this edge to - // the triangle. - outTriangles.set(pTriangle+2 - , workingEdges.get(pEdge+1)); - else - /* - * The first vertex of this edge is NOT already in - * the triangle, so the 2nd vertex must already be - * in it. Add the first vertex of this edge to - * the triangle. - */ - outTriangles.set(pTriangle+2, workingEdges.get(pEdge)); - } - } - } - - } - - /** - * Returns TRUE if the line segments AB and CD intersect at one or - * more points. Otherwise FALSE. - * @param ax The x-value of point (ax, ay) for the line segment AB - * @param ay The y-value of point (ax, ay) for the line segment AB - * @param bx The x-value of point (bx, by) for the line segment AB - * @param by The y-value of point (bx, by) for the line segment AB - * @param cx The x-value of point (cx, cy) for the line segment CD - * @param cy The y-value of point (cx, cy) for the line segment CD - * @param dx The x-value of point (dx, dy) for the line segment CD - * @param dy The y-value of point (dx, dy) for the line segment CD - * @return TRUE if the line segments AB and CD intersect at one or - * more points. Otherwise FALSE. - */ - private static boolean segmentsOverlap(float ax - , float ay - , float bx - , float by - , float cx - , float cy - , float dx - , float dy) - { - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - - final float deltaCDx = dx - cx; - final float deltaCDy = dy - cy; - - final float deltaCAx = ax - cx; - final float deltaCAy = ay - cy; - - final float numerator = (deltaCAy * deltaCDx) - (deltaCAx * deltaCDy); - final float denominator = (deltaABx * deltaCDy) - (deltaABy * deltaCDx); - - final float tolerance = 0.001f; - - if (denominator == 0) - { - if (numerator != 0) - // Parallel and not colinear - return false; - /* - * Lines are colinear. But do the segments overlap? - * - * Note: This design takes into account that it is a - * logic error to call this operation for segments that share - * end points. - * - * Note: Since we know they are colinear, we only need to - * check one axis for overlap. - */ - if (Math.abs(cx - dx) < tolerance) - { - // Line is horizontal. Use y-axis. - if (Math.max(cy, dy) < Math.min(ay, by) - || Math.max(ay, by) < Math.min(cy, dy)) - // The end points of the segments don't overlap. - // No intersection. - return false; - else - // The end points of the segments overlap. Intersection. - return true; - } - else - { - if (Math.max(cx, dx) < Math.min(ax, bx) - || Math.max(ax, bx) < Math.min(cx, dx)) - // The end points of the segments don't overlap. - // No intersection. - return false; - else - // The end points of the segments overlap. Intersection. - return true; - } - } - - // Lines definitely intersect at a single point. - - float factorAB = numerator / denominator; - float factorCD = ((deltaCAy * deltaABx) - (deltaCAx * deltaABy)) - / denominator; - - // Determine the type of intersection - if ((factorAB >= 0.0f) - && (factorAB <= 1.0f) - && (factorCD >= 0.0f) - && (factorCD <= 1.0f)) - // Segments intersect. - return true; - - // Intersection is outside of one or both segments. - return false; - - } - - /** - * Sets the left face value of the specified edge to the specified value - * if the value is not already set. - *

      Note that this means that once the value has been set to a value - * other than UNDEFINED, this operation will not change the value.

      - * @param iEdge The index of the edge to update. - * @param iStartVert The vertex that represents the start of the edge. - * Used to determine which side of the edge is left. - * @param faceValue The new value to apply. - * @param edges The list of edges in the form - * (vertAIndex, vertBIndex, valueA, valueB) - * where valueA represents the left side of the edge A->B and valueB - * represents the left side of the edge B->A. - */ - private static void updateLeftFace(int iEdge - , int iStartVert - , int faceValue - , ArrayList edges) - { - final int pEdge = iEdge*4; - if (edges.get(pEdge) == iStartVert - && edges.get(pEdge+2) == UNDEFINED) - edges.set(pEdge+2, faceValue); - else if (edges.get(pEdge+1) == iStartVert - && edges.get(pEdge+3) == UNDEFINED) - edges.set(pEdge+3, faceValue); - } -} diff --git a/critterai/.svn/pristine/c2/c2107ed57ca6c73729abbb06e9bafbacda91f956.svn-base b/critterai/.svn/pristine/c2/c2107ed57ca6c73729abbb06e9bafbacda91f956.svn-base deleted file mode 100644 index e32f49e7..00000000 --- a/critterai/.svn/pristine/c2/c2107ed57ca6c73729abbb06e9bafbacda91f956.svn-base +++ /dev/null @@ -1,69 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {42218E47-156D-46FF-84E0-119D47B0E4EB} - Library - Properties - org.critterai - cai-nav - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG - prompt - 4 - AnyCPU - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - AnyCPU - ..\bin\Release\cai-nav.XML - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - rcn\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - {319D361B-147F-45AC-854E-50C06FCA3393} - cai-nav-rcn - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/c2/c2ae9097714d1b28f7c03cebebbf7fb395e06983.svn-base b/critterai/.svn/pristine/c2/c2ae9097714d1b28f7c03cebebbf7fb395e06983.svn-base deleted file mode 100644 index 69fef1f2..00000000 --- a/critterai/.svn/pristine/c2/c2ae9097714d1b28f7c03cebebbf7fb395e06983.svn-base +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This feature removed from v0.4. - * - * Not tested. - * - * TODO: EVAL: v0.5: Is this really useful? - * - */ - -//* -// * Copyright (c) 2012 Stephen A. Pratt -// * -// * Permission is hereby granted, free of charge, to any person obtaining a copy -// * of this software and associated documentation files (the "Software"), to deal -// * in the Software without restriction, including without limitation the rights -// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// * copies of the Software, and to permit persons to whom the Software is -// * furnished to do so, subject to the following conditions: -// * -// * The above copyright notice and this permission notice shall be included in -// * all copies or substantial portions of the Software. -// * -// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// * THE SOFTWARE. -// */ -//using UnityEngine; -//using UnityEditor; -//using org.critterai.u3d.editor; -//using org.critterai.nmbuild.u3d.editor; - -//[CustomEditor(typeof(ColliderCompiler))] -//public class ColliderCompilerEditor -// : Editor -//{ -// ///

      -// /// Controls behavior of the inspector. -// /// -// public override void OnInspectorGUI() -// { -// ColliderCompiler targ = (ColliderCompiler)target; - -// EditorGUILayout.Separator(); - -// GUILayout.Label("Priority: " + targ.Priority); - -// EditorGUILayout.Separator(); - -// EditorGUIUtility.LookLikeControls(150); - -// targ.allowMeshColocation = -// EditorGUILayout.Toggle("Allow Mesh Colocation", targ.allowMeshColocation); - -// EditorGUILayout.Separator(); - -// GUILayout.Box("Input Build Processor\n" -// + "Loads and compiles (triangulates) the " + typeof(Collider).Name -// + " components in the scene. Cube, sphere, and mesh colliders are supported." -// , EditorUtil.HelpStyle -// , GUILayout.ExpandWidth(true)); - -// EditorGUILayout.Separator(); - -// if (GUI.changed) -// EditorUtility.SetDirty(targ); -// } - -// [MenuItem(EditorUtil.NMGenAssetMenu + "Compiler : Collider", false, NMBEditorUtil.CompilerGroup)] -// static void CreateAsset() -// { -// ColliderCompiler item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); -// EditorUtility.FocusProjectWindow(); -// Selection.activeObject = item; -// } -//} diff --git a/critterai/.svn/pristine/c3/c3207cda9ed7c8433c73b4347403ab09c60b3a8f.svn-base b/critterai/.svn/pristine/c3/c3207cda9ed7c8433c73b4347403ab09c60b3a8f.svn-base deleted file mode 100644 index ca28ef9b..00000000 --- a/critterai/.svn/pristine/c3/c3207cda9ed7c8433c73b4347403ab09c60b3a8f.svn-base +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.interop; -using org.critterai.nmgen.rcn; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Represents a group of related contours. - /// - /// - /// - /// A contour set is usually generated from a single . All - /// contours share the minimum bounds and cell sizes of the set. - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - public sealed class ContourSet - : IManagedObject - { - - internal ContourSetEx root; - private Contour[] mContours = null; - - /// - /// The width of the set. (Along the x-axis in cell units.) - /// - public int Width { get { return root.width; } } - - /// - /// The depth of the set. (Along the z-axis in cell units.) - /// - public int Depth { get { return root.depth; } } - - /// - /// The width/depth increment of each cell. (On the xz-plane.) - /// - /// - /// - /// See for information on how the bounds and cell sizes are applied - /// to member contours. - /// - /// - public float XZCellSize { get { return root.xzCellSize; } } - - /// - /// The height increment of each cell. (On the y-axis.) - /// - /// - /// - /// See for information on how the bounds and cell sizes are - /// applied to member contours. - /// - /// - public float YCellSize { get { return root.yCellSize; } } - - /// - /// The AABB border size used to generate the source data from which the contours were - /// derived. - /// - public int BorderSize { get { return root.borderSize; } } - - /// - /// The number of contours in the set. - /// - public int Count { get { return root.contourCount; } } - - /// - /// The minimum bounds of the set in world space. - /// - /// - /// - /// See for information on how the bounds and cell sizes are applied - /// to member contours. - /// - /// - /// The minimum bounds of the set. - public Vector3 BoundsMin { get { return root.boundsMin; } } - - /// - /// The maximum bounds of the set in world space. - /// - /// The maximum bounds of the set. - public Vector3 BoundsMax { get { return root.boundsMax; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed - { - get { return (root.contours == IntPtr.Zero); } - } - - /// - /// The type of unmanaged resources within the object. - /// - public AllocType ResourceType { get { return AllocType.External; } } - - private ContourSet(ContourSetEx root) - { - this.root = root; - } - - /// - /// Destructor - /// - ~ContourSet() - { - RequestDisposal(); - } - - /// - /// Frees and marks as disposed all resources. (Including member objects.) - /// - public void RequestDisposal() - { - if (IsDisposed) - return; - - ContourSetEx.nmcsFreeSetData(root); - - if (mContours == null) - return; - - for (int i = 0; i < mContours.Length; i++) - { - if (mContours[i] != null) - mContours[i].Reset(); - } - } - - /// - /// Gets the contour for the specified index. - /// - /// - /// The contour index. [Limits: 0 < value < ] - /// - /// The contour, or null on failure. - public Contour GetContour(int index) - { - if (IsDisposed || index < 0 || index >= root.contourCount) - return null; - - if (mContours == null) - mContours = new Contour[root.contourCount]; - - if (mContours[index] != null) - return mContours[index]; - - Contour result = new Contour(); - - ContourSetEx.nmcsGetContour(root, index, result); - mContours[index] = result; - - return result; - } - - /// - /// Builds a contour set from the region outlines in the provided . - /// - /// - /// - /// The raw contours will match the region outlines exactly. The edgeMaxDeviation - /// and maxEdgeLength parameters control how closely the simplified contours will match - /// the raw contours. - /// - /// - /// Simplified contours are generated such that the vertices for portals between areas - /// match up. (They are considered mandatory vertices.) - /// - /// - /// Setting maxEdgeLength to zero will disabled the feature. - /// - /// - /// The context to use for the build. - /// The field to use for the build.(Must have region data.) - /// - /// The maximum distance a simplified edge may deviate from the raw contour's vertices. - /// [Limit: >= 0] - /// - /// - /// The maximum allowed length of a simplified edge. [Limit: >= 0] - /// - /// The build flags. - /// The contour set, or null on failure. - public static ContourSet Build(BuildContext context, CompactHeightfield field - , float edgeMaxDeviation, int maxEdgeLength, ContourBuildFlags flags) - { - if (context == null || field == null || field.IsDisposed - || edgeMaxDeviation < 0 - || maxEdgeLength < 0) - { - return null; - } - - ContourSetEx root = new ContourSetEx(); - - if (ContourSetEx.nmcsBuildSet(context.root, field - , edgeMaxDeviation, maxEdgeLength - , root - , flags)) - { - return new ContourSet(root); - } - - return null; - } - } -} diff --git a/critterai/.svn/pristine/c3/c32ff153bc161f36a7c1bcacaad843927736d420.svn-base b/critterai/.svn/pristine/c3/c32ff153bc161f36a7c1bcacaad843927736d420.svn-base deleted file mode 100644 index d7f33e47..00000000 --- a/critterai/.svn/pristine/c3/c32ff153bc161f36a7c1bcacaad843927736d420.svn-base +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; - -namespace org.critterai -{ - /// - /// Compares two priority items. - /// - /// The type of the priority item. - public sealed class PriorityComparer - : IComparer where T : IPriorityItem - { - private bool mAscending; - - /// - /// True if the comparison is for an ascending sort. - /// - public bool Ascending { get { return mAscending; } } - - /// - /// Constructor. - /// - /// True for an ascending sort, otherwise false. - public PriorityComparer(bool ascending) - { - mAscending = ascending; - } - - /// - /// Compares two priority items and returns a value indicating whether one is less than, - /// equal to, or greater than the other. - /// - /// - /// - /// Returns zero if the priorities are equal. - /// - /// - /// If ascending, returns -1 if x is less than y, and 1 if x is greater than y. - /// - /// - /// If descending, return -1 if x is greater than y, and 1 if x is less than y. - /// - /// - /// A priority item. - /// A priority item. - /// The comparision result. (See remarks.) - public int Compare(T x, T y) - { - int xp = x.Priority; - int yp = y.Priority; - - if (mAscending) - return (xp == yp ? 0 : xp < yp ? -1 : 1); - else - return (xp == yp ? 0 : xp > yp ? -1 : 1); - } - } -} diff --git a/critterai/.svn/pristine/c3/c3dc920f2b56a82ed6bb246172fe2855f48c74ad.svn-base b/critterai/.svn/pristine/c3/c3dc920f2b56a82ed6bb246172fe2855f48c74ad.svn-base deleted file mode 100644 index 3961cffa..00000000 Binary files a/critterai/.svn/pristine/c3/c3dc920f2b56a82ed6bb246172fe2855f48c74ad.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/c5/c5081eda70260ea2b83326d247847f39e39f3a52.svn-base b/critterai/.svn/pristine/c5/c5081eda70260ea2b83326d247847f39e39f3a52.svn-base deleted file mode 100644 index 19ee8bd5..00000000 --- a/critterai/.svn/pristine/c5/c5081eda70260ea2b83326d247847f39e39f3a52.svn-base +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" -#include "RecastAlloc.h" - -extern "C" -{ - EXPORT_API int nmlsBuildLayers(nmgBuildContext* ctx - , rcCompactHeightfield* chf - , const int borderSize - , const int walkableHeight - , rcHeightfieldLayerSet** resultSet) - { - if (!ctx || !chf) - return -1; - - rcHeightfieldLayerSet* lset = rcAllocHeightfieldLayerSet(); - if (!lset) - return -1; - - if (!rcBuildHeightfieldLayers(ctx - , *chf - , borderSize - , walkableHeight - , *lset)) - { - rcFreeHeightfieldLayerSet(lset); - return -1; - } - - if (lset->nlayers == 0) - { - rcFreeHeightfieldLayerSet(lset); - return -1; - } - - *resultSet = lset; - return lset->nlayers; - } - - EXPORT_API void nmlsFreeLayers(rcHeightfieldLayerSet* lset) - { - rcFreeHeightfieldLayerSet(lset); - } - - EXPORT_API bool nmlsGetLayer(rcHeightfieldLayerSet* lset - , int index - , rcHeightfieldLayer* layer) - { - if (!lset || !layer || index < 0 || index >= lset->nlayers) - return false; - - memcpy(layer, &lset->layers[index], sizeof(rcHeightfieldLayer)); - - return true; - } - -} \ No newline at end of file diff --git a/critterai/.svn/pristine/c5/c586405125fb3e2ca64996e2ccd92295c2834764.svn-base b/critterai/.svn/pristine/c5/c586405125fb3e2ca64996e2ccd92295c2834764.svn-base deleted file mode 100644 index 3265544e..00000000 --- a/critterai/.svn/pristine/c5/c586405125fb3e2ca64996e2ccd92295c2834764.svn-base +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmbuild.u3d.editor; -using org.critterai.u3d.editor; -using UnityEditor; -using UnityEngine; - -/// -/// Handles advanced build features for assets. (Editor Only) -/// -/// -public sealed class NavmeshBuildManager - : EditorWindow -{ - /* - * Design notes: - * - * An editor reset will cause disable/enable to run. - * A scene change is taken care of by the heirarchy change event. - */ - - private const string WindowTitle = "Navmesh Build"; - private const int NoSelection = -1; // Must be < 0; - - private static BuildProcessor mProcessor; - - private const float ToolbarHeight = 25; - private const float GlobalStatusHeight = 20; - - private const float MinWidth = ControlUtil.ButtonAreaWidth + 2 * ControlUtil.MarginSize; - - // The config control is the current restriction; - private const float MinHeight = 455; - - private float mTaskMax; - - void OnEnable() - { - minSize = new Vector2(MinWidth, MinHeight); - - // Remember, the processor is static, so it may have persisted. - SetProcessor(); - - SceneView.onSceneGUIDelegate += OnSceneGUI; - } - - void OnDisable() - { - if (mProcessor.TaskManager.TaskCount == 0) - // Don't want the the background thread to keep running if there is nothing to do. - ClearProcessor(); - - SceneView.onSceneGUIDelegate -= OnSceneGUI; - } - - private static void ClearProcessor() - { - if (mProcessor == null) - return; - - EditorApplication.update -= mProcessor.Update; - mProcessor.Dispose(); - - mProcessor = null; - } - - private static void SetProcessor() - { - if (mProcessor == null) - { - mProcessor = new BuildProcessor(); - EditorApplication.update += mProcessor.Update; - } - } - - void OnGUI() - { - if (mProcessor.BuildCount == 0) - { - GUILayout.Label("Select an advanced navigation mesh build from the project window."); - return; - } - - float displayWidth = position.width - 2 * ControlUtil.MarginSize; - float displayHeight = position.height - 2 * ControlUtil.MarginSize; - - Rect toolBarArea = new Rect(ControlUtil.MarginSize - , ControlUtil.MarginSize - , displayWidth - , ToolbarHeight); - - Rect controlArea = new Rect(ControlUtil.MarginSize - , toolBarArea.yMax + ControlUtil.MarginSize - , displayWidth - , displayHeight - ToolbarHeight - GlobalStatusHeight - 2 * ControlUtil.MarginSize); - - Rect statusArea = new Rect(ControlUtil.MarginSize - , controlArea.yMax + ControlUtil.MarginSize - , displayWidth - , GlobalStatusHeight); - - bool includeMain = position.width >= MinWidth + 3 * ControlUtil.MarginSize; - - BuildSelector.Instance.OnGUI(toolBarArea); - mProcessor.OnGUI(controlArea, includeMain); - - float taskCount = mProcessor.TaskManager.TaskCount; - - if (taskCount == 0) - { - mTaskMax = 0; - GUI.Box(statusArea, "No Build Tasks.", EditorUtil.HelpStyle); - } - else - { - mTaskMax = Mathf.Max(mTaskMax, taskCount); - if (mTaskMax == 1) - GUI.Box(statusArea, "Build Tasks: " + taskCount, EditorUtil.HelpStyle); - else - EditorGUI.ProgressBar(statusArea, 1 - taskCount / mTaskMax, ""); - } - } - - void OnSceneGUI(SceneView scene) - { - mProcessor.OnSceneGUI(); - } - - void OnInspectorUpdate() - { - Repaint(); - } - - void OnSelectionChange() - { - Object selection = Selection.activeObject; - - if (!selection || !(selection is NavmeshBuild)) - return; - - NavmeshBuild build = (NavmeshBuild)selection; - - if (build.BuildType != NavmeshBuildType.Advanced) - return; - - BuildSelector.Instance.Select(build); - } - - internal static void ForceProcessorReset() - { - ClearProcessor(); - SetProcessor(); - } - - /// - /// Opens and focus' the build manager window. - /// - [MenuItem(EditorUtil.MainMenu + "Navmesh Build Manager", false, EditorUtil.ManagerGroup)] - public static void OpenWindow() - { - NavmeshBuildManager window = EditorWindow.GetWindow(false - , WindowTitle); - - window.Show(); - window.Focus(); - } -} diff --git a/critterai/.svn/pristine/c6/c6e27e8df937d19f0014f738125009939bb92f7d.svn-base b/critterai/.svn/pristine/c6/c6e27e8df937d19f0014f738125009939bb92f7d.svn-base deleted file mode 100644 index e5b6f691..00000000 Binary files a/critterai/.svn/pristine/c6/c6e27e8df937d19f0014f738125009939bb92f7d.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/c7/c7060076f09016f634a4d6542a8d28ec681be771.svn-base b/critterai/.svn/pristine/c7/c7060076f09016f634a4d6542a8d28ec681be771.svn-base deleted file mode 100644 index a9032e1c..00000000 --- a/critterai/.svn/pristine/c7/c7060076f09016f634a4d6542a8d28ec681be771.svn-base +++ /dev/null @@ -1,1120 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef RECAST_H -#define RECAST_H - -/// The value of PI used by Recast. -static const float RC_PI = 3.14159265f; - -/// Recast log categories. -/// @see rcContext -enum rcLogCategory -{ - RC_LOG_PROGRESS = 1, ///< A progress log entry. - RC_LOG_WARNING, ///< A warning log entry. - RC_LOG_ERROR, ///< An error log entry. -}; - -/// Recast performance timer categories. -/// @see rcContext -enum rcTimerLabel -{ - /// The user defined total time of the build. - RC_TIMER_TOTAL, - /// A user defined build time. - RC_TIMER_TEMP, - /// The time to rasterize the triangles. (See: #rcRasterizeTriangle) - RC_TIMER_RASTERIZE_TRIANGLES, - /// The time to build the compact heightfield. (See: #rcBuildCompactHeightfield) - RC_TIMER_BUILD_COMPACTHEIGHTFIELD, - /// The total time to build the contours. (See: #rcBuildContours) - RC_TIMER_BUILD_CONTOURS, - /// The time to trace the boundaries of the contours. (See: #rcBuildContours) - RC_TIMER_BUILD_CONTOURS_TRACE, - /// The time to simplify the contours. (See: #rcBuildContours) - RC_TIMER_BUILD_CONTOURS_SIMPLIFY, - /// The time to filter ledge spans. (See: #rcFilterLedgeSpans) - RC_TIMER_FILTER_BORDER, - /// The time to filter low height spans. (See: #rcFilterWalkableLowHeightSpans) - RC_TIMER_FILTER_WALKABLE, - /// The time to apply the median filter. (See: #rcMedianFilterWalkableArea) - RC_TIMER_MEDIAN_AREA, - /// The time to filter low obstacles. (See: #rcFilterLowHangingWalkableObstacles) - RC_TIMER_FILTER_LOW_OBSTACLES, - /// The time to build the polygon mesh. (See: #rcBuildPolyMesh) - RC_TIMER_BUILD_POLYMESH, - /// The time to merge polygon meshes. (See: #rcMergePolyMeshes) - RC_TIMER_MERGE_POLYMESH, - /// The time to erode the walkable area. (See: #rcErodeWalkableArea) - RC_TIMER_ERODE_AREA, - /// The time to mark a box area. (See: #rcMarkBoxArea) - RC_TIMER_MARK_BOX_AREA, - /// The time to mark a cylinder area. (See: #rcMarkCylinderArea) - RC_TIMER_MARK_CYLINDER_AREA, - /// The time to mark a convex polygon area. (See: #rcMarkConvexPolyArea) - RC_TIMER_MARK_CONVEXPOLY_AREA, - /// The total time to build the distance field. (See: #rcBuildDistanceField) - RC_TIMER_BUILD_DISTANCEFIELD, - /// The time to build the distances of the distance field. (See: #rcBuildDistanceField) - RC_TIMER_BUILD_DISTANCEFIELD_DIST, - /// The time to blur the distance field. (See: #rcBuildDistanceField) - RC_TIMER_BUILD_DISTANCEFIELD_BLUR, - /// The total time to build the regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone) - RC_TIMER_BUILD_REGIONS, - /// The total time to apply the watershed algorithm. (See: #rcBuildRegions) - RC_TIMER_BUILD_REGIONS_WATERSHED, - /// The time to expand regions while applying the watershed algorithm. (See: #rcBuildRegions) - RC_TIMER_BUILD_REGIONS_EXPAND, - /// The time to flood regions while applying the watershed algorithm. (See: #rcBuildRegions) - RC_TIMER_BUILD_REGIONS_FLOOD, - /// The time to filter out small regions. (See: #rcBuildRegions, #rcBuildRegionsMonotone) - RC_TIMER_BUILD_REGIONS_FILTER, - /// The time to build heightfield layers. (See: #rcBuildHeightfieldLayers) - RC_TIMER_BUILD_LAYERS, - /// The time to build the polygon mesh detail. (See: #rcBuildPolyMeshDetail) - RC_TIMER_BUILD_POLYMESHDETAIL, - /// The time to merge polygon mesh details. (See: #rcMergePolyMeshDetails) - RC_TIMER_MERGE_POLYMESHDETAIL, - /// The maximum number of timers. (Used for iterating timers.) - RC_MAX_TIMERS -}; - -/// Provides an interface for optional logging and performance tracking of the Recast -/// build process. -/// @ingroup recast -class rcContext -{ -public: - - /// Contructor. - /// @param[in] state TRUE if the logging and performance timers should be enabled. [Default: true] - inline rcContext(bool state = true) : m_logEnabled(state), m_timerEnabled(state) {} - virtual ~rcContext() {} - - /// Enables or disables logging. - /// @param[in] state TRUE if logging should be enabled. - inline void enableLog(bool state) { m_logEnabled = state; } - - /// Clears all log entries. - inline void resetLog() { if (m_logEnabled) doResetLog(); } - - /// Logs a message. - /// @param[in] category The category of the message. - /// @param[in] format The message. - void log(const rcLogCategory category, const char* format, ...); - - /// Enables or disables the performance timers. - /// @param[in] state TRUE if timers should be enabled. - inline void enableTimer(bool state) { m_timerEnabled = state; } - - /// Clears all peformance timers. (Resets all to unused.) - inline void resetTimers() { if (m_timerEnabled) doResetTimers(); } - - /// Starts the specified performance timer. - /// @param label The category of timer. - inline void startTimer(const rcTimerLabel label) { if (m_timerEnabled) doStartTimer(label); } - - /// Stops the specified performance timer. - /// @param label The category of the timer. - inline void stopTimer(const rcTimerLabel label) { if (m_timerEnabled) doStopTimer(label); } - - /// Returns the total accumulated time of the specified performance timer. - /// @param label The category of the timer. - /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started. - inline int getAccumulatedTime(const rcTimerLabel label) const { return m_timerEnabled ? doGetAccumulatedTime(label) : -1; } - -protected: - - /// Clears all log entries. - virtual void doResetLog() {} - - /// Logs a message. - /// @param[in] category The category of the message. - /// @param[in] msg The formatted message. - /// @param[in] len The length of the formatted message. - virtual void doLog(const rcLogCategory /*category*/, const char* /*msg*/, const int /*len*/) {} - - /// Clears all timers. (Resets all to unused.) - virtual void doResetTimers() {} - - /// Starts the specified performance timer. - /// @param[in] label The category of timer. - virtual void doStartTimer(const rcTimerLabel /*label*/) {} - - /// Stops the specified performance timer. - /// @param[in] label The category of the timer. - virtual void doStopTimer(const rcTimerLabel /*label*/) {} - - /// Returns the total accumulated time of the specified performance timer. - /// @param[in] label The category of the timer. - /// @return The accumulated time of the timer, or -1 if timers are disabled or the timer has never been started. - virtual int doGetAccumulatedTime(const rcTimerLabel /*label*/) const { return -1; } - - /// True if logging is enabled. - bool m_logEnabled; - - /// True if the performance timers are enabled. - bool m_timerEnabled; -}; - -/// Specifies a configuration to use when performing Recast builds. -/// @ingroup recast -struct rcConfig -{ - /// The width of the field along the x-axis. [Limit: >= 0] [Units: vx] - int width; - - /// The height of the field along the z-axis. [Limit: >= 0] [Units: vx] - int height; - - /// The width/height size of tile's on the xz-plane. [Limit: >= 0] [Units: vx] - int tileSize; - - /// The size of the non-navigable border around the heightfield. [Limit: >=0] [Units: vx] - int borderSize; - - /// The xz-plane cell size to use for fields. [Limit: > 0] [Units: wu] - float cs; - - /// The y-axis cell size to use for fields. [Limit: > 0] [Units: wu] - float ch; - - /// The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] - float bmin[3]; - - /// The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] - float bmax[3]; - - /// The maximum slope that is considered walkable. [Limits: 0 <= value < 90] [Units: Degrees] - float walkableSlopeAngle; - - /// Minimum floor to 'ceiling' height that will still allow the floor area to - /// be considered walkable. [Limit: >= 3] [Units: vx] - int walkableHeight; - - /// Maximum ledge height that is considered to still be traversable. [Limit: >=0] [Units: vx] - int walkableClimb; - - /// The distance to erode/shrink the walkable area of the heightfield away from - /// obstructions. [Limit: >=0] [Units: vx] - int walkableRadius; - - /// The maximum allowed length for contour edges along the border of the mesh. [Limit: >=0] [Units: vx] - int maxEdgeLen; - - /// The maximum distance a simplfied contour's border edges should deviate - /// the original raw contour. [Limit: >=0] [Units: wu] - float maxSimplificationError; - - /// The minimum number of cells allowed to form isolated island areas. [Limit: >=0] [Units: vx] - int minRegionArea; - - /// Any regions with a span count smaller than this value will, if possible, - /// be merged with larger regions. [Limit: >=0] [Units: vx] - int mergeRegionArea; - - /// The maximum number of vertices allowed for polygons generated during the - /// contour to polygon conversion process. [Limit: >= 3] - int maxVertsPerPoly; - - /// Sets the sampling distance to use when generating the detail mesh. - /// (For height detail only.) [Limits: 0 or >= 0.9] [Units: wu] - float detailSampleDist; - - /// The maximum distance the detail mesh surface should deviate from heightfield - /// data. (For height detail only.) [Limit: >=0] [Units: wu] - float detailSampleMaxError; -}; - -/// Defines the number of bits allocated to rcSpan::smin and rcSpan::smax. -static const int RC_SPAN_HEIGHT_BITS = 13; -/// Defines the maximum value for rcSpan::smin and rcSpan::smax. -static const int RC_SPAN_MAX_HEIGHT = (1< inline void rcSwap(T& a, T& b) { T t = a; a = b; b = t; } - -/// Returns the minimum of two values. -/// @param[in] a Value A -/// @param[in] b Value B -/// @return The minimum of the two values. -template inline T rcMin(T a, T b) { return a < b ? a : b; } - -/// Returns the maximum of two values. -/// @param[in] a Value A -/// @param[in] b Value B -/// @return The maximum of the two values. -template inline T rcMax(T a, T b) { return a > b ? a : b; } - -/// Returns the absolute value. -/// @param[in] a The value. -/// @return The absolute value of the specified value. -template inline T rcAbs(T a) { return a < 0 ? -a : a; } - -/// Returns the square of the value. -/// @param[in] a The value. -/// @return The square of the value. -template inline T rcSqr(T a) { return a*a; } - -/// Clamps the value to the specified range. -/// @param[in] v The value to clamp. -/// @param[in] mn The minimum permitted return value. -/// @param[in] mx The maximum permitted return value. -/// @return The value, clamped to the specified range. -template inline T rcClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } - -/// Returns the square root of the value. -/// @param[in] x The value. -/// @return The square root of the vlaue. -float rcSqrt(float x); - -/// @} -/// @name Vector helper functions. -/// @{ - -/// Derives the cross product of two vectors. (@p v1 x @p v2) -/// @param[out] dest The cross product. [(x, y, z)] -/// @param[in] v1 A Vector [(x, y, z)] -/// @param[in] v2 A vector [(x, y, z)] -inline void rcVcross(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; - dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; - dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -/// Derives the dot product of two vectors. (@p v1 . @p v2) -/// @param[in] v1 A Vector [(x, y, z)] -/// @param[in] v2 A vector [(x, y, z)] -/// @return The dot product. -inline float rcVdot(const float* v1, const float* v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s)) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)] -/// @param[in] s The amount to scale @p v2 by before adding to @p v1. -inline void rcVmad(float* dest, const float* v1, const float* v2, const float s) -{ - dest[0] = v1[0]+v2[0]*s; - dest[1] = v1[1]+v2[1]*s; - dest[2] = v1[2]+v2[2]*s; -} - -/// Performs a vector addition. (@p v1 + @p v2) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to add to @p v1. [(x, y, z)] -inline void rcVadd(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]+v2[0]; - dest[1] = v1[1]+v2[1]; - dest[2] = v1[2]+v2[2]; -} - -/// Performs a vector subtraction. (@p v1 - @p v2) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)] -inline void rcVsub(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]-v2[0]; - dest[1] = v1[1]-v2[1]; - dest[2] = v1[2]-v2[2]; -} - -/// Selects the minimum value of each element from the specified vectors. -/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)] -/// @param[in] v A vector. [(x, y, z)] -inline void rcVmin(float* mn, const float* v) -{ - mn[0] = rcMin(mn[0], v[0]); - mn[1] = rcMin(mn[1], v[1]); - mn[2] = rcMin(mn[2], v[2]); -} - -/// Selects the maximum value of each element from the specified vectors. -/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)] -/// @param[in] v A vector. [(x, y, z)] -inline void rcVmax(float* mx, const float* v) -{ - mx[0] = rcMax(mx[0], v[0]); - mx[1] = rcMax(mx[1], v[1]); - mx[2] = rcMax(mx[2], v[2]); -} - -/// Performs a vector copy. -/// @param[out] dest The result. [(x, y, z)] -/// @param[in] v The vector to copy. [(x, y, z)] -inline void rcVcopy(float* dest, const float* v) -{ - dest[0] = v[0]; - dest[1] = v[1]; - dest[2] = v[2]; -} - -/// Returns the distance between two points. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The distance between the two points. -inline float rcVdist(const float* v1, const float* v2) -{ - float dx = v2[0] - v1[0]; - float dy = v2[1] - v1[1]; - float dz = v2[2] - v1[2]; - return rcSqrt(dx*dx + dy*dy + dz*dz); -} - -/// Returns the square of the distance between two points. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The square of the distance between the two points. -inline float rcVdistSqr(const float* v1, const float* v2) -{ - float dx = v2[0] - v1[0]; - float dy = v2[1] - v1[1]; - float dz = v2[2] - v1[2]; - return dx*dx + dy*dy + dz*dz; -} - -/// Normalizes the vector. -/// @param[in,out] v The vector to normalize. [(x, y, z)] -inline void rcVnormalize(float* v) -{ - float d = 1.0f / rcSqrt(rcSqr(v[0]) + rcSqr(v[1]) + rcSqr(v[2])); - v[0] *= d; - v[1] *= d; - v[2] *= d; -} - -/// @} -/// @name Heightfield Functions -/// @see rcHeightfield -/// @{ - -/// Calculates the bounding box of an array of vertices. -/// @ingroup recast -/// @param[in] verts An array of vertices. [(x, y, z) * @p nv] -/// @param[in] nv The number of vertices in the @p verts array. -/// @param[out] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu] -/// @param[out] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu] -void rcCalcBounds(const float* verts, int nv, float* bmin, float* bmax); - -/// Calculates the grid size based on the bounding box and grid cell size. -/// @ingroup recast -/// @param[in] bmin The minimum bounds of the AABB. [(x, y, z)] [Units: wu] -/// @param[in] bmax The maximum bounds of the AABB. [(x, y, z)] [Units: wu] -/// @param[in] cs The xz-plane cell size. [Limit: > 0] [Units: wu] -/// @param[out] w The width along the x-axis. [Limit: >= 0] [Units: vx] -/// @param[out] h The height along the z-axis. [Limit: >= 0] [Units: vx] -void rcCalcGridSize(const float* bmin, const float* bmax, float cs, int* w, int* h); - -/// Initializes a new heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in,out] hf The allocated heightfield to initialize. -/// @param[in] width The width of the field along the x-axis. [Limit: >= 0] [Units: vx] -/// @param[in] height The height of the field along the z-axis. [Limit: >= 0] [Units: vx] -/// @param[in] bmin The minimum bounds of the field's AABB. [(x, y, z)] [Units: wu] -/// @param[in] bmax The maximum bounds of the field's AABB. [(x, y, z)] [Units: wu] -/// @param[in] cs The xz-plane cell size to use for the field. [Limit: > 0] [Units: wu] -/// @param[in] ch The y-axis cell size to use for field. [Limit: > 0] [Units: wu] -bool rcCreateHeightfield(rcContext* ctx, rcHeightfield& hf, int width, int height, - const float* bmin, const float* bmax, - float cs, float ch); - -/// Sets the area id of all triangles with a slope below the specified value -/// to #RC_WALKABLE_AREA. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable. -/// [Limits: 0 <= value < 90] [Units: Degrees] -/// @param[in] verts The vertices. [(x, y, z) * @p nv] -/// @param[in] nv The number of vertices. -/// @param[in] tris The triangle vertex indices. [(vertA, vertB, vertC) * @p nt] -/// @param[in] nt The number of triangles. -/// @param[out] areas The triangle area ids. [Length: >= @p nt] -void rcMarkWalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, - const int* tris, int nt, unsigned char* areas); - -/// Sets the area id of all triangles with a slope greater than or equal to the specified value to #RC_NULL_AREA. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableSlopeAngle The maximum slope that is considered walkable. -/// [Limits: 0 <= value < 90] [Units: Degrees] -/// @param[in] verts The vertices. [(x, y, z) * @p nv] -/// @param[in] nv The number of vertices. -/// @param[in] tris The triangle vertex indices. [(vertA, vertB, vertC) * @p nt] -/// @param[in] nt The number of triangles. -/// @param[out] areas The triangle area ids. [Length: >= @p nt] -void rcClearUnwalkableTriangles(rcContext* ctx, const float walkableSlopeAngle, const float* verts, int nv, - const int* tris, int nt, unsigned char* areas); - -/// Adds a span to the specified heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in,out] hf An initialized heightfield. -/// @param[in] x The width index where the span is to be added. -/// [Limits: 0 <= value < rcHeightfield::width] -/// @param[in] y The height index where the span is to be added. -/// [Limits: 0 <= value < rcHeightfield::height] -/// @param[in] smin The minimum height of the span. [Limit: < @p smax] [Units: vx] -/// @param[in] smax The maximum height of the span. [Limit: <= #RC_SPAN_MAX_HEIGHT] [Units: vx] -/// @param[in] area The area id of the span. [Limit: <= #RC_WALKABLE_AREA) -/// @param[in] flagMergeThr The merge theshold. [Limit: >= 0] [Units: vx] -void rcAddSpan(rcContext* ctx, rcHeightfield& hf, const int x, const int y, - const unsigned short smin, const unsigned short smax, - const unsigned char area, const int flagMergeThr); - -/// Rasterizes a triangle into the specified heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] v0 Triangle vertex 0 [(x, y, z)] -/// @param[in] v1 Triangle vertex 1 [(x, y, z)] -/// @param[in] v2 Triangle vertex 2 [(x, y, z)] -/// @param[in] area The area id of the triangle. [Limit: <= #RC_WALKABLE_AREA] -/// @param[in,out] solid An initialized heightfield. -/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. -/// [Limit: >= 0] [Units: vx] -void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, - const unsigned char area, rcHeightfield& solid, - const int flagMergeThr = 1); - -/// Rasterizes an indexed triangle mesh into the specified heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] verts The vertices. [(x, y, z) * @p nv] -/// @param[in] nv The number of vertices. -/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt] -/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] -/// @param[in] nt The number of triangles. -/// @param[in,out] solid An initialized heightfield. -/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. -/// [Limit: >= 0] [Units: vx] -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, - const int* tris, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr = 1); - -/// Rasterizes an indexed triangle mesh into the specified heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] verts The vertices. [(x, y, z) * @p nv] -/// @param[in] nv The number of vertices. -/// @param[in] tris The triangle indices. [(vertA, vertB, vertC) * @p nt] -/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] -/// @param[in] nt The number of triangles. -/// @param[in,out] solid An initialized heightfield. -/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. -/// [Limit: >= 0] [Units: vx] -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int nv, - const unsigned short* tris, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr = 1); - -/// Rasterizes triangles into the specified heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] verts The triangle vertices. [(ax, ay, az, bx, by, bz, cx, by, cx) * @p nt] -/// @param[in] areas The area id's of the triangles. [Limit: <= #RC_WALKABLE_AREA] [Size: @p nt] -/// @param[in] nt The number of triangles. -/// @param[in,out] solid An initialized heightfield. -/// @param[in] flagMergeThr The distance where the walkable flag is favored over the non-walkable flag. -/// [Limit: >= 0] [Units: vx] -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr = 1); - -/// Marks non-walkable spans as walkable if their maximum is within @p walkableClimp of a walkable neihbor. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. -/// [Limit: >=0] [Units: vx] -/// @param[in,out] solid A fully built heightfield. (All spans have been added.) -void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid); - -/// Marks spans that are ledges as not-walkable. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to -/// be considered walkable. [Limit: >= 3] [Units: vx] -/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. -/// [Limit: >=0] [Units: vx] -/// @param[in,out] solid A fully built heightfield. (All spans have been added.) -void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, - const int walkableClimb, rcHeightfield& solid); - -/// Marks walkable spans as not walkable if the clearence above the span is less than the specified height. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area to -/// be considered walkable. [Limit: >= 3] [Units: vx] -/// @param[in,out] solid A fully built heightfield. (All spans have been added.) -void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid); - -/// Returns the number of spans contained in the specified heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] hf An initialized heightfield. -/// @returns The number of spans in the heightfield. -int rcGetHeightFieldSpanCount(rcContext* ctx, rcHeightfield& hf); - -/// @} -/// @name Compact Heightfield Functions -/// @see rcCompactHeightfield -/// @{ - -/// Builds a compact heightfield representing open space, from a heightfield representing solid space. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area -/// to be considered walkable. [Limit: >= 3] [Units: vx] -/// @param[in] walkableClimb Maximum ledge height that is considered to still be traversable. -/// [Limit: >=0] [Units: vx] -/// @param[in] hf The heightfield to be compacted. -/// @param[out] chf The resulting compact heightfield. (Must be pre-allocated.) -/// @returns True if the operation completed successfully. -bool rcBuildCompactHeightfield(rcContext* ctx, const int walkableHeight, const int walkableClimb, - rcHeightfield& hf, rcCompactHeightfield& chf); - -/// Erodes the walkable area within the heightfield by the specified radius. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] radius The radius of erosion. [Limits: 0 < value < 255] [Units: vx] -/// @param[in,out] chf The populated compact heightfield to erode. -/// @returns True if the operation completed successfully. -bool rcErodeWalkableArea(rcContext* ctx, int radius, rcCompactHeightfield& chf); - -/// Applies a median filter to walkable area types (based on area id), removing noise. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in,out] chf A populated compact heightfield. -/// @returns True if the operation completed successfully. -bool rcMedianFilterWalkableArea(rcContext* ctx, rcCompactHeightfield& chf); - -/// Applies an area id to all spans within the specified bounding box. (AABB) -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] bmin The minimum of the bounding box. [(x, y, z)] -/// @param[in] bmax The maximum of the bounding box. [(x, y, z)] -/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA] -/// @param[in,out] chf A populated compact heightfield. -void rcMarkBoxArea(rcContext* ctx, const float* bmin, const float* bmax, unsigned char areaId, - rcCompactHeightfield& chf); - -/// Applies the area id to the all spans within the specified convex polygon. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] verts The vertices of the polygon [Fomr: (x, y, z) * @p nverts] -/// @param[in] nverts The number of vertices in the polygon. -/// @param[in] hmin The height of the base of the polygon. -/// @param[in] hmax The height of the top of the polygon. -/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA] -/// @param[in,out] chf A populated compact heightfield. -void rcMarkConvexPolyArea(rcContext* ctx, const float* verts, const int nverts, - const float hmin, const float hmax, unsigned char areaId, - rcCompactHeightfield& chf); - -/// Applies the area id to all spans within the specified cylinder. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] pos The center of the base of the cylinder. [Form: (x, y, z)] -/// @param[in] r The radius of the cylinder. -/// @param[in] h The height of the cylinder. -/// @param[in] areaId The area id to apply. [Limit: <= #RC_WALKABLE_AREA] -/// @param[in,out] chf A populated compact heightfield. -void rcMarkCylinderArea(rcContext* ctx, const float* pos, - const float r, const float h, unsigned char areaId, - rcCompactHeightfield& chf); - -/// Builds the distance field for the specified compact heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in,out] chf A populated compact heightfield. -/// @returns True if the operation completed successfully. -bool rcBuildDistanceField(rcContext* ctx, rcCompactHeightfield& chf); - -/// Builds region data for the heightfield using watershed partitioning. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in,out] chf A populated compact heightfield. -/// @param[in] borderSize The size of the non-navigable border around the heightfield. -/// [Limit: >=0] [Units: vx] -/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas. -/// [Limit: >=0] [Units: vx]. -/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible, -/// be merged with larger regions. [Limit: >=0] [Units: vx] -/// @returns True if the operation completed successfully. -bool rcBuildRegions(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int minRegionArea, const int mergeRegionArea); - -/// Builds region data for the heightfield using simple monotone partitioning. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in,out] chf A populated compact heightfield. -/// @param[in] borderSize The size of the non-navigable border around the heightfield. -/// [Limit: >=0] [Units: vx] -/// @param[in] minRegionArea The minimum number of cells allowed to form isolated island areas. -/// [Limit: >=0] [Units: vx]. -/// @param[in] mergeRegionArea Any regions with a span count smaller than this value will, if possible, -/// be merged with larger regions. [Limit: >=0] [Units: vx] -/// @returns True if the operation completed successfully. -bool rcBuildRegionsMonotone(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int minRegionArea, const int mergeRegionArea); - - -/// Sets the neighbor connection data for the specified direction. -/// @param[in] s The span to update. -/// @param[in] dir The direction to set. [Limits: 0 <= value < 4] -/// @param[in] i The index of the neighbor span. -inline void rcSetCon(rcCompactSpan& s, int dir, int i) -{ - const unsigned int shift = (unsigned int)dir*6; - unsigned int con = s.con; - s.con = (con & ~(0x3f << shift)) | (((unsigned int)i & 0x3f) << shift); -} - -/// Gets neighbor connection data for the specified direction. -/// @param[in] s The span to check. -/// @param[in] dir The direction to check. [Limits: 0 <= value < 4] -/// @return The neighbor connection data for the specified direction, -/// or #RC_NOT_CONNECTED if there is no connection. -inline int rcGetCon(const rcCompactSpan& s, int dir) -{ - const unsigned int shift = (unsigned int)dir*6; - return (s.con >> shift) & 0x3f; -} - -/// Gets the standard width (x-axis) offset for the specified direction. -/// @param[in] dir The direction. [Limits: 0 <= value < 4] -/// @return The width offset to apply to the current cell position to move -/// in the direction. -inline int rcGetDirOffsetX(int dir) -{ - const int offset[4] = { -1, 0, 1, 0, }; - return offset[dir&0x03]; -} - -/// Gets the standard height (z-axis) offset for the specified direction. -/// @param[in] dir The direction. [Limits: 0 <= value < 4] -/// @return The height offset to apply to the current cell position to move -/// in the direction. -inline int rcGetDirOffsetY(int dir) -{ - const int offset[4] = { 0, 1, 0, -1 }; - return offset[dir&0x03]; -} - -/// @} -/// @name Layer, Contour, Polymesh, and Detail Mesh Functions -/// @see rcHeightfieldLayer, rcContourSet, rcPolyMesh, rcPolyMeshDetail -/// @{ - -/// Builds a layer set from the specified compact heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] chf A fully built compact heightfield. -/// @param[in] borderSize The size of the non-navigable border around the heightfield. [Limit: >=0] -/// [Units: vx] -/// @param[in] walkableHeight Minimum floor to 'ceiling' height that will still allow the floor area -/// to be considered walkable. [Limit: >= 3] [Units: vx] -/// @param[out] lset The resulting layer set. (Must be pre-allocated.) -/// @returns True if the operation completed successfully. -bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int walkableHeight, - rcHeightfieldLayerSet& lset); - -/// Builds a contour set from the region outlines in the provided compact heightfield. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] chf A fully built compact heightfield. -/// @param[in] maxError The maximum distance a simplfied contour's border edges should deviate -/// the original raw contour. [Limit: >=0] [Units: wu] -/// @param[in] maxEdgeLen The maximum allowed length for contour edges along the border of the mesh. -/// [Limit: >=0] [Units: vx] -/// @param[out] cset The resulting contour set. (Must be pre-allocated.) -/// @param[in] buildFlags The build flags. (See: #rcBuildContoursFlags) -/// @returns True if the operation completed successfully. -bool rcBuildContours(rcContext* ctx, rcCompactHeightfield& chf, - const float maxError, const int maxEdgeLen, - rcContourSet& cset, const int flags = RC_CONTOUR_TESS_WALL_EDGES); - -/// Builds a polygon mesh from the provided contours. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] cset A fully built contour set. -/// @param[in] nvp The maximum number of vertices allowed for polygons generated during the -/// contour to polygon conversion process. [Limit: >= 3] -/// @param[out] mesh The resulting polygon mesh. (Must be re-allocated.) -/// @returns True if the operation completed successfully. -bool rcBuildPolyMesh(rcContext* ctx, rcContourSet& cset, const int nvp, rcPolyMesh& mesh); - -/// Merges multiple polygon meshes into a single mesh. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] meshes An array of polygon meshes to merge. [Size: @p nmeshes] -/// @param[in] nmeshes The number of polygon meshes in the meshes array. -/// @param[in] mesh The resulting polygon mesh. (Must be pre-allocated.) -/// @returns True if the operation completed successfully. -bool rcMergePolyMeshes(rcContext* ctx, rcPolyMesh** meshes, const int nmeshes, rcPolyMesh& mesh); - -/// Builds a detail mesh from the provided polygon mesh. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] mesh A fully built polygon mesh. -/// @param[in] chf The compact heightfield used to build the polygon mesh. -/// @param[in] sampleDist Sets the distance to use when samping the heightfield. [Limit: >=0] [Units: wu] -/// @param[in] sampleMaxError The maximum distance the detail mesh surface should deviate from -/// heightfield data. [Limit: >=0] [Units: wu] -/// @param[out] dmesh The resulting detail mesh. (Must be pre-allocated.) -/// @returns True if the operation completed successfully. -bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf, - const float sampleDist, const float sampleMaxError, - rcPolyMeshDetail& dmesh); - -/// Copies the poly mesh data from src to dst. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] src The source mesh to copy from. -/// @param[out] dst The resulting detail mesh. (Must be pre-allocated, must be empty mesh.) -/// @returns True if the operation completed successfully. -bool rcCopyPolyMesh(rcContext* ctx, const rcPolyMesh& src, rcPolyMesh& dst); - -/// Merges multiple detail meshes into a single detail mesh. -/// @ingroup recast -/// @param[in,out] ctx The build context to use during the operation. -/// @param[in] meshes An array of detail meshes to merge. [Size: @p nmeshes] -/// @param[in] nmeshes The number of detail meshes in the meshes array. -/// @param[out] mesh The resulting detail mesh. (Must be pre-allocated.) -/// @returns True if the operation completed successfully. -bool rcMergePolyMeshDetails(rcContext* ctx, rcPolyMeshDetail** meshes, const int nmeshes, rcPolyMeshDetail& mesh); - -/// @} - -#endif // RECAST_H - -/////////////////////////////////////////////////////////////////////////// - -// Due to the large amount of detail documentation for this file, -// the content normally located at the end of the header file has been separated -// out to a file in /Docs/Extern. diff --git a/critterai/.svn/pristine/c7/c74e89b910b63164b91c46748ea30d40fa01208d.svn-base b/critterai/.svn/pristine/c7/c74e89b910b63164b91c46748ea30d40fa01208d.svn-base deleted file mode 100644 index 10043011..00000000 --- a/critterai/.svn/pristine/c7/c74e89b910b63164b91c46748ea30d40fa01208d.svn-base +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - internal abstract class BuildControl - : IBuildControl - { - private ControlContext mContext; - private DebugViewContext mDebugContext; - private readonly UnityBuildContext mLogger = new UnityBuildContext(); - - protected UnityBuildContext Logger { get { return mLogger; } } - protected ControlContext Context { get { return mContext; } } - protected DebugViewContext DebugContext { get { return mDebugContext; } } - - public bool IsActive { get { return (mContext != null); } } - - public virtual bool Enter(ControlContext context, DebugViewContext debug) - { - if (mContext != null || context == null || !context.Build || debug == null) - // Strict. - return false; - - mContext = context; - mDebugContext = debug; - - return true; - } - - public virtual void Exit() - { - mContext = null; - mDebugContext = null; - mLogger.ResetLog(); - } - - public virtual void Update() { } - - public void OnGUI() - { - if (mContext == null) - return; - - if (!mContext.HideMain) - OnGUIMain(); - - OnGUIButtons(); - } - - protected abstract void OnGUIMain(); - protected abstract void OnGUIButtons(); - } -} diff --git a/critterai/.svn/pristine/c7/c7ba9827b3b27e661b4ab31474c94ddb81b4b78a.svn-base b/critterai/.svn/pristine/c7/c7ba9827b3b27e661b4ab31474c94ddb81b4b78a.svn-base deleted file mode 100644 index 5a14883f..00000000 --- a/critterai/.svn/pristine/c7/c7ba9827b3b27e661b4ab31474c94ddb81b4b78a.svn-base +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nav; -using org.critterai.nmgen; -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// Undocumented class meant for internal use only. (Editor Only) - /// - [System.Serializable] - public sealed class TileBuildData - { - /* - * Design note: - * - * The strange design is due to the need to support Unity serialization. - */ - - internal const int IndexError = -1; - - /// - /// Undocumented. - /// - public BuildDataItem[] unsafeItems; - - /// - /// Undocumented. - /// - public int unsafeWidth; - - /// - /// Undocumented. - /// - public int unsafeDepth; - - /// - /// Undocumented. - /// - public int unsafeVersion = 0; - - private bool mIsDirty; - - internal bool IsDirty - { - get { return mIsDirty; } - set { mIsDirty = value; } - } - - /// - /// Undocumented. - /// - internal int Version { get { return unsafeVersion; } } - - /// - /// Undocumented. - /// - internal int Width { get { return unsafeWidth; } } - - /// - /// Undocumented. - /// - internal int Depth { get { return unsafeDepth; } } - - /// - /// Undocumented. - /// - internal bool IsTiled { get { return unsafeDepth > 1 || unsafeWidth > 1; } } - - /// - /// Undocumented. - /// - internal bool IsValid - { - get { return (unsafeDepth > 0 && unsafeWidth > 0); } - } - - - internal TileBuildData(int width, int depth) - { - Resize(width, depth); - } - - /// - /// Undocumented. - /// - internal TileBuildData() - { - unsafeWidth = 0; - unsafeDepth = 0; - unsafeItems = new BuildDataItem[0]; - } - - internal void Resize(int width, int depth) - { - unsafeWidth = System.Math.Max(0, width); - unsafeDepth = System.Math.Max(0, depth); - unsafeItems = new BuildDataItem[unsafeWidth * unsafeDepth]; - - for (int tx = 0; tx < unsafeWidth; tx++) - { - for (int tz = 0; tz < unsafeDepth; tz++) - { - unsafeItems[GetIndex(tx, tz)] = new BuildDataItem(tx, tz); - } - } - - mIsDirty = true; - unsafeVersion++; - } - - internal int GetStateCount(TileBuildState state) - { - int result = 0; - foreach (BuildDataItem item in unsafeItems) - { - if (item.TileState == state) - result++; - } - return result; - } - - /// - /// The number of tiles that contain data that can be baked. - /// - /// The number of tiles that contain data that can be baked. - internal int BakeableCount() - { - int result = 0; - foreach (BuildDataItem item in unsafeItems) - { - TileBuildState bstate = item.TileState; - if (bstate == TileBuildState.Built || bstate == TileBuildState.Baked) - result++; - } - - return result; - } - - /// - /// The number of tiles that contain data that can be baked. - /// - /// The number of tiles that contain data that can be baked. - /// The maximum polygons contained by any bakeable tile. - internal void BakeableCount(out int readyToBake, out int maxTilePolys) - { - readyToBake = 0; - maxTilePolys = 0; - foreach (BuildDataItem item in unsafeItems) - { - switch (item.TileState) - { - case TileBuildState.Built: - - readyToBake++; - maxTilePolys = - System.Math.Max(item.workingPolyCount, maxTilePolys); - - break; - - case TileBuildState.Baked: - - readyToBake++; - maxTilePolys = - System.Math.Max(item.bakedPolyCount, maxTilePolys); - - break; - - } - } - } - - internal TileBuildState GetState(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return TileBuildState.Error; - - return unsafeItems[i].TileState; - } - - internal NavmeshTileData GetTileData(int x, int z) - { - int trash; - return GetTileData(x, z, out trash); - } - - internal NavmeshTileData GetTileData(int x, int z, out int polyCount) - { - polyCount = 0; - - int i = GetIndex(x, z); - if (i == IndexError) - return null; - - BuildDataItem item = unsafeItems[i]; - - /* - * Important: Must use the state. This method must return - * the same number of tiles as the BakeableCount method indicates. - */ - - switch (item.TileState) - { - case TileBuildState.Built: - - polyCount = item.workingPolyCount; - return NavmeshTileData.Create(item.workingTile); - - case TileBuildState.Baked: - - polyCount = item.bakedPolyCount; - return NavmeshTileData.Create(item.bakedTile); - } - - polyCount = 0; - return null; - } - - // This method indicates only that there are tiles that are - // no longer in their base state. It doesn't mean that there is - // anything that can be baked. (All tiles may be empty.) - internal int NeedsBakingCount() - { - int result = 0; - - foreach (BuildDataItem item in unsafeItems) - { - TileBuildState ts = item.TileState; - result += (ts == TileBuildState.Built || ts == TileBuildState.Empty) - ? 1 : 0; - } - - return result; - } - - internal int GetActive() - { - int result = 0; - - foreach (BuildDataItem item in unsafeItems) - { - TileBuildState ts = item.TileState; - result += (ts == TileBuildState.InProgress - || ts == TileBuildState.Queued) ? 1 : 0; - } - - return result; - } - - internal void ClearUnbaked(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].ClearUnbaked(); - - mIsDirty = true; - unsafeVersion++; - } - - internal void SetAsEmpty(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].SetAsEmpty(); - - mIsDirty = true; - unsafeVersion++; - } - - internal void SetAsFailed(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].SetAsFailed(); - - mIsDirty = true; - unsafeVersion++; - } - - internal void SetAsQueued(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].SetAsQueued(); - - mIsDirty = true; - unsafeVersion++; - } - - internal void SetAsInProgress(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].SetAsInProgress(); - - mIsDirty = true; - unsafeVersion++; - } - - internal PolyMesh GetPolyMesh(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return null; - - BuildDataItem item = unsafeItems[i]; - - if (item.polyMesh.Length == 0) - return null; - - return PolyMesh.Create(item.polyMesh); - } - - internal PolyMeshDetail GetDetailMesh(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return null; - - BuildDataItem item = unsafeItems[i]; - - if (item.detailMesh.Length == 0) - return null; - - return PolyMeshDetail.Create(item.detailMesh); - } - - internal void SetWorkingData(int x, int z, PolyMesh polyMesh, PolyMeshDetail detailMesh) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].SetWorkingData(polyMesh, detailMesh); - - mIsDirty = true; - unsafeVersion++; - } - - internal void SetWorkingData(int x, int z, NavmeshTileData tile, int polyCount) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].SetWorkingData(tile, polyCount); - - mIsDirty = true; - unsafeVersion++; - } - - internal bool SetAsBaked() - { - bool result = false; - for (int tx = 0; tx < unsafeWidth; tx++) - { - for (int tz = 0; tz < unsafeDepth; tz++) - { - int i = GetIndex(tx, tz); - - // Note: It is safe to call this method on all tiles. - if (unsafeItems[i].SetAsBaked()) - { - mIsDirty = true; - unsafeVersion++; - result = true; - } - } - } - return result; - } - - internal bool SetAsBaked(int x, int z, byte[] tile, int polyCount) - { - int i = GetIndex(x, z); - if (i == IndexError) - return false; - - if (unsafeItems[i].SetAsBaked(tile, polyCount)) - { - mIsDirty = true; - unsafeVersion++; - return true; - } - - return false; - } - - internal bool SetAsBaked(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return false; - - if (unsafeItems[i].SetAsBaked()) - { - mIsDirty = true; - unsafeVersion++; - return true; - } - - return false; - } - - internal void Reset(int x, int z) - { - int i = GetIndex(x, z); - if (i == IndexError) - return; - - unsafeItems[i].Reset(); - - mIsDirty = true; - unsafeVersion++; - } - - internal int GetIndex(int x, int z) - { - if (x < 0 || x >= unsafeWidth || z < 0 || z >= unsafeDepth) - return IndexError; - return (z * unsafeWidth) + x; - } - - internal bool GetMeshBuildData(Vector3 origin, float tileWorldSize - , out NavmeshParams config - , out NavmeshTileData[] tiles) - { - return GetMeshBuildData(origin, tileWorldSize, new TileZone(0, 0, Width - 1, Depth - 1) - , out config, out tiles); - } - - internal bool GetMeshBuildData(Vector3 origin, float tileWorldSize, TileZone zone - , out NavmeshParams config - , out NavmeshTileData[] tiles) - { - // Is there anything to bake? - - config = null; - tiles = null; - - int maxPolyCount; - - int tileCount; - BakeableCount(out tileCount, out maxPolyCount); - - if (tileCount == 0) - return false; - - config = new NavmeshParams(origin - , tileWorldSize, tileWorldSize - , Mathf.Max(1, tileCount) - , Mathf.Max(1, maxPolyCount)); - - // Add the tiles. - - List ltiles = new List(); - - for (int tx = zone.xmin; tx <= zone.xmax; tx++) - { - for (int tz = zone.zmin; tz <= zone.zmax; tz++) - { - int trash; - NavmeshTileData td = GetTileData(tx, tz, out trash); - if (td == null) - // Tile is not available. - continue; - - ltiles.Add(td); - } - } - - tiles = ltiles.ToArray(); - - return true; - } - - } -} diff --git a/critterai/.svn/pristine/c8/c88ff82b43d03d6626379cfbff481af447844580.svn-base b/critterai/.svn/pristine/c8/c88ff82b43d03d6626379cfbff481af447844580.svn-base deleted file mode 100644 index fe661e27..00000000 --- a/critterai/.svn/pristine/c8/c88ff82b43d03d6626379cfbff481af447844580.svn-base +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.interop; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen -{ - /// - /// Represents a layer within a . - /// - /// - /// - /// Undocumented: Equivalent to Recast: rcHeightfieldLayer. - /// - /// - /// Instances of this class can only be obtained from a . - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class HeightfieldLayer - : IManagedObject - { - - // Field layout: rcHeightfieldLayer - - private Vector3 mBoundsMin; - private Vector3 mBoundsMax; - - private float mXZCellSize; - private float mYCellSize; - - private int mWidth; - private int mDepth; - private int mXMin; // Bounding box of usable data. - private int mXMax; - private int mYMin; - private int mYMax; - private int mHeightMin; - private int mHeightMax; - - // Height min/max - private IntPtr mHeights; // byte[depth*width] - private IntPtr mAreas; // byte[depth*width] - private IntPtr mCons; // byte[depth*width] - - /// - /// The width of the layer. (Along the x-axis in cell units.) - /// - public int Width { get { return mWidth; } } - - /// - /// The depth of the layer. (Along the z-axis in cell units.) - /// - public int Depth { get { return mDepth; } } - - /// - /// The minimum bounds of the layer in world space. - /// - /// The minimum bounds of the layer. - public Vector3 BoundsMin { get { return mBoundsMin; } } - - /// - /// The maximum bounds of the layer in world space. - /// - /// The maximum bounds of the layer. - public Vector3 BoundsMax { get { return mBoundsMax; } } - - /// - /// The width/depth increment of each cell. (On the xz-plane.) - /// - public float XZCellSize { get { return mXZCellSize; } } - - /// - /// The height increment of each cell. (On the y-axis.) - /// - public float YCellSize { get { return mYCellSize; } } - - /// - /// The height maximum of the usable data. - /// - public int HeightMin { get { return mHeightMin; } } - - /// - /// The hight minimum of the usable data. - /// - public int HeightMax { get { return mHeightMax; } } - - /// - /// The x-minumum of the usuable data. - /// - public int XMin { get { return mXMin; } } - - /// - /// The x-maximum of teh usable data. - /// - public int XMax { get { return mXMax; } } - - /// - /// The z-minimum of the usable data. - /// - public int ZMin { get { return mYMin; } } - - /// - /// The z-maximum of the usable data. - /// - public int ZMax { get { return mYMax; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return (mHeights == IntPtr.Zero); } } - - /// - /// The type of unmanaged resources within the object. - /// - public AllocType ResourceType - { - get { return AllocType.ExternallyManaged; } - } - - internal HeightfieldLayer() { } - - internal void Reset() - { - mBoundsMin = Vector3Util.Zero; - mBoundsMax = Vector3Util.Zero; - mXZCellSize = 0; - mYCellSize = 0; - mWidth = 0; - mDepth = 0; - mXMin = 0; - mXMax = 0; - mYMin = 0; - mYMax = 0; - mHeightMin = 0; - mHeightMax = 0; - - mHeights = IntPtr.Zero; - mAreas = IntPtr.Zero; - mCons = IntPtr.Zero; - } - - /// - /// Has no effect on the object. (The object owner will handle disposal.) - /// - /// - /// - /// A always owns and manages objects of this type. - /// - /// - public void RequestDisposal() - { - // Always externally managed. So don't do anything. - } - - - /// - /// Loads the height data into the specified buffer. - /// - /// The buffer to load the data into. [Size: >= Width * Depth] - /// True if the operation completed successfully. - public bool GetHeightData(byte[] buffer) - { - if (IsDisposed || buffer.Length < mWidth * mDepth) - return false; - - Marshal.Copy(mHeights, buffer, 0, mWidth * mDepth); - - return true; - } - - /// - /// Loads the area data into the specified buffer. - /// - /// The buffer to load the data into. [Size: >= Width * Depth] - /// True if the operation completed successfully. - public bool GetAreaData(byte[] buffer) - { - if (IsDisposed || buffer.Length < mWidth * mDepth) - return false; - - Marshal.Copy(mAreas, buffer, 0, mWidth * mDepth); - - return true; - } - - /// - /// Loads the connection data into the specified buffer. - /// - /// The buffer to load the data into. [Size: >= Width * Depth] - /// True if the operation completed successfully. - public bool GetConnectionData(byte[] buffer) - { - if (IsDisposed || buffer.Length < mWidth * mDepth) - return false; - - Marshal.Copy(mCons, buffer, 0, mWidth * mDepth); - - return true; - } - } -} diff --git a/critterai/.svn/pristine/c8/c8978c7f64a1284375891b4f344f9834352e3ce8.svn-base b/critterai/.svn/pristine/c8/c8978c7f64a1284375891b4f344f9834352e3ce8.svn-base deleted file mode 100644 index 63021c3c..00000000 --- a/critterai/.svn/pristine/c8/c8978c7f64a1284375891b4f344f9834352e3ce8.svn-base +++ /dev/null @@ -1,738 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nav.rcn; -using org.critterai.interop; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Represents a dynamic polygon corridor used to plan client movement. - /// - /// - /// - /// The corridor is loaded with a path, usually obtained from a - /// NavmeshQuery FindPath call. The corridor - /// is then used to plan local movement, with the corridor automatically updating as needed to - /// deal with inaccurate client locomotion. - /// - /// - /// Example of a common use case: - ///
        - ///
      1. Construct the corridor object using the - /// and objects in use by the navigation client.
      2. - ///
      3. Obtain a path from a object.
      4. - ///
      5. Use to load the client's current position. - /// (At the beginning of the path.)
      6. - ///
      7. Use to load the path and target.
      8. - ///
      9. Use to plan movement. (This is the straightend path.)
      10. - ///
      11. Use the to feed client movement back into the corridor. - /// (Or if the target is dynamic.) The corridor will automatically adjust - /// as needed.
      12. - ///
      13. Repeat the previous 2 steps to continue to move the client.
      14. - ///
      - /// - /// The corridor position and target are always constrained to the navigation mesh. - /// - /// - /// One of the difficulties in maintaining a path is that floating point errors, locomotion - /// inaccuracies, and/or local steering can result in the client crossing the boundary of the - /// path corridor, temporarily invalidating the path. This class uses local mesh queries - /// to detect and update the corridor as needed to handle these types of issues. - /// - /// - /// The fact that local mesh queries are used to move the position and target locations - /// results in two beahviors that need to be considered: - /// - /// - /// Every time a move method is used there is a chance that the path will become non-optimial. - /// Basically, the further the target is moved from its original location, and the further the - /// position is moved outside the original corridor, the more likely the path will become - /// non-optimal. This issue can be addressed by periodically running the - /// and methods. - /// - /// - /// All local mesh queries have distance limitations. (Review the - /// methods for details.) So the most accurate use case is to move the position and target in - /// small increments. If a large increment is used, then the corridor may not be able to - /// accurately find the new location. Because of this limiation, if a position is moved in a - /// large increment, then compare the desired and resulting polygon references. If the two do - /// not match, then path replanning may be needed. E.g. If you move the target, check - /// the polygon reference of to see if it is as expected. - /// - ///
      - public sealed class PathCorridor - : IManagedObject - { - private IntPtr mRoot; - private int mMaxPathSize; - private NavmeshQueryFilter mFilter; - private NavmeshQuery mQuery; - - private NavmeshPoint mPosition; - private NavmeshPoint mTarget; - - private CornerData mCorners; - - /// - /// The corner point for the specified index. - /// - /// The corner index. [Limit: <= - /// The corner point. - public NavmeshPoint this[int index] { get { return mCorners[index]; } } - - /// - /// The maximum path size that can be handled by the corridor. - /// - public int MaxPathSize { get { return mMaxPathSize; } } - - /// - /// The maximum number of corners that the corner buffer can hold. - /// - public int MaxCorners { get { return mCorners.MaxCorners; } } - - /// - /// The type of unmanaged resource used by the object. - /// - public AllocType ResourceType { get { return AllocType.External; } } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public bool IsDisposed { get { return (mRoot == IntPtr.Zero); } } - - /// - /// The query object used by the corridor. - /// - /// - /// - /// This property can't be used to set the query to null. - /// - /// - public NavmeshQuery Query - { - get { return mQuery; } - set - { - if (value != null) - mQuery = value; - } - } - - /// - /// The query filter used by the corridor. - /// - /// - /// - /// This property can't be used to set the filter to null. - /// - /// - public NavmeshQueryFilter Filter - { - get { return mFilter; } - set - { - if (value != null) - mFilter = value; - } - } - - /// - /// The position within the first polygon of the corridor. - /// - /// - /// - /// This value is automatically constrained to the navigation mesh. - /// - /// - public NavmeshPoint Position { get { return mPosition; } } - - /// - /// The target within the last polygon of the corridor. - /// - /// - /// - /// This value is automatically constrained to the navigation mesh. - /// - /// - public NavmeshPoint Target { get { return mTarget; } } - - - /// - /// The straight path corners for the corridor. (The string-pulled path.) - /// - /// - /// - /// Due to internal optimizations, the maximum number of detectable corners returned will - /// be (Corners.MaxCorners - 1) For example: If the corner buffers are sized to - /// hold 10 corners, there will never be more than 9 corners available. - /// - /// - /// If the target is within range, it will be the last corner and have a polygon reference of zero. - /// - /// - /// This is a reference, not a copy, of the internal data buffer. It should be treated with - /// care. (I.e. Not mutated.) - /// - /// - public CornerData Corners { get { return mCorners; } } - - /// - /// Constructor. - /// - /// - /// - /// Important: The method must be called before the corridor - /// can be used. (That is how the position is set.) - /// - /// - /// Due to internal optimizations, the maximum number of detectable corners will be - /// ( - 1). - /// - /// The query and filter parameters can be set to null. This supports the ability - /// to create pools of re-usable path corridor objects. But it means that care needs to - /// be taken not to use the corridor until query and filter objects have been set. - /// See and for pool related utility - /// functions. - /// - /// - /// - /// The maximum path size that can be handled by the object. [Limit: >= 1] - /// - /// - /// The maximum number of corners the corner buffer can hold. [Limit: >= 2] - /// - /// The query to be used by the corridor. - /// The query filter to be used by the corridor. - public PathCorridor(int maxPathSize, int maxCorners - , NavmeshQuery query, NavmeshQueryFilter filter) - { - maxPathSize = Math.Max(1, maxPathSize); - - mRoot = PathCorridorEx.dtpcAlloc(maxPathSize); - - if (mRoot == IntPtr.Zero) - { - mMaxPathSize = 0; - return; - } - - mQuery = query; - mFilter = filter; - mMaxPathSize = maxPathSize; - mCorners = new CornerData(Math.Max(2, maxCorners)); - } - - /// - /// Destructor. - /// - ~PathCorridor() - { - RequestDisposal(); - } - - /// - /// Immediately frees all unmanaged resources allocated by the object. - /// - public void RequestDisposal() - { - if (!IsDisposed) - { - PathCorridorEx.dtpcFree(mRoot); - mRoot = IntPtr.Zero; - } - } - - /// - /// Resizes the corner buffers. - /// - /// - /// - /// Due to internal optimizations, the maximum number of detectable corners will be - /// ( - 1). - /// - /// - /// All possible corner buffer state will be preserved. (Some state may be lost if the - /// buffer is reduced in size.) - /// - /// - /// - /// The maximum number of corners the corner buffer can hold. [Limit: >= 2] - /// - public void ResizeCornerBuffer(int maxCorners) - { - CornerData nc = new CornerData(Math.Max(2, maxCorners)); - CornerData.Copy(mCorners, nc); - mCorners = nc; - } - - /// - /// Resets the corridor to the specified position. - /// - /// - /// - /// This method sets the position and target to the specified location, and reduces the - /// corridor to the location's polygon. (Path size = 1) - /// - /// - /// This method does not perform any validation of the input data. - /// - /// - /// The position of the client. - public void Reset(NavmeshPoint position) - { - PathCorridorEx.dtpcReset(mRoot, position); - - mPosition = position; - mTarget = position; - - mCorners.cornerCount = 1; - mCorners.verts[0] = position.point; - mCorners.flags[0] = WaypointFlag.Start | WaypointFlag.End; - mCorners.polyRefs[0] = position.polyRef; - } - - /// - /// Finds the corners in the corridor from the position toward the target. - /// (The straightened path.) - /// - /// - /// - /// This method can be used to do corner searches that exceed the capacity of the - /// corridor's normal corner buffers. - /// - /// - /// This method performs essentially the same function as - /// . - /// - /// - /// Due to internal optimizations, the actual maximum number of corners returned - /// will be (buffer.MaxCorners - 1) - /// - /// - /// If the target is within range, it will be the last corner and have a polygon - /// reference of zero. - /// - /// - /// Behavior is undefined if the buffer structure is malformed. E.g. The flag and polygon - /// buffers are different sizes. - /// - /// - /// The buffer to load the results into. [Length: >= 2] - /// The number of corners returned in the buffers. - public int FindCorners(CornerData buffer) - { - buffer.cornerCount = PathCorridorEx.dtpcFindCorners(mRoot - , buffer.verts, buffer.flags, buffer.polyRefs, buffer.polyRefs.Length - , mQuery.root, mFilter.root); - - return buffer.cornerCount; - } - - /// - /// Attempts to optimize the path if the specified point is visible from the current - /// position. - /// - /// - /// - /// Improves pathfinding appearance when using meshes that contain non-border. - /// vertices. (E.g. Tiled meshes and meshes constructed using multiple areas.) - /// - /// - /// The only time should be set to false is if a move - /// or other optimization method is to be called next. Otherwise the corner data may - /// become invalid. - /// - /// - /// Inaccurate locomotion or dynamic obstacle avoidance can force the agent position - /// significantly outside the original corridor. Over time this can result in the - /// formation of a non-optimal corridor. A non-optimal corridor can also form near - /// non-border vertices. (I.e. At tile corners or area transitions.) - /// - /// - /// This function uses an efficient local visibility search to try to optimize the corridor - /// between the current position and . - /// - /// - /// The corridor will change only if is visible from the - /// current position and moving directly toward the point is better than following the - /// existing path. - /// - /// - /// The more inaccurate the client movement, the more beneficial this method becomes. - /// Simply adjust the frequency of the call to match the needs to the client. - /// - /// - /// This method is not suitable for long distance searches. - /// - /// - /// The point to search toward. - /// The maximum range to search. [Limit: > 0] - /// True if the corners data should be refreshed. - public void OptimizePathVisibility(Vector3 next, float optimizationRange - , bool updateCorners) - { - if (updateCorners) - { - mCorners.cornerCount = PathCorridorEx.dtpcOptimizePathVisibilityExt(mRoot - , ref next, optimizationRange - , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length - , mQuery.root, mFilter.root); - } - else - { - PathCorridorEx.dtpcOptimizePathVisibility( - mRoot, ref next, optimizationRange, mQuery.root, mFilter.root); - } - } - - /// - /// Attempts to optimize the path using a local area search. - /// (Partial replanning.) - /// - /// - /// - /// Improves pathfinding appearance in crowded areas and for complex meshes. - /// - /// - /// The only time should be set to false is if a move or - /// another optimization method is to be called next. Otherwise the corner data may - /// become invalid. - /// - /// - /// Inaccurate locomotion or dynamic obstacle avoidance can force the client position - /// significantly outside the original corridor. Over time this can result in the - /// formation of a non-optimal corridor. This method will use a local area path search - /// to try to re-optimize the corridor. - /// - /// - /// The more inaccurate the client movement, the more beneficial this method becomes. - /// Simply adjust the frequency of the call to match the needs to the client. - /// - /// - /// This is a local optimization. It usually doesn't effect the entire corridor - /// through to the goal. It should normally be called based on a time increment rather - /// than movement events. I.e. Call once a second. - /// - /// - /// True if the corners data should be refreshed. - public void OptimizePathTopology(bool updateCorners) - { - if (updateCorners) - { - mCorners.cornerCount = PathCorridorEx.dtpcOptimizePathTopologyExt(mRoot - , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length - , mQuery.root, mFilter.root); - } - else - PathCorridorEx.dtpcOptimizePathTopology(mRoot, mQuery.root, mFilter.root); - } - - /// - /// Moves over an off-mesh connection. - /// - /// - /// - /// This method is minimally tested and documented. - /// - /// - /// The connection polygon reference. - /// Polygon endpoint references. [Length: 2] - /// The start position. - /// The end position. - /// True if the operation succeeded. - public bool MoveOverConnection(uint connectionRef, uint[] endpointRefs - , Vector3 startPosition, Vector3 endPosition) - { - return PathCorridorEx.dtpcMoveOverOffmeshConnection(mRoot - , connectionRef, endpointRefs, ref startPosition, ref endPosition, ref mPosition - , mQuery.root); - } - - /// - /// Moves the position from its current location to the desired location, adjusting the - /// corridor as needed to reflect the new position. - /// - /// - /// - /// Behavior: - /// - ///
        - ///
      • The movement is constrained to the surface of the navigation mesh.
      • - ///
      • The corridor is automatically adjusted (shorted or lengthened) and - /// updated in order to remain valid.
      • - ///
      • The new position will be located in the adjusted corridor's first polygon.
      • - ///
      - /// - /// The expected use case: The desired position will be 'near' the corridor. What is - /// considered 'near' depends on local polygon density, query search extents, etc. - /// - /// - /// The resulting position will differ from the desired position if the desired position - /// is not on the navigation mesh, or it can't be reached using a local search. - /// - ///
      - /// The desired position. - /// The result of the move. - public NavmeshPoint MovePosition(Vector3 desiredPosition) - { - mCorners.cornerCount = PathCorridorEx.dtpcMovePosition(mRoot - , ref desiredPosition, ref mPosition - , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length - , mQuery.root, mFilter.root); - - return mPosition; - } - - /// - /// Moves the target from its curent location to the desired location, adjusting the - /// corridor as needed to reflect the change. - /// - /// - /// - /// Behavior: - /// - ///
        - ///
      • The movement is constrained to the surface of the navigation mesh.
      • - ///
      • The corridor is automatically adjusted (shorted or lengthened) and - /// updated in order to remain valid.
      • - ///
      • The new position will be located in the adjusted corridor's last polygon.
      • - ///
      - /// - /// The expected use case: The desired target will be 'near' the corridor. What is - /// considered 'near' depends on local polygon density, query search extents, etc. - /// - /// - /// The resulting target will differ from the desired target if the desired target is - /// not on the navigation mesh, or it can't be reached using a local search. - /// - ///
      - /// The desired target. - /// The result of the move. - public NavmeshPoint MoveTarget(Vector3 desiredTarget) - { - mCorners.cornerCount = PathCorridorEx.dtpcMoveTargetPosition(mRoot - , ref desiredTarget, ref mTarget - , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length - , mQuery.root, mFilter.root); - - return mTarget; - } - - /// - /// Moves the position and target from their curent locations to the desired locations. - /// - /// - /// - /// Performs an aggregrate operation in the following order: - /// - ///
        - ///
      1. - ///
      2. - ///
      - /// - /// See the documentation of the related functions for details on behavior. - /// - /// - /// This method is more efficient than calling the other methods individually. - /// - ///
      - /// The desired position. - /// The desired target. - public void Move(Vector3 desiredPosition, Vector3 desiredTarget) - { - mCorners.cornerCount = PathCorridorEx.dtpcMove(mRoot - , ref desiredPosition, ref desiredTarget, ref mPosition, ref mTarget - , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length - , mQuery.root, mFilter.root); - } - - /// - /// Loads a new path and target into the corridor. - /// - /// - /// - /// The current position is expected to be within the first - /// polygon in the path. The target is expected to be in the last - /// polygon. - /// - /// - /// The target location within the last polygon of the path. - /// - /// The path corridor. [(polyRef) * ] - /// - /// - /// The number of polygons in the path. - /// [Limits: 0 <= value <= ] - /// - public void SetCorridor(Vector3 target - , uint[] path - , int pathCount) - { - mCorners.cornerCount = PathCorridorEx.dtpcSetCorridor(mRoot - , ref target, path, pathCount, ref mTarget - , mCorners.verts, mCorners.flags, mCorners.polyRefs, mCorners.polyRefs.Length - , mQuery.root, mFilter.root); - } - - /// - /// Obtains a copy of the corridor path. - /// - /// - /// - /// The buffer should be sized to hold the entire path. - /// (See: and .) - /// - /// - /// The buffer to load with the result. [(polyRef) * pathCount] - /// The number of polygons in the path. - public int GetPath(uint[] buffer) - { - return PathCorridorEx.dtpcGetPath(mRoot, buffer, buffer.Length); - } - - /// - /// The number of polygons in the corridor path. - /// - /// The number of polygons in the corridor path. - /// - public int GetPathCount() - { - return PathCorridorEx.dtpcGetPathCount(mRoot); - } - - /// - /// Checks the corridor path to see if its polygon references remain valid. - /// - /// - /// - /// The path can be invalidated if there are structural changes to the underlying - /// navigation mesh, or the state of a polygon within the path changes resulting in it - /// being filtered out. (E.g. An exclusion or inclusion flag changes.) - /// - /// - /// - /// The number of polygons from the beginning of the corridor to search. - /// - /// True if the seached portion of the path is still valid. - public bool IsValid(int maxLookAhead) - { - return PathCorridorEx.dtpcIsValid(mRoot, maxLookAhead, mQuery.root, mFilter.root); - } - - /// - /// Loads the corridor data into the provided buffer. - /// - /// - /// - /// Make sure the buffer is sized to hold the entire result. - /// (See: and .) - /// - /// - /// - /// The buffer to load the data into. - /// [Length: Maximum Path Size >= ] - /// - /// False if the operation failed. - public bool GetData(PathCorridorData buffer) - { - // Only performs a partial parameter validation. - if (buffer == null|| buffer.path == null|| buffer.path.Length < 1) - return false; - - if (buffer.path.Length == PathCorridorData.MarshalBufferSize) - return PathCorridorEx.dtpcGetData(mRoot, buffer); - - buffer.pathCount = GetPath(buffer.path); - buffer.position = mPosition.point; - buffer.target = mTarget.point; - - return true; - } - - /// - /// Released the references to the query and filter. - /// - /// - /// - /// Warning: The corridor will not be in a useable state after this operation. - /// Using the corridor without successfully calling will result in - /// undefined behavior. - /// - /// - /// This method is useful when pooling path corridors for use by mulitple clients. - /// - /// - /// The corridor to update. - public static void ReleaseLocals(PathCorridor corridor) - { - corridor.mQuery = null; - corridor.mFilter = null; - } - - /// - /// Sets the specified resources and resets the corridor. - /// - /// - /// - /// This method is useful when pooling path corridors for use by mulitple clients. - /// - /// - /// See for information on the effect of the reset. - /// - /// - /// Existing references will be replaced by the new references. - /// - /// - /// This method cannot be used to set references to null. Attempting to do so will result - /// in a failure. - /// - /// - /// The corridor to update. - /// The position to reset to corridor to. - /// The query object to use. - /// The filter object to use. - /// True if successful. - public static bool LoadLocals(PathCorridor corridor, NavmeshPoint position - , NavmeshQuery query, NavmeshQueryFilter filter) - { - // Basic checks first. - if (position.polyRef == 0|| corridor == null|| query == null|| filter == null) - return false; - - // Validate optional parameters. - - // Assign and reset. - - corridor.mQuery = query; - corridor.mFilter = filter; - corridor.Reset(position); - - return true; - } - } -} diff --git a/critterai/.svn/pristine/c8/c8ed994da6732962daf2591331906892a15d192b.svn-base b/critterai/.svn/pristine/c8/c8ed994da6732962daf2591331906892a15d192b.svn-base deleted file mode 100644 index 3fc6876e..00000000 --- a/critterai/.svn/pristine/c8/c8ed994da6732962daf2591331906892a15d192b.svn-base +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import static org.critterai.math.geom.Triangle2.*; - -import org.critterai.math.geom.Triangle2; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Triangle2} class. - */ -public class Triangle2Test { - - // Clockwise wrapped - private static final float AX = 3; - private static final float AY = 2; - private static final float BX = 2; - private static final float BY = -1; - private static final float CX = 0; - private static final float CY = -1; - - // Clockwise Wrapped - private static final float AXI = 3; - private static final float AYI = 2; - private static final float BXI = 2; - private static final float BYI = -1; - private static final float CXI = 0; - private static final float CYI = -1; - - public static final float TOLERANCE = 0.0001f; - - @Before - public void setUp() throws Exception - { - } - - @Test - public void testStaticContains() - { - - // Vertex inclusion tests - - assertTrue(contains(AX, AY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(BX, BY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(BX - TOLERANCE, BY + TOLERANCE, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(BX + TOLERANCE, BY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(CX, CY, AX, AY, BX, BY, CX, CY)); - - // Wall inclusion tests - - float midpointX = AX + (BX - AX) / 2; - float midpointY = AY + (BY - AY) / 2; - assertTrue(contains(midpointX, midpointY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(midpointX - TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(midpointX + TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - midpointX = BX + (CX - BX) / 2; - midpointY = BY + (CY - BY) / 2; - assertTrue(contains(midpointX, midpointY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(midpointX, midpointY + TOLERANCE, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(midpointX, midpointY - TOLERANCE, AX, AY, BX, BY, CX, CY)); - midpointX = CX + (AX - CX) / 2; - midpointY = CY + (AY - CY) / 2; - assertTrue(contains(midpointX, midpointY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(midpointX + TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(midpointX - TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - - } - - - - @Test - public void testAreaFloat() - { - float result = getSignedAreaX2(AX, AY, BX, BY, CX, CY); - assertTrue(result == -6); - result = getSignedAreaX2(AX, AY, CX, CY, BX, BY); - assertTrue(result == 6); - } - - @Test - public void testAreaInt() - { - float result = getSignedAreaX2(AXI, AYI, BXI, BYI, CXI, CYI); - assertTrue(result == -6); - result = getSignedAreaX2(AXI, AYI, CXI, CYI, BXI, BYI); - assertTrue(result == 6); - } - -} diff --git a/critterai/.svn/pristine/c9/c9a658e10950f23d84a37dec3ff14d10a77b421f.svn-base b/critterai/.svn/pristine/c9/c9a658e10950f23d84a37dec3ff14d10a77b421f.svn-base deleted file mode 100644 index b68c922d..00000000 --- a/critterai/.svn/pristine/c9/c9a658e10950f23d84a37dec3ff14d10a77b421f.svn-base +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNODE_H -#define DETOURNODE_H - -#include "DetourNavMesh.h" - -enum dtNodeFlags -{ - DT_NODE_OPEN = 0x01, - DT_NODE_CLOSED = 0x02, -}; - -typedef unsigned short dtNodeIndex; -static const dtNodeIndex DT_NULL_IDX = (dtNodeIndex)~0; - -struct dtNode -{ - float pos[3]; ///< Position of the node. - float cost; ///< Cost from previous node to current node. - float total; ///< Cost up to the node. - unsigned int pidx : 30; ///< Index to parent node. - unsigned int flags : 2; ///< Node flags 0/open/closed. - dtPolyRef id; ///< Polygon ref the node corresponds to. -}; - - -class dtNodePool -{ -public: - dtNodePool(int maxNodes, int hashSize); - ~dtNodePool(); - inline void operator=(const dtNodePool&) {} - void clear(); - dtNode* getNode(dtPolyRef id); - dtNode* findNode(dtPolyRef id); - - inline unsigned int getNodeIdx(const dtNode* node) const - { - if (!node) return 0; - return (unsigned int)(node - m_nodes)+1; - } - - inline dtNode* getNodeAtIdx(unsigned int idx) - { - if (!idx) return 0; - return &m_nodes[idx-1]; - } - - inline const dtNode* getNodeAtIdx(unsigned int idx) const - { - if (!idx) return 0; - return &m_nodes[idx-1]; - } - - inline int getMemUsed() const - { - return sizeof(*this) + - sizeof(dtNode)*m_maxNodes + - sizeof(dtNodeIndex)*m_maxNodes + - sizeof(dtNodeIndex)*m_hashSize; - } - - inline int getMaxNodes() const { return m_maxNodes; } - - inline int getHashSize() const { return m_hashSize; } - inline dtNodeIndex getFirst(int bucket) const { return m_first[bucket]; } - inline dtNodeIndex getNext(int i) const { return m_next[i]; } - -private: - - dtNode* m_nodes; - dtNodeIndex* m_first; - dtNodeIndex* m_next; - const int m_maxNodes; - const int m_hashSize; - int m_nodeCount; -}; - -class dtNodeQueue -{ -public: - dtNodeQueue(int n); - ~dtNodeQueue(); - inline void operator=(dtNodeQueue&) {} - - inline void clear() - { - m_size = 0; - } - - inline dtNode* top() - { - return m_heap[0]; - } - - inline dtNode* pop() - { - dtNode* result = m_heap[0]; - m_size--; - trickleDown(0, m_heap[m_size]); - return result; - } - - inline void push(dtNode* node) - { - m_size++; - bubbleUp(m_size-1, node); - } - - inline void modify(dtNode* node) - { - for (int i = 0; i < m_size; ++i) - { - if (m_heap[i] == node) - { - bubbleUp(i, node); - return; - } - } - } - - inline bool empty() const { return m_size == 0; } - - inline int getMemUsed() const - { - return sizeof(*this) + - sizeof(dtNode*)*(m_capacity+1); - } - - inline int getCapacity() const { return m_capacity; } - -private: - void bubbleUp(int i, dtNode* node); - void trickleDown(int i, dtNode* node); - - dtNode** m_heap; - const int m_capacity; - int m_size; -}; - - -#endif // DETOURNODE_H diff --git a/critterai/.svn/pristine/ca/ca05a1f221f96b228f29fa503d3b5d111c4dbdc5.svn-base b/critterai/.svn/pristine/ca/ca05a1f221f96b228f29fa503d3b5d111c4dbdc5.svn-base deleted file mode 100644 index 12650228..00000000 --- a/critterai/.svn/pristine/ca/ca05a1f221f96b228f29fa503d3b5d111c4dbdc5.svn-base +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.interop; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen.rcn -{ - internal static class PolyMeshDetailEx - { - /* - * Design note: - * - * This class will have to be converted to a structure when the - * merge mesh functionality is implemented. - * - */ - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpdFreeMeshData([In, Out] PolyMeshDetail detailMesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpdGetSerializedData( - [In] PolyMeshDetail detailMesh - , bool includeBuffer - , ref IntPtr resultData - , ref int dataSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpdBuildFromMeshData([In] byte[] meshData - , int dataSize - , [In, Out] PolyMeshDetail detailMesh); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpdFlattenMesh([In] PolyMeshDetail detailMesh - , [In, Out] Vector3[] verts - , ref int vertCount - , int vertsSize - , [In, Out] int[] tris - , ref int triCount - , int trisSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool rcpdBuildPolyMeshDetail(IntPtr context - , ref PolyMeshEx polyMesh - , [In] CompactHeightfield chf - , float sampleDist - , float sampleMaxError - , [In, Out] PolyMeshDetail detailMesh); - } -} diff --git a/critterai/.svn/pristine/ca/ca764cf44b976ccb94173230ab769545a4bc0756.svn-base b/critterai/.svn/pristine/ca/ca764cf44b976ccb94173230ab769545a4bc0756.svn-base deleted file mode 100644 index d051b461..00000000 Binary files a/critterai/.svn/pristine/ca/ca764cf44b976ccb94173230ab769545a4bc0756.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/ca/ca89683e41ba618d83ec5a576c990f7517efea94.svn-base b/critterai/.svn/pristine/ca/ca89683e41ba618d83ec5a576c990f7517efea94.svn-base deleted file mode 100644 index 1cce1fd3..00000000 --- a/critterai/.svn/pristine/ca/ca89683e41ba618d83ec5a576c990f7517efea94.svn-base +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - The T:NavmeshBuild asset's advanced build type serves three main purposes: - - - - Provides extra debug information to help you figure out problems, or better set the configuration. - Allows a partial rebuilds of multi-tiled navigation meshes. - Performs background processing for long builds. - - - - The advanced build uses the Navmesh Build Manager editor window that can be opened via the CritterAI menu. - - - - The main drawback of the advanced build is that things can get a bit complex. With lots of extra options you need to know what you are doing. - - - - The advanced build breaks the build down into four steps: - - - - Compile the input. - Set and accept the NMGen Configuration - Build and preview the result. - Bake the result to the target. - - - - While the standard build handles all these steps in one click, they are all separate steps in the advanced build. - - - - - - - The advanced build features are currently in an experimental state. The Unity editor can be finicky when it comes to running background processes. - Also, exception handling is not fully tested. - - - - Make sure you save your scenes frequency when using the advanced build features. - - - - - - -
      - - Limitations & Gotchas - - - - - Because the advanced build lets you go back and forth between the build and the scene while the build is in a partially complete state, there are some things you need to be - careful of. - - - - The input is compiled manually. If you make a change to the scene in the middle of a build, you will need to recompile the input before the build will - pick up the changes. - - - - Certain configuration settings are locked in once you reach the builder stage. If you want to change these settings after you've started the build you'll need to - re-initialize the builder, throwing away any unbaked results. - - - - If you chose to base a new build on the current target's navigation mesh then you will be automatically locked into certain configutration settings from the target. - This includes the target's origin. Any new scene geometry below the origin will not be included in the new build. - - - - The input data cannot survive a Unity Editor reset. A Unity Editor reset will occur, for example, when scripts are recompiled. If an editor reset occurs - during a build the build will enter a recovery state requiring manual intervention. - - - - Be careful when switching scenes while performing an advanced build. If you re-compile the input, it will gather the input from the currently open scene. - - - - The advanced builder stores intermediate build data in the T:NavmeshBuild asset. This data is not cleared when - you bake the mesh. You must exit the build using the Exit Build button. Otherwise, the next time you interact with - the build you'll start with the cached data. The primary reason for this behavior is to prevent the loss of build data in case of an accidental Unity Editor reset. - But it is also a useful behavior if you happen to want to return to a partially complete build at a later time. - - - - Don't forget to bake your build result. Baking to the target is never automatic. - - - - -
      - -
      - - Input Compile - - - - - The first step in the advanced build is the input compile. Once you run the compile you'll get useful debug information along with visualization options. - - - - - - - - You can come back and re-compile the input at any point in the build process. This is especially helpful if you are tweaking the scene and partially - rebuilding a multi-tile navigation mesh. - - - - -
      - -
      - - Configuration - - - - - During the configuration step you set the NMGen configuration that same as you would during a standard build. - - - - - - - - Once the configuration is set, you can start a new build from scratch using the From Scratch button. If the target contains a - supported multi-tile navigation mesh, then you can initialize the build from the target using the Based on Target button. This will - load the existing mesh's configuration and tile data into the builder so you can perform a partial rebuild. - - - - -
      - -
      - - The Builder - - - - - - - - There are two types of builders, one for single-tile and one for multi-tile meshes. This section covers the multi-tile version. - The single-tile version is simple, so it is not covered here. - - - - - - The builder allows you to build, tweak, and rebuild your navigation mesh as needed. Once satisfied you can bake the result to the build target. - Various debug visualizations are available to help you see what is going on with the build. Some visualizations are only available in zone mode. - - - - - - - - - - - Be careful. Some of the visualizations, especially the Input Geometry visualization, are framerate killers. - - - - - - It is possible to operate on only part of a navigation mesh by entering zone mode. You can do this by clicking a tile and adjusting - the Zone Size to get the coverage you desire. You can set the zone size to zero if you only want to select a single tile. - Exit zone mode by clicking on the selected tile. - - - - Builds are performed in the background with the progress shown in the tile grid. Be aware that the background builder is shared by - all build operations in a priority queued manner. It also limits the number of concurrent operations. So if you are building multiple - meshes at once, or perform an input compile in the middle of an in-progress build, don't be surprise when some operations have to wait for - others to complete. Input compiles have the highest priority, followed by zone builds. 'Build All' builds have the lowest priority. - - - - -
      - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/cb/cb04915687d321905b49a451b9b63bae8061b297.svn-base b/critterai/.svn/pristine/cb/cb04915687d321905b49a451b9b63bae8061b297.svn-base deleted file mode 100644 index 1179564b..00000000 --- a/critterai/.svn/pristine/cb/cb04915687d321905b49a451b9b63bae8061b297.svn-base +++ /dev/null @@ -1,61 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE} - Library - Properties - org.critterai - cai-util-u3d - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - none - true - ..\bin\Release\ - TRACE - prompt - 4 - AnyCPU - ..\bin\Release\cai-util-u3d.XML - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - Properties\AssemblyInfo.cs - - - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/cb/cbfa5ddc55c8bb8fe24e817342a455b7f85ab325.svn-base b/critterai/.svn/pristine/cb/cbfa5ddc55c8bb8fe24e817342a455b7f85ab325.svn-base deleted file mode 100644 index 007d7f9a..00000000 --- a/critterai/.svn/pristine/cb/cbfa5ddc55c8bb8fe24e817342a455b7f85ab325.svn-base +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild -{ - /// - /// The state of a build task. - /// - public enum BuildTaskState : byte - { - /// - /// The task has been created but not run. - /// - Inactive = 0, - - /// - /// The task is running. - /// - InProgress, - - /// - /// The task is in the process or aborting. - /// - Aborting, - - /// - /// The task completed successfully. (A finished state.) - /// - Complete, - - /// - /// The task was aborted due to an abort request or error. (A finished state.) - /// - Aborted, - } -} diff --git a/critterai/.svn/pristine/cc/cc0c6a08c95cd689d383a9bc04633f8936576a16.svn-base b/critterai/.svn/pristine/cc/cc0c6a08c95cd689d383a9bc04633f8936576a16.svn-base deleted file mode 100644 index f89b9121..00000000 --- a/critterai/.svn/pristine/cc/cc0c6a08c95cd689d383a9bc04633f8936576a16.svn-base +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -using org.critterai.nav.rcn; -using org.critterai.interop; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// A tile within a - /// - /// - /// - /// Tiles always exist within the context of a object. - /// - /// - /// Tiles returned by a are not guarenteed to be populated. (The tile at - /// a location may have been removed.) Check the polygon count in the - /// to determine if a tile is active. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class NavmeshTile - { - private Navmesh mOwner; - private IntPtr mTile; - - /// - /// True if the object has been disposed and should no longer be used. - /// - /// - /// - /// Just because a tile has no polygons does not mean it is disposed. - /// - /// - public bool IsDisposed { get { return mOwner.IsDisposed; } } - - internal NavmeshTile(Navmesh owner, IntPtr tile) - { - mOwner = owner; - mTile = tile; - } - - /// - /// The reference of the tile. - /// - /// The refernce id of the tile. - public uint GetTileRef() - { - if (mOwner.IsDisposed) - return 0; - return NavmeshTileEx.dtnmGetTileRef(mOwner.root, mTile); - } - - /// - /// Gets the reference of the base polygon in the tile. - /// - /// The reference of the base polygon. - public uint GetBasePolyRef() - { - if (mOwner.IsDisposed) - return 0; - return NavmeshTileEx.dtnmGetPolyRefBase(mOwner.root, mTile); - } - - /// - /// Gets the size of the buffer required by the method. - /// - /// The size of the state data. - public int GetStateSize() - { - if (mOwner.IsDisposed) - return 0; - return NavmeshTileEx.dtnmGetTileStateSize(mOwner.root, mTile); - } - - /// - /// Gets the non-structural state of the tile. (Flags, areas, etc.) - /// - /// - /// - /// The state data is only valid until the tile reference changes. - /// - /// - /// - /// The buffer to load the state into. [Length: >= ] - /// - /// The flags for the operation. - public NavStatus GetState(byte[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return (NavStatus.Failure | NavStatus.InvalidParam); - - return NavmeshTileEx.dtnmStoreTileState(mOwner.root - , mTile - , buffer - , buffer.Length); - } - - /// - /// Sets the non-structural state defined by the state data. - /// (Obtained from the method.) - /// - /// The state data to apply. - /// The flags for the operation. - public NavStatus SetState(byte[] stateData) - { - if (mOwner.IsDisposed || stateData == null) - return (NavStatus.Failure | NavStatus.InvalidParam); - - return NavmeshTileEx.dtnmRestoreTileState(mOwner.root - , mTile - , stateData - , stateData.Length); - } - - /// - /// Gets the tile header. - /// - /// The tile header. - public NavmeshTileHeader GetHeader() - { - if (mOwner.IsDisposed) - { - return new NavmeshTileHeader(); - } - - IntPtr header = NavmeshTileEx.dtnmGetTileHeader(mTile); - - if (header == IntPtr.Zero) - { - return new NavmeshTileHeader(); - } - - return (NavmeshTileHeader) - Marshal.PtrToStructure(header, typeof(NavmeshTileHeader)); - } - - /// - /// Gets a copy of the polygon buffer. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of polygons returned. - public int GetPolys(NavmeshPoly[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTilePolys(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets a copy of the vertex buffer. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of vertices returned. - public int GetVerts(Vector3[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTileVerts(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets a copy of the detailed vertex buffer. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of vertices returned. - public int GetDetailVerts(Vector3[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTileDetailVerts(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets a copy of the detail triangle buffer. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of triangles returned. - public int GetDetailTris(byte[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTileDetailTris(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets a copy of the detail mesh buffer buffer. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of meshes returned. - public int GetDetailMeshes(NavmeshDetailMesh[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTileDetailMeshes(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets a copy of the link buffer. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of links returned. - public int GetLinks(NavmeshLink[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTileLinks(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets a copy of the tree. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of nodes returned. - public int GetBVTree(NavmeshBVNode[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTileBVTree(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets a copy of the off-mesh connection buffer. - /// - /// - /// The buffer to load the results into. - /// [Length: >= ] - /// - /// The number of connections returned. - public int GetConnections(NavmeshConnection[] buffer) - { - if (mOwner.IsDisposed || buffer == null) - return 0; - - return NavmeshTileEx.dtnmGetTileConnections(mTile - , buffer - , buffer.Length); - } - - /// - /// Gets the reference of the polygon based on its polygon index within a tile. - /// - /// - /// The reference of the tile's base poygon. () - /// - /// The polygon's index within the tile. - /// The reference of the polygon. - public static uint GetPolyRef(uint basePolyRef, int polyIndex) - { - return (basePolyRef | (uint)polyIndex); - } - } -} diff --git a/critterai/.svn/pristine/cc/cc48dae237f6082c085f008b428c10a88a0537ca.svn-base b/critterai/.svn/pristine/cc/cc48dae237f6082c085f008b428c10a88a0537ca.svn-base deleted file mode 100644 index c375b3da..00000000 Binary files a/critterai/.svn/pristine/cc/cc48dae237f6082c085f008b428c10a88a0537ca.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/cc/cceb0985fbfcf77b60eccea53636fab08ce1403c.svn-base b/critterai/.svn/pristine/cc/cceb0985fbfcf77b60eccea53636fab08ce1403c.svn-base deleted file mode 100644 index 24b7c959..00000000 --- a/critterai/.svn/pristine/cc/cceb0985fbfcf77b60eccea53636fab08ce1403c.svn-base +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Represents a set of related contours (simple polygons) - * within a bounded field. - *

      The contours may be connected (share edges), but are expected - * to not intersect.

      - * @see Contour - */ -public final class ContourSet - extends BoundedField -{ - - /* - * Design notes: - * - * Not adding the ability to remove contours until it is needed. - * - * Recast Reference: rcContourSet in Recast.h - */ - - private final ArrayList mContours; - - /** - * Constructor - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - * @param initialSize The initial size of the set. Effects performance - * and memory consumption. The actual size will dynamically resize - * as needed. - */ - ContourSet(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize - , float cellHeight - , int initialSize) - { - super(gridBoundsMin, gridBoundsMax, cellSize, cellHeight); - mContours = new ArrayList(initialSize); - } - - /** - * Add a contour to the set. - *

      Behavior is undefined if the contour argument is null.

      - * @param contour The contour to add to the set. - */ - public void add(Contour contour) { mContours.add(contour);} - - /** - * Gets the contour specified by the index. - * @param index The index of the contour to retrieve. - * @return The contour for the specified index, or null if the index - * is invalid. - */ - public Contour get(int index) - { - if (index < 0 || index >= mContours.size()) - return null; - return mContours.get(index); - } - - /** - * The number of contours in the set. - * @return The number of contours in the set. - */ - public int size() { return mContours.size(); } - -} \ No newline at end of file diff --git a/critterai/.svn/pristine/cd/cdbaf1b7bbff22efd29d262ae7c2e71ef5f25fa2.svn-base b/critterai/.svn/pristine/cd/cdbaf1b7bbff22efd29d262ae7c2e71ef5f25fa2.svn-base deleted file mode 100644 index 504fe04f..00000000 Binary files a/critterai/.svn/pristine/cd/cdbaf1b7bbff22efd29d262ae7c2e71ef5f25fa2.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/ce/ce5010388723b52aeb62116c91850b7aca8ef7d7.svn-base b/critterai/.svn/pristine/ce/ce5010388723b52aeb62116c91850b7aca8ef7d7.svn-base deleted file mode 100644 index 51b12742..00000000 --- a/critterai/.svn/pristine/ce/ce5010388723b52aeb62116c91850b7aca8ef7d7.svn-base +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nav -{ - /// - /// Provides neighbor data for agents managed by a crowd manager. - /// (See: ) - /// - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct CrowdNeighbor - { - /// - /// The maximum number of agent neighbors. - /// - /// - /// - /// Used to size buffers of this structure. - /// - /// - public const int MaxNeighbors = 6; - - /// - /// The index of the neighbor. (In the agent buffer.) - /// - public int index; - - /// - /// The distance to the neighbor. - /// - public float distance; - } -} diff --git a/critterai/.svn/pristine/ce/ce9bd02a2241fa1e2e6777b180a145395e72734c.svn-base b/critterai/.svn/pristine/ce/ce9bd02a2241fa1e2e6777b180a145395e72734c.svn-base deleted file mode 100644 index 3c74aa78..00000000 --- a/critterai/.svn/pristine/ce/ce9bd02a2241fa1e2e6777b180a145395e72734c.svn-base +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(StaticFilter))] -public sealed class StaticFilterEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - StaticFilter targ = (StaticFilter)target; - - EditorGUILayout.Separator(); - - GUILayout.Label("Priority: " + targ.Priority); - - EditorGUILayout.Separator(); - - GUILayout.Box("Input Build Processor\n\n" - + "Filters out all components that are NOT marked as static." - , EditorUtil.HelpStyle - , GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Component Filter : Static", false, NMBEditorUtil.FilterGroup)] - static void CreateAsset() - { - StaticFilter item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/cf/cf3637c1eb3cfa53e8dc77b0ae9a6d4bdbf48945.svn-base b/critterai/.svn/pristine/cf/cf3637c1eb3cfa53e8dc77b0ae9a6d4bdbf48945.svn-base deleted file mode 100644 index efb627e1..00000000 --- a/critterai/.svn/pristine/cf/cf3637c1eb3cfa53e8dc77b0ae9a6d4bdbf48945.svn-base +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using UnityEngine; -using UnityEditor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal class BuildSelector - { - private class UnityComparer - : IComparer - { - public int Compare(NavmeshBuild x, NavmeshBuild y) - { - return string.Compare(x.name, y.name, true); - } - } - - private static BuildSelector mInstance; - - private readonly UnityComparer mComparer = new UnityComparer(); - - public event BuildDelegate OnSelect; - - private List mBuilds = new List(); - private string[] mNames; - - private NavmeshBuild mSelected; - // This next field is needed to detect when the selection has been lost due to - // object deletion. - private bool mHasSelection = false; - - public int Count - { - get - { - Validate(); - return mBuilds.Count; - } - } - - public NavmeshBuild Selected - { - get - { - Validate(); - return mSelected; - } - } - - public void Select(NavmeshBuild build) - { - Validate(); - - // Note: Can't set to null. - if (!build || build == mSelected || !mBuilds.Contains(build)) - return; - - mSelected = build; - - HandleSelectionChange(); - } - - public void Remove(NavmeshBuild build) - { - if (!build || !mBuilds.Contains(build)) - return; - - Validate(); - mBuilds.Remove(build); - RefreshNames(); - - if (mSelected == build) - { - mSelected = (mBuilds.Count > 0 ? mBuilds[0] : null); - HandleSelectionChange(); - } - } - - public void Add(NavmeshBuild build) - { - if (!build || mBuilds.Contains(build)) - return; - - mBuilds.Add(build); - mBuilds.Sort(mComparer); - RefreshNames(); - - Validate(); - } - - public void OnGUI(Rect area) - { - Validate(); - - if (!mSelected) - return; - - int iOrig = mBuilds.IndexOf(mSelected); - int iSelected; - - if (mBuilds.Count < 5) - iSelected = GUI.Toolbar(area, iOrig, mNames); - else - { - GUILayout.BeginArea(area); - GUILayout.BeginHorizontal(); - iSelected = EditorGUILayout.Popup(iOrig, mNames); - GUILayout.FlexibleSpace(); - GUILayout.EndHorizontal(); - GUILayout.EndArea(); - } - - if (iSelected != iOrig) - { - mSelected = mBuilds[iSelected]; - HandleSelectionChange(); - } - } - - private void Validate() - { - bool changed = false; - - // Check for and remove nulls. Check for name change. - for (int i = mBuilds.Count - 1; i >= 0; i--) - { - if (!mBuilds[i]) - { - mBuilds.RemoveAt(i); - changed = true; - } - else if (mBuilds[i].name != mNames[i]) - { - mBuilds.Sort(mComparer); - changed = true; - } - } - - if (changed) - RefreshNames(); - - // Has the selection changed? - if (!mSelected) - { - if (mBuilds.Count > 0) - mSelected = mBuilds[0]; - - if (mSelected || mHasSelection) - HandleSelectionChange(); - } - } - - private void HandleSelectionChange() - { - mHasSelection = (mSelected ? true : false); - - if (OnSelect != null) - OnSelect(mSelected); - } - - private void RefreshNames() - { - mNames = new string[mBuilds.Count]; - - for (int i = 0; i < mBuilds.Count; i++) - { - mNames[i] = mBuilds[i].name; - } - } - - public static BuildSelector Instance - { - get - { - if (mInstance == null) - mInstance = new BuildSelector(); - return mInstance; - } - } - } -} diff --git a/critterai/.svn/pristine/cf/cfaa8d028271d93cd066cfd9fffe347da2099a6b.svn-base b/critterai/.svn/pristine/cf/cfaa8d028271d93cd066cfd9fffe347da2099a6b.svn-base deleted file mode 100644 index 61f35f3d..00000000 Binary files a/critterai/.svn/pristine/cf/cfaa8d028271d93cd066cfd9fffe347da2099a6b.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/cf/cfc2eec7e88fa6354b76e254750aec62d5be3440.svn-base b/critterai/.svn/pristine/cf/cfc2eec7e88fa6354b76e254750aec62d5be3440.svn-base deleted file mode 100644 index f8b8f0d7..00000000 --- a/critterai/.svn/pristine/cf/cfc2eec7e88fa6354b76e254750aec62d5be3440.svn-base +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild -{ - /// - /// A standard processor used during the NMGen build process. - /// - public abstract class NMGenProcessor - : INMGenProcessor - { - private readonly string mName; - private readonly int mPriority; - - /// - /// The name of the processor. - /// - public string Name { get { return mName; } } - - /// - /// The processor priority. - /// - public int Priority { get { return mPriority; } } - - /// - /// True if the processor is safe to use for threaded builds. - /// - public abstract bool IsThreadSafe { get; } - - /// - /// The build assets that should be preserved past their normal disposal point. - /// - public virtual NMGenAssetFlag PreserveAssets { get { return 0; } } - - /// - /// Constructor. - /// - /// The name of the processor. - /// The processor priority. - public NMGenProcessor(string name, int priority) - { - mPriority = NMBuild.ClampPriority(priority); - mName = (name == null || name.Length == 0) ? "Unnamed" : name; - } - - /// - /// Process the build context. - /// - /// The current build state. - /// The context to process. - /// False if the build should abort. Otherwise true. - public abstract bool ProcessBuild(NMGenContext context, NMGenState state); - } -} diff --git a/critterai/.svn/pristine/d0/d00d24a8565918f81ddf6072b0850ada03cb2d0f.svn-base b/critterai/.svn/pristine/d0/d00d24a8565918f81ddf6072b0850ada03cb2d0f.svn-base deleted file mode 100644 index 9cfb5788..00000000 --- a/critterai/.svn/pristine/d0/d00d24a8565918f81ddf6072b0850ada03cb2d0f.svn-base +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.geom -{ - /// - /// A basic indexed triangle mesh. - /// - /// - /// - /// The buffers may contain unused space. - /// - /// - public class TriangleMesh - { - /// - /// Vertices [Length: >= ] - /// - public Vector3[] verts; - - /// - /// Triangles [(vertAIndex, vertBIndex, vertCIndex) * ] - /// [Length: >= ( * 3)] - /// - public int[] tris; - - /// - /// The number of vertices. - /// - public int vertCount; - - /// - /// The number of triangles. - /// - public int triCount; - - /// - /// Default constuctor. (Un-initialized, not content.) - /// - public TriangleMesh() { } - - /// - /// Constructor. - /// - /// - /// The maximum number of vertices the buffer needs to hold. - /// [Limit: >= 3] - /// - /// - /// The maximum number of triangles the buffer needs to hold. - /// [Limit: >= 1] - /// - public TriangleMesh(int maxVerts, int maxTris) - { - this.verts = new Vector3[Math.Max(3, maxVerts)]; - this.tris = new int[Math.Max(1, maxTris) * 3]; - } - - /// - /// Constructor. - /// - /// - /// - /// This constructor assigns the provided arrays to the object. (No copying.) - /// - /// - /// - /// The vertices. [Length: >= ] - /// - /// The number of vertices. - /// - /// The triangles. [(vertAIndex, vertBIndex, vertCIndex) * triCount] - /// [Length: >= () * 3] - /// - /// The number of triangles. - public TriangleMesh(Vector3[] verts, int vertCount, int[] tris, int triCount) - { - this.verts = verts; - this.vertCount = vertCount; - this.tris = tris; - this.triCount = triCount; - } - - /// - /// Gets the AABB bounds of the mesh. - /// - /// - /// - /// Do not call this method on an uninitialized mesh. - /// - /// - /// The minimum bounds of the mesh. - /// The maximum bounds of the mesh. - public void GetBounds(out Vector3 boundsMin, out Vector3 boundsMax) - { - boundsMin = verts[tris[0]]; - boundsMax = verts[tris[0]]; - - for (int i = 1; i < triCount * 3; i++) - { - Vector3 v = verts[tris[i]]; - boundsMin.x = Math.Min(boundsMin.x, v.x); - boundsMin.y = Math.Min(boundsMin.y, v.y); - boundsMin.z = Math.Min(boundsMin.z, v.z); - boundsMax.x = Math.Max(boundsMax.x, v.x); - boundsMax.y = Math.Max(boundsMax.y, v.y); - boundsMax.z = Math.Max(boundsMax.z, v.z); - } - } - - /// - /// True if the minimum bounds is less than the maximum bounds on all axes. - /// - /// The minimum AABB bounds. - /// The maximum AABB bounds. - /// - /// True if the minimum bounds is less than the maximum bounds on all axes. - /// - public static bool IsBoundsValid(Vector3 boundsMin, Vector3 boundsMax) - { - return !(boundsMax.x < boundsMin.x - || boundsMax.y < boundsMin.y - || boundsMax.z < boundsMin.z); - } - - /// - /// Validates the structure and, optionally, the content of the mesh. - /// - /// - /// - /// The basic structural validation includes null checks, array size checks, etc. - /// - /// - /// The optional content validation checks that the indices refer to valid vertices - /// and that triangles do not contain duplicate vertices. - /// - /// - /// The mesh vertices. - /// The vertex count. - /// The triangle indices. - /// The triangle count. - /// - /// If true, the content will be checked. Otherwise only the structure will be checked. - /// - /// True if the validation tests pass. - public static bool IsValid(Vector3[] verts, int vertCount - , int[] tris, int triCount - , bool includeContent) - { - if (tris == null || verts == null - || triCount * 3 > tris.Length - || vertCount > verts.Length - || triCount < 0 || vertCount < 0) - { - return false; - } - - if (includeContent) - { - int length = triCount * 3; - - for (int p = 0; p < length; p += 3) - { - int a = tris[p + 0]; - int b = tris[p + 1]; - int c = tris[p + 2]; - - if (a < 0 || a >= vertCount - || b < 0 || b >= vertCount - || c < 0 || c >= vertCount - || a == b || b == c || c == a) - { - return false; - } - } - } - - return true; - } - - /// - /// Validates the structure and, optionally, the content of the mesh. - /// - /// - /// - /// The basic structural validation includes null checks, array size checks, etc. - /// - /// - /// The optional content validation checks that the indices refer to valid vertices - /// and that triangles do not contain duplicate vertices. - /// - /// - /// The mesh to check. - /// - /// If true, the content will be checked. Otherwise only the structure will be checked. - /// - /// True if the validation tests pass. - public static bool IsValid(TriangleMesh mesh, bool includeContent) - { - if (mesh == null) - return false; - - return IsValid(mesh.verts, mesh.vertCount - , mesh.tris, mesh.triCount - , includeContent); - } - } -} diff --git a/critterai/.svn/pristine/d0/d01411744b4b79d7453342a79bc85ad4af6a75cc.svn-base b/critterai/.svn/pristine/d0/d01411744b4b79d7453342a79bc85ad4af6a75cc.svn-base deleted file mode 100644 index 921ada6a..00000000 --- a/critterai/.svn/pristine/d0/d01411744b4b79d7453342a79bc85ad4af6a75cc.svn-base +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents a set of related convex polygons within a bounded field. - *

      The polygons are usually connected (share edges), but are expected - * to not intersect.

      - *

      The data within this class is unprotected. So care must be taken.

      - *

      - * - *

      - * @see PolyMeshFieldBuilder - */ -public final class PolyMeshField - extends BoundedField -{ - - /* - * Recast Reference: rcPolyMesh in Recast.h - */ - - /** - * Represents an index value for a null (non-existent) vertex. - *

      This is required since polygons held within {@link #polys} are - * variable in size. So all entries for polygons within {@link #polys} - * that have fewer vertices than {@link #maxVertsPerPoly()} are padded - * with this value. See {@link #polys} for more information.

      - */ - public static final int NULL_INDEX = -1; - - /** - * The maximum vertices per polygon held within the {@link #polys} array. - * ({@link #maxVertsPerPoly()} * 2) represents the stride of the array. - *

      This value is informational only. There is no enforcement. - */ - private final int mMaxVertsPerPoly; - - /** - * The vertices that make up the field in the form (x, y, z). Value - * defaults to null. - */ - public int[] verts = null; - - /** - * Holds flattened polygon index and neighbor information. Value - * defaults to null. - *

      Where mvpp = {@link #maxVertsPerPoly()}:

      - *
        - *
      • Each polygon entry is 2*mvpp.
      • - *
      • The first mvpp of each entry contains the indices of the polygon. - * The first instance of {@link #NULL_INDEX} means the end of polygon - * indices for the entry.
      • - *
      • The second mvpp of each entry contains indices to neighbor - * polygons. A value of NULL_INDEX indicates no connection for that - * particular edge.
      • - *
      - *

      Example:

      - *

      If mvpp = 6, the polygon has 4 vertices and 2 neighbor - * connections.
      - * Then for (1, 3, 4, 8, NULL_INDEX, NULL_INDEX, 18, NULL_INDEX, 21, - * NULL_INDEX, NULL_INDEX, NULL_INDEX)
      - * (1, 3, 4, 8) defines the polygon.
      - * Polygon 18 shares edge 1->3.
      - * Polygon 21 shares edge 4->8.
      - * Edges 3->4 and 8->1 are border edges. (Not shared with any other - * polygon.)

      - */ - public int[] polys = null; - - /** - * Holds membership region data for each polygon in the form (regionID). - * Value defaults to null. - */ - public int[] polyRegions = null; - - /** - * Consructor - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the base - * of the field.) - * @param cellHeight The height increment of the field. - * @param maxVertsPerPoly The maximum vertices per polygon. Value will - * be auto-clamped to >=3. - * @throws IllegalArgumentException If the bounds are null or the - * wrong size. - */ - public PolyMeshField(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize - , float cellHeight - , int maxVertsPerPoly) - throws IllegalArgumentException - { - super(gridBoundsMin, gridBoundsMax, cellSize, cellHeight); - mMaxVertsPerPoly = Math.max(maxVertsPerPoly, 3); - } - - /** - * Gets the region ID of the polygon. - * @param polyIndex The index of the polygon. - * @return The region ID of the polygon, or -1 if the polygon index - * is invalid. - */ - public int getPolyRegion(int polyIndex) - { - if (polyIndex < 0 || polyIndex >= polyRegions.length) - return -1; - return polyRegions[polyIndex]; - } - - /** - * Gets an array containing the vertices of the polygon. - *

      This is a costly convenience operation.

      - * @param polyIndex The index of the polygon. - * @return An array containing the vertices of the polygon. - */ - public int[] getPolyVerts(int polyIndex) - { - - int pPoly = polyIndex*mMaxVertsPerPoly*2; - if (polyIndex < 0 || pPoly >= polys.length) - return null; - - // Determine the vertex count for this polygon. - int polyVertCount = getPolyVertCount(pPoly, polys, mMaxVertsPerPoly); - int[] result = new int[polyVertCount*3]; - - // Get the vertices. - for (int i = 0; i < polyVertCount; i++) - { - int pVert = polys[pPoly+i]*3; - result[i*3] = verts[pVert]; - result[i*3+1] = verts[pVert+1]; - result[i*3+2] = verts[pVert+2]; - } - - return result; - } - - /** - * The maximum vertices per polygon held within the {@link #polys} array. - * ({@link #maxVertsPerPoly()} * 2) represents the stride of the array. - *

      This value is informational only. There is no enforcement. - * @return The maximum vertices per polygon held within the - * {@link #polys} array. - */ - public int maxVertsPerPoly() { return mMaxVertsPerPoly; } - - /** - * The number of polygons in the {@link #polys} array. - * @return The number of vertices in the {@link #verts} array. - */ - public int polyCount() - { - if (polys == null) - return 0; - return polys.length / (2 * mMaxVertsPerPoly); - } - - /** - * The number of vertices in the {@link #verts} array. - * @return The number of vertices in the {@link #verts} array. - */ - public int vertCount() - { - if (verts == null) - return 0; - return verts.length / 3; - } - - /** - * Returns the vertex count for the specified polygon in the polygon array. - *

      The array is assumed to to be well formed (correct size and layout). - * Otherwise behavior is undefined.

      - *

      Basically, this operation starts counting array entries starting at - * the pointer. It continues to count until it runs into a NULL_INDEX - * value or reaches maxVertsPerPoly, whichever occurs first.

      - * @param polyPointer A pointer of the start of the polygon. - * @param polys An array of polygons in the standard format. - * (E.g. NULL_INDEX indicates end of the polygon and each entry is - * maxVertsPerPoly long.) - * @param maxVertsPerPoly The maximum number of vertices for a polygon - * in the array. - * @return The number of vertices for the specified polygon. - */ - static int getPolyVertCount(int polyPointer - , int[] polys - , int maxVertsPerPoly) - { - for (int i = 0; i < maxVertsPerPoly; i++) - if (polys[polyPointer+i] == NULL_INDEX) - // Ran into a null index. No more vertices for this polygon. - return i; - return maxVertsPerPoly; - } - -} diff --git a/critterai/.svn/pristine/d0/d0482acb272abfb82645d94f6e2db27466df720a.svn-base b/critterai/.svn/pristine/d0/d0482acb272abfb82645d94f6e2db27466df720a.svn-base deleted file mode 100644 index 2aba5823..00000000 --- a/critterai/.svn/pristine/d0/d0482acb272abfb82645d94f6e2db27466df720a.svn-base +++ /dev/null @@ -1,70 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {9DFC1FE0-6469-4A04-AB13-9EAC59087802} - Library - Properties - org.critterai - cai-nmgen - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG - prompt - 4 - AnyCPU - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - AnyCPU - ..\bin\Release\cai-nmgen.XML - - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - rcn\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - {B783B817-8746-4D54-A6CC-664C0A73186F} - cai-nmgen-rcn - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/d0/d0a24b5a6898618262cf0f657a2bd12c8c5a4236.svn-base b/critterai/.svn/pristine/d0/d0a24b5a6898618262cf0f657a2bd12c8c5a4236.svn-base deleted file mode 100644 index f9927a4b..00000000 --- a/critterai/.svn/pristine/d0/d0a24b5a6898618262cf0f657a2bd12c8c5a4236.svn-base +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - The only supported platforms are .NET and UnityPro on Windows. This topic exists - only because attempts are being made to keep CAINav interop friendly. - - - - - - The only provided distributions for CIANav are for the Windows OS. But follows are some - tips if you choose to try to get it working on other platforms. - - - - For the native code, you'll need to recompile the cai-nmgen-rcn and - cai-nav-rcn libraries for your target platform. - The native code is simple, with no Windows dependent headers. If you are inspecting the current libraries and wondering - about some unexpected dependancies, don't worry. They are compiled with the /clr (common languare runtime) flag - because it makes testing and debugging a whole lot easier. It isn't technically required. - - - - Some platforms, including iOS, require that the C# source code be added directly to the - Unity project. This is easy. - Simply browse to \cai-nav-x.x.x\source\src\main\Assets in the distribution and copy the CAI folder - into your project's Asset folder. - - - - - - - A lot of the code protection depends on internal scoping. So take care not to accidentally use internally scoped elements - if you are using a source distribution. - - - - - - Another item you need to be aware of is a serialization gotcha. Never use - the .NET ISerializable interface to serialize CAINav objects. Use the various - byte[] serialization methods instead. It will save you a lot - of headaches down the road if you need to transfer serialized assets between projects on different platforms. - - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/d0/d0b83bc2f9535a21f4856ed019dfab80d9cf7d1e.svn-base b/critterai/.svn/pristine/d0/d0b83bc2f9535a21f4856ed019dfab80d9cf7d1e.svn-base deleted file mode 100644 index 1afc3ed4..00000000 --- a/critterai/.svn/pristine/d0/d0b83bc2f9535a21f4856ed019dfab80d9cf7d1e.svn-base +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - The navigation side of CAINav consists of features - used to create and use navigation meshes for pathfinding and local steering. - - Core: N:org.critterai.nav - - - Unity extensions: - N:org.critterai.nav.u3d - - - There are five main classes you'll be dealing with: - - - - - CAINav uses the OpenGL coordinate system. - - - - - The Navmesh class defines the structure and state of the navigation mesh. The only user component that deals directly with this class - on a regular basis is the component responsible for creating the mesh and managing its state. Normal navigation clients, the one's needing to perform pathfinding - and such, rarely if ever interact directly with the navigation mesh. - - - - The most important class to understand and become comfortable with is the NavmeshQuery class. It provides almost all of the - client navigation features, including A* and Dijkstra path searches, string pulling, point and polygon searches, raycasting, etc. - - - - The NavmeshQueryFilter is a seemingly minor class, but it has a large impact on navigation. Filters are used to define the costs of - traversing the mesh and flags that control which parts of the navigation mesh are included in operations. Multiple filters can be used to customize the - navigation behavior on a per client basis. - - - - The PathCorridor class provides a way of moving along a navigation path without worrying about the minutiae of managing the - path. - - - - The CrowdManager is the big beast of the navigation classes. It not only handles a lot of the path management for you, but also - local steering and dynamic avoidance between navigation clients. I.e. It can keep your agents from running into each other. - - - - - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshQueryFilter - T:org.critterai.nav.PathCorridor - T:org.critterai.nav.CrowdManager - - - - - - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/d0/d0d9af7db78a6abc5273e3845e638e220e17b45b.svn-base b/critterai/.svn/pristine/d0/d0d9af7db78a6abc5273e3845e638e220e17b45b.svn-base deleted file mode 100644 index 35144b8e..00000000 --- a/critterai/.svn/pristine/d0/d0d9af7db78a6abc5273e3845e638e220e17b45b.svn-base +++ /dev/null @@ -1,7 +0,0 @@ -The NMGen source is located in the editor directory -since it is normally only used in the Unity Editor. -This layout prevents code bloat in the Project build. - -Just move the source to this directory if NMGen is -required at runtime. - diff --git a/critterai/.svn/pristine/d1/d16378483562f8580e6a85c60e138b4d458f72af.svn-base b/critterai/.svn/pristine/d1/d16378483562f8580e6a85c60e138b4d458f72af.svn-base deleted file mode 100644 index 6a113d18..00000000 --- a/critterai/.svn/pristine/d1/d16378483562f8580e6a85c60e138b4d458f72af.svn-base +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Builds the CritterAI NMGen library. - Override the version property with -Dversion. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - - Project Home and - - Source Code - -

      -

      - Copyright 2010 Stephen Pratt. All rights reserved. - Use is subject to - - license terms. -

      -
      - - ]]> -
      -
      -
      - - - - - -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/d2/d227f695ec995ca117dbe4b0e2f414f2a90f314c.svn-base b/critterai/.svn/pristine/d2/d227f695ec995ca117dbe4b0e2f414f2a90f314c.svn-base deleted file mode 100644 index d7b72451..00000000 --- a/critterai/.svn/pristine/d2/d227f695ec995ca117dbe4b0e2f414f2a90f314c.svn-base +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "NMGen.h" -#include "RecastAlloc.h" - -extern "C" -{ - EXPORT_API bool nmcfBuildField(nmgBuildContext* ctx - , const int walkableHeight - , const int walkableClimb - , rcHeightfield* hf - , rcCompactHeightfield* chf) - { - if (!ctx || !hf || !chf) - return false; - - return rcBuildCompactHeightfield(ctx - , walkableHeight - , walkableClimb - , *hf - , *chf); - } - - EXPORT_API void nmcfFreeFieldData(rcCompactHeightfield* chf) - { - if (chf) - { - rcFree(chf->cells); - rcFree(chf->spans); - rcFree(chf->dist); - rcFree(chf->areas); - chf->cells = 0; - chf->spans = 0; - chf->dist = 0; - chf->areas = 0; - } - } - - EXPORT_API bool nmcfGetCellData(rcCompactHeightfield* chf - , rcCompactCell* cells - , const int cellsSize) - { - if (!chf || !cells || cellsSize < chf->width * chf->height) - return false; - - memcpy(cells - , chf->cells - , sizeof(rcCompactCell) * chf->width * chf->height); - - return true; - } - - EXPORT_API bool nmcfGetSpanData(rcCompactHeightfield* chf - , rcCompactSpan* spans - , const int spansSize) - { - if (!chf || !spans || spansSize < chf->spanCount) - return false; - - memcpy(spans - , chf->spans - , sizeof(rcCompactSpan) * chf->spanCount); - - return true; - } - - EXPORT_API bool nmcfErodeWalkableArea(nmgBuildContext* ctx - , const int radius - , rcCompactHeightfield* chf) - { - if (ctx && chf) - return rcErodeWalkableArea(ctx, radius, *chf); - return false; - } - - EXPORT_API bool nmcfMedianFilterWalkableArea(nmgBuildContext* ctx - , rcCompactHeightfield* chf) - { - if (ctx && chf) - return rcMedianFilterWalkableArea(ctx, *chf); - return false; - } - - EXPORT_API bool nmcfMarkBoxArea(nmgBuildContext* ctx - , const float* bmin - , const float* bmax - , unsigned char areaId - , rcCompactHeightfield* chf) - { - if (ctx && bmin && bmax && chf) - { - rcMarkBoxArea(ctx, bmin, bmax, areaId, *chf); - return true; - } - return false; - } - - EXPORT_API bool nmcfMarkConvexPolyArea(nmgBuildContext* ctx - , const float* verts - , const int nverts - , const float hmin - , const float hmax - , unsigned char areaId - , rcCompactHeightfield* chf) - { - if (ctx && verts && chf) - { - rcMarkConvexPolyArea(ctx, verts, nverts, hmin, hmax, areaId, *chf); - return true; - } - return false; - } - - EXPORT_API bool nmcfMarkCylinderArea(nmgBuildContext* ctx - , const float* pos - , const float r - , const float h - , unsigned char areaId - , rcCompactHeightfield* chf) - { - if (ctx && pos && chf) - { - rcMarkCylinderArea(ctx, pos, r, h, areaId, *chf); - return true; - } - return false; - } - - EXPORT_API bool nmcfBuildDistanceField(nmgBuildContext* ctx - , rcCompactHeightfield* chf) - { - if (ctx && chf) - return rcBuildDistanceField(ctx, *chf); - return false; - } - - EXPORT_API bool nmcfBuildRegions(nmgBuildContext* ctx - , rcCompactHeightfield* chf - , const int borderSize - , const int minRegionArea - , const int mergeRegionArea) - { - if (ctx && chf) - return rcBuildRegions(ctx - , *chf - , borderSize - , minRegionArea - , mergeRegionArea); - return false; - } - - EXPORT_API bool nmcfBuildRegionsMonotone(nmgBuildContext* ctx - , rcCompactHeightfield* chf - , const int borderSize - , const int minRegionArea - , const int mergeRegionArea) - { - if (ctx && chf) - return rcBuildRegions(ctx - , *chf - , borderSize - , minRegionArea - , mergeRegionArea); - return false; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/d2/d2486a268eeaf564a97610d0e54136648598d20e.svn-base b/critterai/.svn/pristine/d2/d2486a268eeaf564a97610d0e54136648598d20e.svn-base deleted file mode 100644 index 29e69684..00000000 --- a/critterai/.svn/pristine/d2/d2486a268eeaf564a97610d0e54136648598d20e.svn-base +++ /dev/null @@ -1,1203 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nav.rcn; -using org.critterai.interop; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Provides core pathfinding functionality for navigation meshes. - /// - /// - /// - /// In the context of this class: A wall is a polygon segment that is considered impassable. - /// A portal is a passable segment between polygons. - /// - /// - /// If a buffer is too small to hold the entire result, the return status will include - /// the flag. (For methods that support undersized - /// buffers.) - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - public sealed class NavmeshQuery - : ManagedObject - { - internal IntPtr root; // dtNavmeshQuery - - private bool mIsRestricted; - - internal NavmeshQuery(IntPtr query, bool isConstant, AllocType type) - : base(type) - { - mIsRestricted = isConstant; - root = query; - } - - /// - /// Destructor - /// - ~NavmeshQuery() - { - RequestDisposal(); - } - - /// - /// If true, certain methods are disabled. - /// - /// - /// - /// Certain methods are generally not safe for use by multiple clients. These - /// methods will fail if the object is marked as restricted. - /// - /// - public bool IsRestricted { get { return mIsRestricted; } } - - - /// - /// Marks the object as disposed and immediately frees all unmanaged resources for - /// locally owned objects. - /// - /// - /// - /// This method is not projected by the feature. - /// - /// - public override void RequestDisposal() - { - if (ResourceType == AllocType.External) - NavmeshQueryEx.dtnqFree(ref root); - - root = IntPtr.Zero; - } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public override bool IsDisposed - { - get { return (root == IntPtr.Zero); } - } - - /// - /// Finds the nearest point on the surface of the navigation mesh. - /// - /// - /// - /// If the search box does not intersect any polygons the search will return success, - /// but the result polygon reference will be zero. So always check the polygon reference - /// before using the point data. - /// - /// Warning: This function is not suitable for large area searches. If the - /// search extents overlaps more than 128 polygons it may return an invalid result. - /// - /// The detail mesh is used to correct the y-value of result. - /// - /// - /// The center of the search box. - /// The search distance along each axis. - /// The filter to apply to the query. - /// The nearest point on the polygon. - /// The flags for the query. - public NavStatus GetNearestPoint(Vector3 searchPoint, Vector3 extents - , NavmeshQueryFilter filter - , out NavmeshPoint result) - { - result = NavmeshPoint.Zero; - - return NavmeshQueryEx.dtqFindNearestPoly(root - , ref searchPoint - , ref extents - , filter.root - , ref result); - } - - /// - /// Returns the wall segments for the specified polygon. - /// - /// - /// - /// A segment that is normally a portal will be included in the result if the - /// filter results in the neighbor polygon being considered impassable. - /// - /// - /// The vertex buffer must be sized for the maximum segments per polygon of the - /// source navigation mesh. I.e: 2 * - /// - /// - /// The segments can be used for simple 2D collision detection. - /// - /// - /// The polygon reference. - /// The filter to apply to the query. - /// - /// The segment vertex buffer for all walls. [(vertA, vertB) * segmentCount] - /// - /// - /// The number of segments returned in the segments array. - /// - /// The flags for the query. - public NavStatus GetPolySegments(uint polyRef - , NavmeshQueryFilter filter - , Vector3[] resultSegments - , out int segmentCount) - { - segmentCount = 0; - - return NavmeshQueryEx.dtqGetPolyWallSegments(root - , polyRef - , filter.root - , resultSegments - , null - , ref segmentCount - , resultSegments.Length / 2); - } - - /// - /// Returns the segments for the specified polygon, optionally excluding portals. - /// - /// - /// - /// If the segmentPolyRefs parameter is provided, then all polygon segments will be - /// returned. If the parameter is null, then only the wall segments are returned. - /// - /// - /// A segment that is normally a portal will be included in the result as a wall - /// if the filter results in the neighbor polygon being considered impassable. - /// - /// - /// The vertex and polyRef buffers must be sized for the maximum segments per polygon of - /// the source navigation mesh. - /// I.e. (2 * ) - /// - /// - /// The polygon reference. - /// The filter to apply to the query. - /// - /// The segment vertex buffer for all segments. [(vertA, vertB) * segmentCount] - /// - /// - /// Refernce ids of the each segment's neighbor polygon. Or zero if the segment is - /// considered impassable. [(polyRef) * segmentCount] (Optional) - /// The number of segments returned. - /// The flags for the query. - public NavStatus GetPolySegments(uint polyRef - , NavmeshQueryFilter filter - , Vector3[] resultSegments - , uint[] segmentPolyRefs - , out int segmentCount) - { - segmentCount = 0; - - return NavmeshQueryEx.dtqGetPolyWallSegments(root - , polyRef - , filter.root - , resultSegments - , segmentPolyRefs - , ref segmentCount - , resultSegments.Length / 2); - } - - /// - /// Gets all polygons whose AABB's overlap the search box. - /// - /// - /// - /// This is a fast, but inaccurate query since only AABB's are checked. A strict - /// polygon-box overlap check is not performed. - /// - /// - /// If no polygons are found, the method will return success with a result count of zero. - /// - /// - /// If the result buffer is too small to hold the entire result then the buffer - /// will be filled to capacity. The method of choosing which polygons from the full - /// result are included in the partial result is undefined. - /// - /// - /// The center of the query box. - /// The search distance along each axis. - /// The filter to apply to the query. - /// - /// The references of the polygons that overlap the query box. - /// [(polyRef) * resultCount] (Out) - /// - /// The number of polygons found. - /// The flags for the query. - public NavStatus GetPolys(Vector3 searchPoint - , Vector3 extents - , NavmeshQueryFilter filter - , uint[] resultPolyRefs - , out int resultCount) - { - resultCount = 0; - - return NavmeshQueryEx.dtqQueryPolygons(root - , ref searchPoint - , ref extents - , filter.root - , resultPolyRefs - , ref resultCount - , resultPolyRefs.Length); - } - - /// - /// Finds the polygons within the graph that touch the specified circle. - /// - /// - /// - /// At least one result buffer must be provided. - /// - /// - /// The order of the result is from least to highest cost to reach the polygon. - /// - /// - /// The primary use case for this method is for performing Dijkstra searches. - /// Candidate polygons are found by searching the graph beginning at the start polygon. - /// - /// - /// If a polygon is not found via the graph search, even if it intersects the - /// search circle, it will not be included in the result. Example scenario: - /// - /// polyA is the start polygon.
      - /// polyB shares an edge with polyA. (Is adjacent.)
      - /// polyC shares an edge with polyB, but not with polyA
      - /// Even if the search circle overlaps polyC, it will not be included in the result - /// unless polyB is also in the set. - ///
      - /// - /// The value of the center point is used as the start point for cost calculations. - /// It is not projected onto the surface of the mesh, so its y-value will effect the costs. - /// - /// - /// Intersection tests occur in 2D. All polygons and the search circle are projected - /// onto the xz-plane. So the y-value of the center point does not effect intersection - /// tests. - /// - /// If the buffers are to small to hold the entire result, they will be filled to - /// capacity. - /// - ///
      - /// - /// The center point to start from which to start the search. (Must be valid.) - /// - /// The radius of the query circle. - /// The filter to apply to the query. - /// - /// The references of the polygons touched by the circle. - /// [(polyRef) * resultCount] (Optional) - /// - /// - /// The reference of the parent polygons for each result. Zero if a result polygon has no - /// parent. [(parentRef) * resultCount] (Optional) - /// - /// The search cost from the center point to the polygon. [(cost) * resultCount] (Optional) - /// - /// The number of polygons found. - /// The flags for the query. - public NavStatus FindPolys(NavmeshPoint start, float radius - , NavmeshQueryFilter filter - , uint[] resultPolyRefs, uint[] resultParentRefs, float[] resultCosts - , out int resultCount) - { - resultCount = 0; - - // Set max count to the smallest length. - int maxCount = (resultPolyRefs == null ? 0 : resultPolyRefs.Length); - - maxCount = (resultParentRefs == null - ? maxCount - : Math.Min(maxCount, resultParentRefs.Length)); - - maxCount = (resultCosts == null - ? maxCount - : Math.Min(maxCount, resultCosts.Length)); - - if (maxCount == 0) - return (NavStatus.Failure | NavStatus.InvalidParam); - - return NavmeshQueryEx.dtqFindPolysAroundCircle(root - , start.polyRef - , ref start.point - , radius - , filter.root - , resultPolyRefs - , resultParentRefs - , resultCosts - , ref resultCount - , maxCount); - } - - /// - /// Finds the navigation polygons within the graph that touch the specified convex polygon. - /// - /// - /// - /// The order of the result is from least to highest cost. - /// - /// - /// At least one result buffer must be provided. - /// - /// - /// The primary use case for this method is for performing Dijkstra searches. - /// Candidate polygons are found by searching the graph beginning at the start polygon. - /// - /// - /// The same intersection test restrictions that apply to the circle version of this - /// method apply to this method. - /// - /// - /// The 3D centroid of the polygon is used as the start position for cost - /// calculations. - /// - /// Intersection tests occur in 2D. All polygons are projected onto the xz-plane, - /// so the y-values of the vertices do not effect intersection tests. - /// - /// - /// If the buffers are is too small to hold the entire result, they will be - /// filled to capacity. - /// - /// - /// The reference of the polygon to start the search at. - /// - /// The vertices of the convex polygon. [Length: vertCount] - /// - /// The filter to apply to the query. - /// - /// The references of the polygons touched by the search - /// polygon. [(polyRef) * resultCount] (Optional) - /// - /// - /// The references of the parent polygons for each result. - /// Zero if a result polygon has no parent. [(parentRef) * resultCount] (Optional) - /// - /// - /// The search cost from the centroid point to the polygon. - /// [(cost) * resultCount] (Optional) - /// - /// The number of polygons found. - /// The flags for the query. - public NavStatus FindPolys(uint startPolyRef - , Vector3[] vertices - , NavmeshQueryFilter filter - , uint[] resultPolyRefs - , uint[] resultParentRefs - , float[] resultCosts - , out int resultCount) - { - resultCount = 0; - - // Set max count to the smallest length. - int maxCount = (resultPolyRefs == null ? 0 : resultPolyRefs.Length); - - maxCount = (resultParentRefs == null - ? maxCount - : Math.Min(maxCount, resultParentRefs.Length)); - - maxCount = (resultCosts == null - ? maxCount - : Math.Min(maxCount, resultCosts.Length)); - - if (maxCount == 0) - return (NavStatus.Failure | NavStatus.InvalidParam); - - return NavmeshQueryEx.dtqFindPolysAroundShape(root - , startPolyRef - , vertices - , vertices.Length - , filter.root - , resultPolyRefs - , resultParentRefs - , resultCosts - , ref resultCount - , maxCount); - } - - /// - /// Finds the non-overlapping navigation polygons in the local neighborhood around the - /// specified point. - /// - /// - /// - /// This method is optimized for a small query radius and small number of result polygons. - /// - /// - /// The order of the result is from least to highest cost. - /// - /// At least one result buffer must be provided. - /// - /// The primary use case for this method is for performing Dijkstra searches. - /// Candidate polygons are found by searching the graph beginning at the start polygon. - /// - /// - /// The same intersection test restrictions that apply to the FindPoly methods apply - /// to this method. - /// - /// - /// The value of the center point is used as the start point for cost calculations. - /// It is not projected onto the surface of the mesh, so its y-value will effect the costs. - /// - /// - /// Intersection tests occur in 2D. All polygons and the search circle are projected - /// onto the xz-plane, so the y-value of the center point does not effect intersection - /// tests. - /// - /// - /// If the buffers are is too small to hold the entire result, they will be - /// filled to capacity. - /// - /// - /// - /// The center point to start from which to start the search. (Must be valid.) - /// - /// The radius of the search circle. - /// The filter to apply to the query. - /// - /// The references of the polygons touched by the circle. - /// [(polyRef) * resultCount] (Optional) - /// - /// - /// The references of the parent polygons for each result. - /// Zero if a result polygon has no parent. [(parentRef) * resultCount] (Optional) - /// - /// The number of polygons found. - /// The flags for the query. - public NavStatus GetPolysLocal(NavmeshPoint start, float radius - , NavmeshQueryFilter filter - , uint[] resultPolyRefs, uint[] resultParentRefs, out int resultCount) - { - resultCount = 0; - - // Set max count to the smallest length. - int maxCount = (resultPolyRefs == null ? 0 : resultPolyRefs.Length); - - maxCount = (resultParentRefs == null - ? maxCount - : Math.Min(maxCount, resultParentRefs.Length)); - - if (maxCount == 0) - return (NavStatus.Failure | NavStatus.InvalidParam); - - return NavmeshQueryEx.dtqFindLocalNeighbourhood(root - , start.polyRef - , ref start.point - , radius - , filter.root - , resultPolyRefs - , resultParentRefs - , ref resultCount - , maxCount); - } - - /// - /// Finds the closest point on the specified polygon. - /// - /// - /// - /// Uses the height detail to provide the most accurate information. - /// - /// - /// The source point does not have to be within the bounds of the navigation mesh. - /// - /// - /// The polygon reference. - /// The position to search from. - /// The closest point on the polygon. - /// The flags for the query. - public NavStatus GetNearestPoint(uint polyRef, Vector3 sourcePoint, out Vector3 resultPoint) - { - resultPoint = Vector3Util.Zero; - - return NavmeshQueryEx.dtqClosestPointOnPoly(root - , polyRef - , ref sourcePoint - , ref resultPoint); - } - - /// - /// Returns a point on the boundary closest to the source point if the source point is - /// outside the polygon's xz-column. - /// - /// - /// - /// Much faster than the other nearest point methods. - /// - /// - /// If the provided point lies within the polygon's xz-column (above or below), then - /// the source and result points will be equal. - /// - /// - /// The boundary point will be the polygon boundary, not the height corrected detail - /// boundary. Use if needed. - /// - /// The source point does not have to be within the bounds of the navigation mesh. - /// - /// - /// The polygon reference. - /// The point to check. - /// The closest point. - /// The flags for the query. - public NavStatus GetNearestPointF(uint polyRef - , Vector3 sourcePoint - , out Vector3 resultPoint) - { - resultPoint = Vector3Util.Zero; - - return NavmeshQueryEx.dtqClosestPointOnPolyBoundary(root - , polyRef - , ref sourcePoint - , ref resultPoint); - } - - /// - /// Gets the height of the polygon at the provided point using the detail mesh. - /// (Most accurate.) - /// - /// - /// - /// The method will return falure if the provided point is outside the xz-column - /// of the polygon. - /// - /// - /// The point within the polygon's xz-column. - /// The height at the surface of the polygon. - /// - /// The flags for the query. - public NavStatus GetPolyHeight(NavmeshPoint point, out float height) - { - height = 0; - - return NavmeshQueryEx.dtqGetPolyHeight(root - , point - , ref height); - } - - /// - /// Returns the distance from the specified position to the nearest polygon wall. - /// - /// - /// - /// The closest point is not height adjusted using the detail data. - /// Use if needed. - /// - /// - /// The distance will equal the search radius if there is no wall within the radius. - /// In this case the values of closestPoint and normal are undefined. - /// - /// - /// The normal will become unpredicable if the distance is a very small number. - /// - /// - /// The center of the search circle. - /// The radius of the search circle. - /// The filter to apply to the query. - /// Distance to nearest wall. - /// The nearest point on the wall. - /// - /// The normalized ray formed from the wall point to the source point. - /// - /// The flags for the query. - public NavStatus FindDistanceToWall(NavmeshPoint searchPoint - , float searchRadius - , NavmeshQueryFilter filter - , out float distance - , out Vector3 closestPoint - , out Vector3 normal) - { - distance = 0; - closestPoint = Vector3Util.Zero; - normal = Vector3Util.Zero; - - return NavmeshQueryEx.dtqFindDistanceToWall(root - , searchPoint - , searchRadius - , filter.root - , ref distance - , ref closestPoint - , ref normal); - } - - /// - /// Finds the polygon path from the start to the end polygon. - /// - /// - /// - /// If the end polygon cannot be reached, then the last polygon is the nearest one - /// found to the end polygon. - /// - /// - /// If the path buffer is to small to hold the result, it will be filled as far as - /// possible from the start polygon toward the end polygon. - /// - /// - /// The start and end points are used to calculate traversal costs. (y-values matter.) - /// - /// - /// A point within the start polygon. - /// A point within the end polygon. - /// The filter to apply to the query. - /// - /// An ordered list of polygoon references in the path. (Start to end.) (Out) - /// [(polyRef) * pathCount] - /// - /// The number of polygons in the path. - /// The flags for the query. - public NavStatus FindPath(NavmeshPoint start, NavmeshPoint end - , NavmeshQueryFilter filter - , uint[] resultPath, out int pathCount) - { - pathCount = 0; - - return NavmeshQueryEx.dtqFindPath(root - , start - , end - , filter.root - , resultPath - , ref pathCount - , resultPath.Length); - } - - /// - /// Finds the polygon path from the start to the end polygon. - /// - /// - /// - /// This method is useful if the polygon reference of either the - /// or point is not known. If both points - /// have a polygon reference of zero, then this method is equivalent to the following: - /// - ///
        - ///
      1. - /// Using with the - /// point to get the start polygon. - ///
      2. - ///
      3. - /// Using with the - /// point to get the end polygon. - ///
      4. - ///
      5. Calling the normal find path using the two new start and end points.
      6. - ///
      - /// - /// A point search will only be performed for points with a polygon reference - /// of zero. If a point search is required, the point and its polygon reference - /// parameter become output parameters and the point will be snapped to the navigation mesh. - /// - /// - /// This method may return a partial result, even if there is a failure. If there is - /// no failure, it will at least perform the required point searches. If the point - /// searches succeed, then the find path operation will be performed. - /// - /// - /// Checking the return results: - /// - ///
        - ///
      • If the is greater than zero, then the path and all - /// required point searches succeeded.
      • - ///
      • If the overall operation failed, but a point with an input polygon reference of - /// zero has an output polygon reference that is non-zero, then that point's search - /// succeeded.
      • - ///
      - /// - /// For the path results: - /// - /// - /// If the end polygon cannot be reached, then the last polygon is the nearest one - /// found to the end polygon. - /// - /// - /// If the path buffer is to small to hold the result, it will be filled as far as - /// possible from the start polygon toward the end polygon. - /// - /// The start and end points are used to calculate traversal costs. - /// (y-values matter.) - /// - ///
      - /// - /// A point within the start polygon. (In) (Out if the polygon reference is zero.) - /// - /// - /// A point within the end polygon. (In) (Out if the polygon reference is zero.) - /// - /// - /// The search extents to use if the start or end point polygon reference is zero. - /// - /// The filter to apply to the query. - /// - /// An ordered list of polygon references in the path. (Start to end.) (Out) - /// [(polyRef) * pathCount] - /// - /// The number of polygons in the path. - /// The flags for the query. - public NavStatus FindPath(ref NavmeshPoint start, ref NavmeshPoint end - , Vector3 extents, NavmeshQueryFilter filter - , uint[] resultPath, out int pathCount) - { - pathCount = 0; - - return NavmeshQueryEx.dtqFindPathExt(root - , ref start - , ref end - , ref extents - , filter.root - , resultPath - , ref pathCount - , resultPath.Length); - } - - /// - /// Returns true if the polygon refernce is in the current closed list. - /// - /// - /// - /// The closed list is the list of polygons that were fully evaluated during a find - /// operation. - /// - /// - /// All methods prefixed with "Find" and all sliced path methods generate a closed - /// list. The content of the list will persist until the next find/sliced method is called. - /// - /// - /// The polygon reference. - /// True if the polgyon is in the current closed list. - public bool IsInClosedList(uint polyRef) - { - return NavmeshQueryEx.dtqIsInClosedList(root, polyRef); - } - - /// - /// Returns true if the polygon reference is valid and passes the filter restrictions. - /// - /// The polygon reference. - /// The filter to apply to the query. - /// - /// True if the polygon reference is valid and passes the filter restrictions. - /// - public bool IsValidPolyRef(uint polyRef, NavmeshQueryFilter filter) - { - return NavmeshQueryEx.dtqIsValidPolyRef(root, polyRef, filter.root); - } - - /// - /// Casts a 'walkability' ray along the surface of the navigation mesh from the start point - /// toward the end point. - /// - /// - /// - /// This method is meant to be used for quick short distance checks. - /// - /// - /// If the path buffer is too small to hold the result, it will be filled as far as - /// possible from the start point toward the end point. - /// - /// Using the Hit Paramter - /// - /// If the hit parameter is a very high value (>1E38), then the ray has hit the - /// end point. In this case the path represents a valid corridor to the end point and - /// the value of hitNormal is undefined. - /// - /// - /// If the hit parameter is zero, then the start point is on the border that was hit - /// and the value of hitNormal is undefined. - /// - /// - /// If 0 < hitParameter < 1.0 then the following applies: - /// - /// distanceToHitBorder = distanceToEndPoint * hitParameter - /// hitPoint = startPoint + (endPoint - startPoint) * hitParameter - /// - /// - /// Use Case Restriction - /// - /// - /// The raycast ignores the y-value of the end point. (2D check) This places - /// significant limits on how it can be used. Example scenario: - /// - /// Consider a scene where there is a main floor with a second floor balcony that - /// hangs over the main floor. So the first floor mesh extends below the balcony mesh. - /// The start point is somewhere on the first floor. The end point is on the balcony. - /// - /// - /// The raycast will search toward the end point along the first floor mesh. If it - /// reaches the end point's xz-coordinates it will indicate 'no hit', meaning it reached - /// the end point. - /// - /// - /// - /// A point within the start polygon representing the start of the ray. - /// - /// The point to cast the ray toward. - /// The filter to apply to the query. - /// The hit parameter. (>1E38 if no hit.) - /// The normal of the nearest wall hit. - /// - /// The references of the visited polygons. [(polyRef) * pathCount] (Optional) - /// - /// The number of visited polygons. - /// The flags for the query. - public NavStatus Raycast(NavmeshPoint start, Vector3 end - , NavmeshQueryFilter filter - , out float hitParameter, out Vector3 hitNormal - , uint[] path, out int pathCount) - { - pathCount = 0; - hitParameter = 0; - hitNormal = Vector3Util.Zero; - - int maxCount = (path == null ? 0 : path.Length); - - return NavmeshQueryEx.dtqRaycast(root - , start - , ref end - , filter.root - , ref hitParameter - , ref hitNormal - , path - , ref pathCount - , maxCount); - } - - /// - /// Returns the staight path from the start to the end point within the polygon corridor. - /// - /// - /// - /// This method peforms what is often called 'string pulling'. - /// - /// - /// If the provided result buffers are too small for the entire result, they will - /// be filled as far as possible from the start point toward the end point. - /// - /// - /// The start point is clamped to the first polygon in the path, and the end point - /// is clamped to the last. So the start and end points should be within or very near the - /// first and last polygons respectively. The pathStart and pathCount parameters can be - /// adjusted to restrict the usable portion of the the path to meet this requirement. - /// (See the example below.) - /// - /// - /// The returned polygon references represent the polygon that is entered at the - /// associated path point. The reference associated with the end point will always be - /// zero. - /// - /// - /// Example use case for adjusting the straight path during locomotion: - /// - /// - /// Senario: The path consists of polygons A, B, C, D, with the start point in A and - /// the end point in D. - /// - /// - /// The first call to the method will return straight waypoints for the entire path: - /// - /// - /// query.GetStraightPath(startPoint, endPoint - /// , path - /// , 0, 4 // pathStart, pathCount - /// , straigthPath, null, null - /// , out straightCount); - /// - /// - /// If the agent moves into polygon B and needs to recaclulate its straight path for - /// some reason, it can call the method as follows using the original path buffer: - /// - /// - /// query.GetStraightPath(startPoint, endPoint - /// , path - /// , 1, 3 // pathStart, pathCount <- Note the changes here. - /// , straigthPath, null, null - /// , out straightCount); - /// - /// - /// The start point. - /// The end point. - /// - /// The list of polygon references that represent the path corridor. - /// - /// - /// The index within the path buffer of the polygon that contains the start point. - /// - /// - /// The length of the path within the path buffer. (endPolyIndex - startPolyIndex) - /// - /// - /// Points describing the straight path. [(point) * straightPathCount]. - /// - /// Flags describing each point. [(flags) * striaghtPathCount] (Optional) - /// - /// The reference of the polygon that is being entered at the point position. - /// [(polyRef) * straightPathCount] (Optional) - /// The number of points in the straight path. - /// The flags for the query. - public NavStatus GetStraightPath(Vector3 start, Vector3 end - , uint[] path, int pathStart, int pathCount - , Vector3[] resultPoints, WaypointFlag[] resultFlags, uint[] resultRefs - , out int resultCount) - { - resultCount = 0; - - int maxPath = resultPoints.Length; - - maxPath = (resultFlags == null ? maxPath - : Math.Min(resultFlags.Length, maxPath)); - - maxPath = (resultRefs == null ? maxPath - : Math.Min(resultRefs.Length, maxPath)); - - if (maxPath < 1) - return (NavStatus.Failure | NavStatus.InvalidParam); - - return NavmeshQueryEx.dtqFindStraightPath(root - , ref start - , ref end - , path - , pathStart - , pathCount - , resultPoints - , resultFlags - , resultRefs - , ref resultCount - , maxPath); - } - - /// - /// Moves from the start to the end point constrained to the navigation mesh. - /// - /// - /// - /// This method is optimized for small delta movement and a small number of polygons. - /// If used for too great a distance, the result will form an incomplete path. - /// - /// The result point will equal the end point if the end is reached. Otherwise the - /// closest reachable point will be returned. - /// - /// - /// The result position is not projected to the surface of the navigation mesh. If - /// that is needed, use . - /// - /// This method treats the end point in the same manner as the - /// method. (As a 2D point.) See that method's documentation for details on the impact. - /// - /// - /// If the result buffer is too small to hold the entire result, it will be - /// filled as far as possible from the start point toward the end point. - /// - /// - /// A position within the start polygon. - /// The end position. - /// The filter to apply to the query. - /// The result point from the move. - /// The references of the polygons - /// visited during the move. [(polyRef) * visitedCount] - /// The number of polygons visited during - /// the move. - /// The flags for the query. - public NavStatus MoveAlongSurface(NavmeshPoint start, Vector3 end - , NavmeshQueryFilter filter - , out Vector3 resultPoint - , uint[] visitedPolyRefs, out int visitedCount) - { - visitedCount = 0; - resultPoint = Vector3Util.Zero; - - return NavmeshQueryEx.dtqMoveAlongSurface(root - , start - , ref end - , filter.root - , ref resultPoint - , visitedPolyRefs - , ref visitedCount - , visitedPolyRefs.Length); - } - - /// - /// Returns a random point on the navigation mesh. - /// - /// - /// - /// The search speed is linear to the number of polygons. - /// - /// - /// The filter to apply to the query. - /// A random point on the navigation mesh. - /// The flags for the query. - public NavStatus GetRandomPoint(NavmeshQueryFilter filter, out NavmeshPoint randomPoint) - { - randomPoint = new NavmeshPoint(); - - return NavmeshQueryEx.dtqFindRandomPoint(root, filter.root, ref randomPoint); - } - - /// - /// Returns a random point within reach of the specified location. - /// - /// - /// - /// The result point is constrainted to the polygons overlapped by the circle, not - /// the circle itself. The overlap test follows the same rules as the FindPolys method. - /// - /// - /// The search speed is linear to the number of polygons. - /// - /// - /// The point to search from. - /// The polygon overlap radius. - /// The filter to apply to the query. - /// A random point within reach of the specified location. - /// The flags for the query. - public NavStatus GetRandomPoint(NavmeshPoint start, float radius - , NavmeshQueryFilter filter - , out NavmeshPoint randomPoint) - { - randomPoint = new NavmeshPoint(); - - return NavmeshQueryEx.dtqFindRandomPointCircle(root, start, radius - , filter.root - , ref randomPoint); - } - - /// - /// Initializes a sliced path find query. - /// - /// - /// - /// This method will fail if is true. - /// - /// - /// Warning: Calling any other query methods besides the other sliced path methods - /// before finalizing this query may result in corrupted data. - /// - /// - /// The filter is stored and used for the duration of the query. - /// - /// - /// The standard use case: - /// - ///
        - ///
      1. Initialize the sliced path query
      2. - ///
      3. Call until its status returns complete.
      4. - ///
      5. Call to get the path.
      6. - ///
      - ///
      - /// A point within the start polygon. - /// A point within the end polygon. - /// The filter to apply to the query. - /// The flags for the query. - public NavStatus InitSlicedFindPath(NavmeshPoint start, NavmeshPoint end - , NavmeshQueryFilter filter) - { - if (mIsRestricted) - return NavStatus.Failure; - - return NavmeshQueryEx.dtqInitSlicedFindPath(root - , start - , end - , filter.root); - } - - /// - /// Continues a sliced path find query. - /// - /// - /// - /// This method will fail if is true. - /// - /// - /// The maximum number of iterations to perform. - /// The actual number of iterations performed. - /// The flags for the query. - public NavStatus UpdateSlicedFindPath(int maxIterations - , out int actualIterations) - { - actualIterations = 0; - - if (mIsRestricted) - return NavStatus.Failure; - - return NavmeshQueryEx.dtqUpdateSlicedFindPath(root - , maxIterations - , ref actualIterations); - } - - /// - /// Finalizes and returns the results of the sliced path query. - /// - /// - /// - /// This method will fail if is true. - /// - /// - /// An ordered list of polygons representing the path. - /// [(polyRef) * pathCount] - /// The number of polygons in the path. - /// The flags for the query. - public NavStatus FinalizeSlicedFindPath(uint[] path - , out int pathCount) - { - pathCount = 0; - - if (mIsRestricted) - return NavStatus.Failure; - - return NavmeshQueryEx.dtqFinalizeSlicedFindPath(root - , path - , ref pathCount - , path.Length); - } - - /// - /// Creates a new navigation mesh query based on the provided navigation mesh. - /// - /// A navigation mesh to query against. - /// - /// The maximum number of nodes allowed when performing A* and Dijkstra searches. - /// - /// A navigation mesh query object. - /// The flags for the build request. - public static NavStatus Create(Navmesh navmesh - , int maximumNodes - , out NavmeshQuery resultQuery) - { - IntPtr query = IntPtr.Zero; - - NavStatus status = NavmeshQueryEx.dtnqBuildDTNavQuery( - navmesh.root - , maximumNodes - , ref query); - - if (NavUtil.Succeeded(status)) - resultQuery = new NavmeshQuery(query, false, AllocType.External); - else - resultQuery = null; - - return status; - } - - } -} diff --git a/critterai/.svn/pristine/d3/d3241643cbe339d07d3c75a5594a2d7374bd974a.svn-base b/critterai/.svn/pristine/d3/d3241643cbe339d07d3c75a5594a2d7374bd974a.svn-base deleted file mode 100644 index f94182ac..00000000 --- a/critterai/.svn/pristine/d3/d3241643cbe339d07d3c75a5594a2d7374bd974a.svn-base +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Represents the detailed and simplified versions of a contour. - * A contour is expected to always represent a simple polygon. - * (Convex or concave.) - *

      - * - * - *

      - * @see ContourSetBuilder - */ -public final class Contour -{ - /* - * Recast Reference: rcContour in Recast.h - */ - - /** - * The region associated with the contour. - */ - public final int regionID; - - /** - * The vertices which represent the raw (or detailed) contour. - *

      Vertices are clockwise wrapped in the form (x, y, z, regionID), - * where regionID is the external region the vertex is considered to be - * connected to.

      - */ - public final int[] rawVerts; - - /** - * The raw vertex count. (A convenience value.) - */ - public final int rawVertCount; - - /** - * The vertices which represent the simplified contour. - *

      Vertices are clockwise wrapped in the form (x, y, z, regionID), - * where regionID is the external region the vertex is considered to be - * connected to.

      - */ - public final int[] verts; - - /** - * The detail vertex count. (A convenience value.) - */ - public final int vertCount; - - /** - * Constructor - *

      All vertex lists are expected to be clockwise wrapped in - * the form (x, y, z, regionID), where regionID is the external - * region the vertex is considered to be connected to.

      - * @param regionID The region associated with the contour. - * @param rawList The vertices which represent the raw (or detailed) - * contour. - * @param vertList The vertices which represent the detailed contour. - * @throws IllegalArgumentException If either vertex list is null. - * The size of the vertex lists is not checked. - */ - public Contour(int regionID - , ArrayList rawList - , ArrayList vertList) - throws IllegalArgumentException - { - if (rawList == null || vertList == null) - throw new IllegalArgumentException( - "One or both vertex lists are null."); - - this.regionID = regionID; - - rawVerts = new int[rawList.size()]; - for (int i = 0; i < rawVerts.length; i++) - rawVerts[i] = rawList.get(i); - - rawVertCount = rawVerts.length / 4; - - verts = new int[vertList.size()]; - for (int i = 0; i < verts.length; i++) - verts[i] = vertList.get(i); - - vertCount = verts.length / 4; - } - -} diff --git a/critterai/.svn/pristine/d3/d36af851c32398aa9ed4299e648188e685d0f364.svn-base b/critterai/.svn/pristine/d3/d36af851c32398aa9ed4299e648188e685d0f364.svn-base deleted file mode 100644 index c8e4aaa1..00000000 --- a/critterai/.svn/pristine/d3/d36af851c32398aa9ed4299e648188e685d0f364.svn-base +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "DetourNavMeshQuery.h" -#include "DetourEx.h" - -extern "C" -{ - EXPORT_API dtQueryFilter* dtqfAlloc() - { - return new dtQueryFilter(); - } - - EXPORT_API void dtqfFree(dtQueryFilter* filter) - { - if (filter) - filter->~dtQueryFilter(); - } - - EXPORT_API void dtqfSetAreaCost(dtQueryFilter* filter - , const int index - , const float cost) - { - filter->setAreaCost(index, cost); - } - - EXPORT_API float dtqfGetAreaCost(dtQueryFilter* filter - , const int index) - { - return filter->getAreaCost(index); - } - - EXPORT_API void dtqfSetIncludeFlags(dtQueryFilter* filter - , const unsigned short flags) - { - filter->setIncludeFlags(flags); - } - - EXPORT_API unsigned short dtqfGetIncludeFlags(dtQueryFilter* filter) - { - return filter->getIncludeFlags(); - } - - EXPORT_API void dtqfSetExcludeFlags(dtQueryFilter* filter - , const unsigned short flags) - { - filter->setExcludeFlags(flags); - } - - EXPORT_API unsigned short dtqfGetExcludeFlags(dtQueryFilter* filter) - { - return filter->getExcludeFlags(); - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/d4/d412a6852572d899840b66ebd1ec88a18b17f097.svn-base b/critterai/.svn/pristine/d4/d412a6852572d899840b66ebd1ec88a18b17f097.svn-base deleted file mode 100644 index 0ddd63a6..00000000 --- a/critterai/.svn/pristine/d4/d412a6852572d899840b66ebd1ec88a18b17f097.svn-base +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// Applies flags to the polygons in a based on area assignment. - /// - /// - /// - /// This process will add the flags to all polygons assigned to the associated area. - /// Existing flags are not altered. - /// - /// - public sealed class AreaFlagMapper - : NMGenProcessor - { - private readonly byte[] mAreas; - private readonly ushort[] mFlags; - - private AreaFlagMapper(string name, int priority, byte[] areas, ushort[] flags) - : base(name, priority) - { - mAreas = areas; - mFlags = flags; - } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// The flags will be applied during the - /// state. - /// - /// - /// The current build state. - /// The context to process. - /// False on error, otherwise true. - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - if (state != NMGenState.PolyMeshBuild) - return true; - - PolyMesh mesh = context.PolyMesh; - PolyMeshData data = mesh.GetData(false); - - if (data.polyCount == 0) - return true; - - bool applied = false; - - for (int i = 0; i < mAreas.Length; i++) - { - byte area = mAreas[i]; - ushort flags = mFlags[i]; - - int marked = 0; - - for (int iPoly = 0; iPoly < data.polyCount; iPoly++) - { - if (data.areas[iPoly] == area) - { - data.flags[iPoly] |= flags; - marked++; - } - } - - if (marked > 0) - { - string msg = string.Format( - "{0} : Added '0x{1:X}' flag(s) to {2} poylgons assigned to area {3}." - , Name, flags, marked, area); - - context.Log(msg, this); - - applied = true; - } - } - - if (applied) - mesh.Load(data); - else - context.Log(Name + ": No flags applied.", this); - - return true; - } - - /// - /// Creates a new mapper. - /// - /// - /// - /// Will return null if parameters are invalid. Must have at least one valid area/flag map. - /// - /// - /// The processor name. - /// The processor priority. - /// The areas check for. - /// The flags to apply. - /// A new marker, or null on error. - public static AreaFlagMapper Create(string name, int priority, byte[] areas, ushort[] flags) - { - if (areas == null || flags == null || areas.Length != flags.Length - || !NMGen.IsValidAreaBuffer(areas, areas.Length)) - { - return null; - } - - return new AreaFlagMapper(name, priority - , (byte[])areas.Clone(), (ushort[])flags.Clone()); - } - } -} diff --git a/critterai/.svn/pristine/d4/d46fd28e0c2455e23571681cead91e26bd5031f9.svn-base b/critterai/.svn/pristine/d4/d46fd28e0c2455e23571681cead91e26bd5031f9.svn-base deleted file mode 100644 index 3b6b87f9..00000000 --- a/critterai/.svn/pristine/d4/d46fd28e0c2455e23571681cead91e26bd5031f9.svn-base +++ /dev/null @@ -1,3 +0,0 @@ -This directory contains 'singleton' assets. (One per project.) Various -editors will use the assets in this directory, automatically creating them -if they don't exist. diff --git a/critterai/.svn/pristine/d4/d49ad1148fdd6ee2a3429ac9b0369d1f8112b87f.svn-base b/critterai/.svn/pristine/d4/d49ad1148fdd6ee2a3429ac9b0369d1f8112b87f.svn-base deleted file mode 100644 index 94d75099..00000000 --- a/critterai/.svn/pristine/d4/d49ad1148fdd6ee2a3429ac9b0369d1f8112b87f.svn-base +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Used to generate static triangle meshes representing the traversable - * surfaces of arbitrary source geometry. - *

      When the build operation is provided with source geometry, several - * meshes are generated which represent the traversable (walkable) - * surfaces of the source geometry. A large number of configuration options - * are used to adjust the final result.

      - *

      - *

      - * @see Project Home - * @see Process Overview - * @see Configuration Options - */ -public final class NavmeshGenerator -{ - - /* - * Design notes: - * - * Recast reference: Sample_StatMeshSimple.cpp - * - * Configuration getters will not be added until they are needed. - * Do not add setters. The design is meant to be thread friendly and - * setters would compromise that. - * Never add getters for the builder fields. That would not be thread - * friendly. - */ - - // The builders used by this class. - private final SolidHeightfieldBuilder mSolidHeightFieldBuilder; - private final OpenHeightfieldBuilder mOpenHeightFieldBuilder; - private final ContourSetBuilder mContourSetBuilder; - private final PolyMeshFieldBuilder mPolyMeshBuilder; - private final DetailMeshBuilder mTriangleMeshBuilder; - - /** - * Constructor - * @param cellSize The width and depth resolution used when sampling - * the source mesh. - *

      Constraints: > 0

      - * - * @param cellHeight The height resolution used when sampling the - * source mesh. - *

      Constraints: > 0

      - * - * @param minTraversableHeight Represents the minimum floor to ceiling - * height that will still allow the floor area to be considered walkable. - *

      Permits detection of overhangs in the geometry which make the - * geometry below become unwalkable.

      - *

      Constraints: > 0

      - * - * @param maxTraversableStep Represents the maximum ledge height that - * is considered to still be walkable. - *

      Prevents minor deviations in height from improperly showing - * as obstructions. Permits detection of stair-like structures, curbs, etc. - *

      - *

      Constraints: >= 0

      - * - * @param maxTraversableSlope The maximum slope that is considered - * walkable. (Degrees) - *

      Constraints: 0 <= value <= 85

      - * - * @param clipLedges Indicates whether ledges should be marked - * as unwalkable. - *

      A ledge is a normally walkable voxel that has one or more - * accessible neighbors with a an un-steppable drop from voxel top to - * voxel top.

      - *

      E.g. If an agent using the navmesh were to travel down from the - * ledge voxel to its neighbor voxel, it would result in the maximum - * traversable step distance being violated. The agent cannot legally - * "step down" from a ledge to its neighbor.

      - * - * @param traversableAreaBorderSize Represents the closest any part of - * the navmesh can get to an obstruction in the source mesh. - *

      Usually set to the maximum bounding radius of entities utilizing - * the navmesh for navigation decisions.

      - *

      Constraints: >= 0

      - * - * @param smoothingThreshold The amount of smoothing to be performed - * when generating the distance field. - *

      This value impacts region formation and border detection. A - * higher value results in generally larger regions and larger border - * sizes. A value of zero will disable smoothing.

      - *

      Constraints: 0 <= value <= 4

      - * - * @param useConservativeExpansion Applies extra algorithms to regions - * to help prevent poorly formed regions from forming. - *

      If the navigation mesh is missing sections that should be present, - * then enabling this feature will likely fix the problem

      - *

      Enabling this feature significantly increased processing cost.

      - * - * @param minUnconnectedRegionSize The minimum region size for - * unconnected (island) regions. (Voxels) - *

      Any generated regions that are not connected to any other region - * and are smaller than this size will be culled before final navmesh - * generation. I.e. No longer considered walkable.

      - *

      Constraints: > 0

      - * - * @param mergeRegionSize Any regions smaller than this size will, if - * possible, be merged with larger regions. (Voxels) - *

      Helps reduce the number of unnecessarily small regions that can - * be formed. This is especially an issue in diagonal path regions - * where inherent faults in the region generation algorithm can result in - * unnecessarily small regions.

      - *

      If a region cannot be legally merged with a neighbor region, then - * it will be left alone.

      - *

      Constraints: >= 0

      - * - * @param maxEdgeLength The maximum length of polygon edges that - * represent the border of the navmesh. - *

      More vertices will be added to navmesh border edges if this value - * is exceeded for a particular edge. In certain cases this will reduce - * the number of thin, long triangles in the navmesh.

      - *

      A value of zero will disable this feature.

      - *

      Constraints: >= 0

      - * - * @param edgeMaxDeviation The maximum distance the edge of the navmesh - * may deviate from the source geometry. - *

      Setting this lower will result in the navmesh edges following the - * geometry contour more accurately at the expense of an increased - * triangle count.

      - *

      Setting the value to zero is not recommended since it can result - * in a large increase in the number of - * triangles in the final navmesh at a high processing cost.

      - *

      Constraints: >= 0

      - * - * @param maxVertsPerPoly The maximum number of vertices per polygon - * for polygons generated during the voxel to polygon conversion stage. - *

      Higher values reduce performance, but can also result in better - * formed triangles in the navmesh. A value of around 6 is generally - * adequate with diminishing returns for values higher than 6.

      - *

      Contraints: >= 3

      - * - * @param contourSampleDistance Sets the sampling distance to use when - * matching the navmesh to the surface of the original geometry. - *

      Impacts how well the final mesh conforms to the original - * geometry's surface contour. Higher values result in a navmesh which - * conforms more closely to the original geometry's surface at the cost - * of a higher final triangle count and higher processing cost.

      - *

      Setting this argument to zero will disable this functionality.

      - *

      Constraints: >= 0

      - * - * @param contourMaxDeviation The maximum distance the surface of the - * navmesh may deviate from the surface of the original geometry. - *

      The accuracy of the algorithm which uses this value is impacted - * by the value of the contour sample distance argument.

      - *

      The value of this argument has no meaning if the contour sample - * distance argument is set to zero.

      - *

      Setting the value to zero is not recommended since it can result - * in a large increase in the number of triangles in the final navmesh - * at a high processing cost.

      - *

      Constraints: >= 0

      - * - * @throws IllegalArgumentException If there are any unresolvable - * argument errors. (Most argument errors are avoided through value - * clamping and other auto-correction methods.) - * - * @see Detailed parameter information. - */ - public NavmeshGenerator(float cellSize - , float cellHeight - , float minTraversableHeight - , float maxTraversableStep - , float maxTraversableSlope - , boolean clipLedges - , float traversableAreaBorderSize - , int smoothingThreshold - , boolean useConservativeExpansion - , int minUnconnectedRegionSize - , int mergeRegionSize - , float maxEdgeLength - , float edgeMaxDeviation - , int maxVertsPerPoly - , float contourSampleDistance - , float contourMaxDeviation) - throws IllegalArgumentException - { - - // Convert certain values from world units to voxel units. - int vxMinTraversableHeight = 1; - if (minTraversableHeight != 0) - { - vxMinTraversableHeight = (int)Math.ceil( - Math.max(Float.MIN_VALUE, minTraversableHeight) / - Math.max(Float.MIN_VALUE, cellHeight)); - } - - int vxMaxTraversableStep = 0; - if (maxTraversableStep != 0) - { - vxMaxTraversableStep = (int)Math.ceil( - Math.max(Float.MIN_VALUE, maxTraversableStep) / - Math.max(Float.MIN_VALUE, cellHeight)); - } - - int vxTraversableAreaBorderSize = 0; - if (traversableAreaBorderSize != 0) - { - vxTraversableAreaBorderSize = (int)Math.ceil( - Math.max(Float.MIN_VALUE, traversableAreaBorderSize) / - Math.max(Float.MIN_VALUE, cellSize)); - } - - int vxMaxEdgeLength = 0; - if (maxEdgeLength != 0) - { - vxMaxEdgeLength = (int)Math.ceil( - Math.max(Float.MIN_VALUE, maxEdgeLength) / - Math.max(Float.MIN_VALUE, cellSize)); - } - - // Construct the solid field builder. - mSolidHeightFieldBuilder = new SolidHeightfieldBuilder(cellSize - , cellHeight - , vxMinTraversableHeight - , vxMaxTraversableStep - , maxTraversableSlope - , clipLedges); - - // Construct the open field builder. - // The order of the algorithms is the order they are applied. - ArrayList regionAlgorithms = - new ArrayList(); - if (vxTraversableAreaBorderSize > 0) - // Since there will be a boarder around all null regions, - // we can use the more efficient form of the algorithm. - regionAlgorithms.add(new CleanNullRegionBorders(true)); - else - regionAlgorithms.add(new CleanNullRegionBorders(false)); - regionAlgorithms.add(new FilterOutSmallRegions(minUnconnectedRegionSize - , mergeRegionSize)); - mOpenHeightFieldBuilder = new OpenHeightfieldBuilder( - vxMinTraversableHeight - , vxMaxTraversableStep - , vxTraversableAreaBorderSize - , smoothingThreshold - , SpanFlags.WALKABLE - , useConservativeExpansion - , regionAlgorithms); - - // Construct the contour set builder. - // The order of the algorithms is the order they are applied. - ArrayList contourAlgorithms = - new ArrayList(); - /* - * Note: Semi-converting edgeMaxDeviation to voxel unit. - * (It's still a float.) - * This is needed because the null region edges algorithm has no - * concept of world units. It only knows about the units it - * is passed, and it is being passed voxel sized units. - */ - contourAlgorithms.add( - new MatchNullRegionEdges(edgeMaxDeviation / cellSize)); - contourAlgorithms.add(new NullRegionMaxEdge(vxMaxEdgeLength)); - mContourSetBuilder = new ContourSetBuilder(contourAlgorithms); - - // Construct the polymesh and triange mesh builders. - mPolyMeshBuilder = new PolyMeshFieldBuilder(maxVertsPerPoly); - mTriangleMeshBuilder = new DetailMeshBuilder(contourSampleDistance - , contourMaxDeviation); - } - - /** - * Build a navigation mesh from the source geometry. - * @param vertices The source geometry vertices in the form (x, y, z) - * @param indices The triangle mesh vertices in the form - * (vertA, vertB, vertC), wrapped clockwise. - * @param outIntermediateData If non-null, the intermediate build - * results will be added to this object. If the build fails, the object - * will contain all intermediate results which were successfully generated. - * @return The generated navigation mesh, or null if generation failed. - * @see Process Overview - */ - public TriangleMesh build(float[] vertices - , int[] indices - , IntermediateData outIntermediateData) - { - - if (outIntermediateData != null) - outIntermediateData.reset(); - - long timerStart = 0; - - // Reference: Heightfield overview - // http://www.critterai.org/?q=nmgen_hfintro - - // Generate a height field representing obstructed (solid) space. - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final SolidHeightfield solidField = - mSolidHeightFieldBuilder.build(vertices, indices); - if (solidField == null || !solidField.hasSpans()) - return null; - - if (outIntermediateData != null) - outIntermediateData.voxelizationTime = - System.nanoTime() - timerStart; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setSolidHeightfield(solidField); - - /* - * Generate a heightfield representing the open space - * - * Instead of spans representing obstructed space, spans - * represent open space above obstructed space and between obstructions. - * - * Note: Only a partial build of the heightfield object is being - * performed here. - * The only reason for doing a partial build is for ease of prototyping. - * I.e. Can comment out portions of the height field build without - * touching the open heightfield builder class. - */ - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final OpenHeightfield openField = - mOpenHeightFieldBuilder.build(solidField, false); - if (openField == null) - return null; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setOpenHeightfield(openField); - - // Finish the build of the field. - // Order is important. - mOpenHeightFieldBuilder.generateNeighborLinks(openField); - mOpenHeightFieldBuilder.generateDistanceField(openField); - mOpenHeightFieldBuilder.blurDistanceField(openField); - mOpenHeightFieldBuilder.generateRegions(openField); - - if (outIntermediateData != null) - outIntermediateData.regionGenTime = System.nanoTime() - timerStart; - - // Terminology references: - // http://en.wikipedia.org/wiki/Polygon - // http://en.wikipedia.org/wiki riangulation_%28advanced_geometry%29 - - // Generate contours from the open heightfield's regions. - // Contours are simply polygons that represent the edges of regions. - - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final ContourSet contours = mContourSetBuilder.build(openField); - if (contours == null) - return null; - - if (outIntermediateData != null) - outIntermediateData.contourGenTime = System.nanoTime() - timerStart; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setContours(contours); - - // Generate a convex polygon mesh from the contours. - // Converts contours (simple polygons) to convex polygons. - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final PolyMeshField polyMesh = mPolyMeshBuilder.build(contours); - if (polyMesh == null) - return null; - - if (outIntermediateData != null) - outIntermediateData.polyGenTime = System.nanoTime() - timerStart; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setPolyMesh(polyMesh); - - // Triangulate the convex polygon mesh. This is where contour - // matching is performed. Also referred to as tesselation. - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - TriangleMesh mesh = mTriangleMeshBuilder.build(polyMesh, openField); - - if (outIntermediateData != null && mesh != null) - outIntermediateData.finalMeshGenTime = System.nanoTime() - timerStart; - - return mesh; - - } - -} diff --git a/critterai/.svn/pristine/d4/d4c5ca73a58bbc2a89d978847a0a4a5ebc12d023.svn-base b/critterai/.svn/pristine/d4/d4c5ca73a58bbc2a89d978847a0a4a5ebc12d023.svn-base deleted file mode 100644 index d94cff5d..00000000 --- a/critterai/.svn/pristine/d4/d4c5ca73a58bbc2a89d978847a0a4a5ebc12d023.svn-base +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Defines an axis aligned bounding box containing a grid based field. - *

      There are no enforced usage models for this class. But within this - * package the following standards apply:

      - *
        - *
      • The base (width/depth) of the field is defined by a grid of cells - * with a size of {@link #cellSize()}.
      • - *
      • Width of the field is associated with the x-axis and depth with - * the z-axis. So the width and depth of the field lies on the xz-plane.

        - *
      • The position of a cell is defined by an aggregate width/depth index - * obtained from {@link #gridIndex(int, int) gridIndex()}.
      • - *
      • The grid indices originate at the minimum bounds of the field.
      • - *
      • The height increment within each grid location is defined by the - * value of {@link #cellHeight()} - * and also originates at the field's minimum bounds.
      • - *
      • Sizing of the bounds and the values of cell size/height will be - * such that the bounds will not contain partial cells.
      • - *
      - *

      Warning: Behavior is undefined if the minimum bounds is set to be - * greater than the maximum bounds.

      - * @see Introduction to Height Fields - */ -public class BoundedField -{ - - /* - * Design notes: - * - * In most cases, performance trumps object safety. For example, the - * bounds getters return a reference to the internal bounds arrays in - * order to save on object creation costs. - * - * Setters are protected rather than public in order to allow implementing - * classes to control mutability. - * - * Recast Reference: None - */ - - private int mWidth; - private int mDepth; - private final float[] mBoundsMin = new float[3]; - private final float[] mBoundsMax = new float[3]; - private float mCellSize; - private float mCellHeight; - - /** - * Constructor - Default - *

      The bounds of the field will default to min(0, 0, 0) and - * max(1, 1, 1).

      - *

      The cell size and height will default to 0.1.

      - */ - public BoundedField() - { - resetBounds(); - resetCellInfo(); // Must call this after the bounds call. - } - - /** - * Constructor - Partial - *

      The bounds of the field will default to min(0, 0, 0) and - * max(1, 1, 1).

      - *

      The cell size and height values are auto-clamped to - * {@link Float#MIN_VALUE}.

      - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - */ - public BoundedField(float cellSize, float cellHeight) - { - mCellSize = Math.max(cellSize, Float.MIN_VALUE); - mCellHeight = Math.max(cellHeight, Float.MIN_VALUE); - calculateWidthDepth(); - } - - /** - * Constructor - Full - *

      The cell size and height values are auto-clamped to - * {@link Float#MIN_VALUE}.

      - *

      Warning: Behavior is undefined if the minimum bounds is set to - * be greater than the maximum bounds.

      - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - * @throws IllegalArgumentException If the bounds are null or the - * wrong size. - */ - public BoundedField(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize - , float cellHeight) - throws IllegalArgumentException - { - if (gridBoundsMax == null - || gridBoundsMin == null - || gridBoundsMax.length != 3 - || gridBoundsMin.length != 3) - throw new IllegalArgumentException( - "One or both bounds are invalid."); - - System.arraycopy(gridBoundsMin, 0, mBoundsMin, 0, 3); - System.arraycopy(gridBoundsMax, 0, mBoundsMax, 0, 3); - - mCellSize = Math.max(cellSize, Float.MIN_VALUE); - mCellHeight = Math.max(cellHeight, Float.MIN_VALUE); - - calculateWidthDepth(); - } - - /** - * The maximum bounds of the field in world units. - *

      Warning: A reference to the internal array is being returned, - * not a new array.

      - *

      Form: (maxX, maxY, maxZ)

      - */ - public final float[] boundsMax() { return mBoundsMax; } - - /** - * The minimum bounds of the field in world units. - *

      Warning: A reference to the internal array is being returned, - * not a new array.

      - *

      Form: (minX, minY, minZ)

      - *

      Considered the origin of the field.

      - */ - public final float[] boundsMin() { return mBoundsMin; } - - /** - * The height increment of the field. - */ - public final float cellHeight() { return mCellHeight; } - - /** - * The size of the cells. (The grid that forms the base of the field.) - */ - public final float cellSize() { return mCellSize; } - - /** - * Depth of the field in voxels. - *

      The maximum depth index for the field is equal to(depth - 1). - */ - public final int depth() { return mDepth; } - - /** - * Indicates whether or not the provided index values represent a - * valid cell location within - * the field. - * @param widthIndex The width index. - * @param depthIndex The depth index. - * @return TRUE if the width and depth indices are valid for the field. - * Otherwise FALSE. - */ - public final boolean isInBounds(int widthIndex, int depthIndex) - { - return (widthIndex >= 0 - && depthIndex >= 0 - && widthIndex < mWidth - && depthIndex < mDepth); - } - - /** - * Indicates whether or not the provided bounds overlaps the bounds of - * the current field. - *

      All tests are inclusive. So if there is an edge match, then the - * bounds overlap.

      - * @param boundsMin The minimum bounds of the field to test in the - * form (minX, minY, minZ). - * @param boundsMax The maximum bounds of the field to test in the - * form (maxX, maxY, maxZ). - * @return TRUE if the provided bounds overlaps the bounds of the - * current field. Otherwise FALSE. - */ - public final boolean overlaps(float[] boundsMin, float[] boundsMax) - { - boolean overlaps = true; - if (boundsMin == null - || boundsMax == null - || boundsMin.length != 3 - || boundsMax.length != 3) - return false; - // Keep the value of TRUE unless a non-overlap condition is found. - overlaps = (mBoundsMin[0] > boundsMax[0] - || mBoundsMax[0] < boundsMin[0]) ? false : overlaps; - overlaps = (mBoundsMin[1] > boundsMax[1] - || mBoundsMax[1] < boundsMin[1]) ? false : overlaps; - overlaps = (mBoundsMin[2] > boundsMax[2] - || mBoundsMax[2] < boundsMin[2]) ? false : overlaps; - return overlaps; - } - - /** - * Width of the field in voxels. - *

      The maximum width index for the field is equal to (width - 1).

      - */ - public final int width() { return mWidth; } - - - /** - * Generates a standardized grid index suitable for use in flattened - * storage arrays. - *

      Results in depth adjacent storage. (Cells at depth 0, Cells at - * depth 1, etc.)

      - * @param widthIndex The width index. - * @param depthIndex The depth index. - * @return A standardized grid index for the cell identified by the - * width and depth - * indices. If the width and depth combination is invalid for the - * field, a value of -1 will be returned. - */ - protected final int gridIndex(int widthIndex, int depthIndex) - { - /* - * Design notes: - * - * It is not uncommon during iteration processes, especially - * processes which are iterating on the edge of the bounds, that the - * width and depth indices may go out of range. While there would be - * a slight performance gain by leaving out the below argument - * validation, and require that callers be responsible for passing - * good values, experience indicates that this causes hard to find - * bugs. So instead, the validation is being performed here for - * all calls. - * - * Compare this algorithm to flattened vertex storage. - * This only involves different naming conventions. - * vertPointer = vertIndex * 3 + offset. - * Where: 3 is the number of values per vertex (the dimension) - * and 0 <= offset < vertex dimensions. - */ - if (widthIndex < 0 - || depthIndex < 0 - || widthIndex >= mWidth - || depthIndex >= mDepth) - return -1; - return widthIndex * mDepth + depthIndex ; - } - - /** - * Resets the bounds to min(0, 0, 0) and max(1, 1, 1). - */ - protected final void resetBounds() - { - mBoundsMin[0] = 0; - mBoundsMin[1] = 0; - mBoundsMin[2] = 0; - mBoundsMax[0] = 1; - mBoundsMax[1] = 1; - mBoundsMax[2] = 1; - calculateWidthDepth(); - } - - /** - * Reset the cell size and height values to 0.1. - */ - protected final void resetCellInfo() - { - mCellSize = 0.1f; - mCellHeight = 0.1f; - calculateWidthDepth(); - } - - /** - * Sets the bounds of the field. - *

      Warning: Behavior is undefined if the minimum bounds is greater - * than the maximum bounds.

      - * @param xmin The x-value for the minimum bounds. - * @param ymin The y-value for the minimum bounds. - * @param zmin The z-value for the minimum bounds. - * @param xmax The x-value for the maximum bounds. - * @param ymax The y-value for the maximum bounds. - * @param zmax The z-value for the maximum bounds. - */ - protected final void setBounds(float xmin, float ymin, float zmin - , float xmax, float ymax, float zmax) - { - mBoundsMin[0] = xmin; - mBoundsMin[1] = ymin; - mBoundsMin[2] = zmin; - mBoundsMax[0] = xmax; - mBoundsMax[1] = ymax; - mBoundsMax[2] = zmax; - calculateWidthDepth(); - } - - /** - * Sets the bounds of the field. - *

      Null values and arrays of length other than 3 are ignored.

      - *

      Warning: Behavior is undefined if the minimum bounds is greater - * than the maximum bounds.

      - * @param min The minimum bounds in the form (minX, minY, minZ). - * @param max The maximum bounds in the form (maxX, maxY, maxZ). - */ - protected final void setBounds(float[] min, float[] max) - { - if (min == null || max == null || min.length != 3 || max.length != 3) - return; - System.arraycopy(min, 0, mBoundsMin, 0, 3); - System.arraycopy(max, 0, mBoundsMax, 0, 3); - calculateWidthDepth(); - } - - /** - * Set the maximum bounds of the field. - *

      Null values and arrays of length other than 3 are ignored.

      - *

      Warning: Behavior is undefined if the new maximum bounds is less - * than the current minimum bounds.

      - * @param value The maximum bounds in the form (maxX, maxY, maxZ). - */ - protected final void setBoundsMax(float[] value) - { - if (value == null || value.length != 3) - return; - System.arraycopy(value, 0, mBoundsMax, 0, 3);; - calculateWidthDepth(); - } - - /** - * Set the minimum bounds of the field. - *

      Null values and arrays of length other than 3 are ignored.

      - *

      Warning: Behavior is undefined if the new minimum bounds is - * greater than the current maximum bounds.

      - * @param value The minimum bounds in the form (minX, minY, minZ). - */ - protected final void setBoundsMin(float[] value) - { - if (value == null || value.length != 3) - return; - System.arraycopy(value, 0, mBoundsMin, 0, 3); - calculateWidthDepth(); - } - - /** - * Set the cell height. - *

      The cell height value is clamped to {@link Float#MIN_VALUE}.

      - * @param value The new cell height. - */ - protected final void setCellHeight(float value) - { - mCellHeight = Math.max(value, Float.MIN_VALUE); - } - - /** - * Set the cell size. - *

      The cell size value is clamped to {@link Float#MIN_VALUE}.

      - * @param value The new cell size. - */ - protected final void setCellSize(float value) - { - mCellSize = Math.max(value, Float.MIN_VALUE); - calculateWidthDepth(); - } - - /** - * Sets the width and depth fields based on the current - * bounds and cell size. - */ - private void calculateWidthDepth() - { - mWidth = (int)((mBoundsMax[0] - mBoundsMin[0]) / mCellSize + 0.5f); - mDepth = (int)((mBoundsMax[2] - mBoundsMin[2]) / mCellSize + 0.5f); - } - - /** - * When used in conjunction with {@link #getDirOffsetWidth(int)}, gets a - * standard axis-neighbor direction offset that can be used for - * searching adjacent grid locations. - *

      The combined offset will be in the clockwise direction for - * direction 0 to 3, starting at (-1, 0).

      - *

      For example, if a direction value of 3 is passed to both this - * operation and {@link #getDirOffsetWidth(int)}, - * then the combined width/depth offset will be (0, -1).

      - * @param dir A value representing the direction to get the offset for. - * The value will be automatically constrained to a valid value between - * 0 and 3 inclusive using wrapping. E.g. A value of 4 will be - * automatically wrapped to 0, a value of 9 will be automatically - * wrapped to 1, etc. - * @return The standard offset for the provided direction. - * @see Neighbor Searches - */ - public static int getDirOffsetDepth(int dir) - { - final int offset[] = { 0, 1, 0, -1 }; - return offset[dir&0x03]; - } - - /** - * When used in conjunction with {@link #getDirOffsetDepth(int)}, gets a - * standard axis-neighbor direction offset that can be used for - * searching adjacent grid locations within the field. - *

      The combined offset will be in the clockwise direction for - * direction 0 to 3, starting at (-1, 0).

      - *

      For example, if a direction value of 3 is passed to both this - * operation and {@link #getDirOffsetDepth(int)}, then the combined - * width/depth offset will be (0, -1).

      - * @param dir A value representing the direction to get the offset for. - * The value will be automatically constrained to a valid value between - * 0 and 3 inclusive, using wrapping. E.g. A value of 4 will be - * automatically wrapped to 0, a value of 9 will be automatically wrapped - * to 1, etc. - * @return The standard offset for the provided direction. - * @see Neighbor Searches - */ - public static int getDirOffsetWidth(int dir) - { - final int offset[] = { -1, 0, 1, 0 }; - // All bits above 3 are discarded, constraining argument to 0 - 3; - return offset[dir&0x03]; - } - -} diff --git a/critterai/.svn/pristine/d5/d59f1c2326adaf09e23ee7e6f66facabdd50a25d.svn-base b/critterai/.svn/pristine/d5/d59f1c2326adaf09e23ee7e6f66facabdd50a25d.svn-base deleted file mode 100644 index c87bb491..00000000 --- a/critterai/.svn/pristine/d5/d59f1c2326adaf09e23ee7e6f66facabdd50a25d.svn-base +++ /dev/null @@ -1,508 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; -import static org.critterai.nmgen.OpenHeightFieldUtil.*; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; -import org.junit.Test; - -/** - * Tests the ability of {@link CleanNullRegionBorders} to detect - * and fix null regions that are fully encompassed by a single - * non-null region. - *

      This is a partial test of {@link CleanNullRegionBorders} - * functionality.

      - */ -public class EncompassedNullRegionTests -{ - - /* - * Design notes: - * - * These tests make assumptions on the way the OpenHeightField - * iterates. Specifically that it is a width first search. - * - * The "all span" searches inherently validate the detection of - * outer encompassing null regions. - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. Search restricted to null spans. (A) - */ - @Test - public void testEncompassedNullARestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionA(); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 2); - assertTrue(field.getData(0, 3).regionID() == 2); - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == 2); - assertTrue(field.getData(1, 3).regionID() == NULL_REGION); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(2, 0).regionID() == 2); - assertTrue(field.getData(2, 1).regionID() == 2); - assertTrue(field.getData(2, 2).regionID() == NULL_REGION); - assertTrue(field.getData(2, 3).regionID() == NULL_REGION); - assertTrue(field.getData(2, 4).regionID() == 2); - assertTrue(field.getData(3, 0).regionID() == 1); - assertTrue(field.getData(3, 1).regionID() == NULL_REGION); - assertTrue(field.getData(3, 2).regionID() == NULL_REGION); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 1); - assertTrue(field.getData(4, 1).regionID() == 1); - assertTrue(field.getData(4, 2).regionID() == 1); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - } - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. Search all spans. (A) - */ - @Test - public void testEncompassedNullA() - { - - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionA(); - - algo.apply(field); - - // field.printRegionField(); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 1); - assertTrue(field.getData(0, 3).regionID() == 1); - assertTrue(field.getData(0, 4).regionID() == 1); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == 1); - assertTrue(field.getData(1, 3).regionID() == NULL_REGION); - assertTrue(field.getData(1, 4).regionID() == 1); - assertTrue(field.getData(2, 0).regionID() == 2); - assertTrue(field.getData(2, 1).regionID() == 2); - assertTrue(field.getData(2, 2).regionID() == NULL_REGION); - assertTrue(field.getData(2, 3).regionID() == NULL_REGION); - assertTrue(field.getData(2, 4).regionID() == 1); - assertTrue(field.getData(3, 0).regionID() == 2); - assertTrue(field.getData(3, 1).regionID() == NULL_REGION); - assertTrue(field.getData(3, 2).regionID() == NULL_REGION); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == 2); - assertTrue(field.getData(4, 2).regionID() == 1); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search restricted to null spans. (A) - */ - @Test - public void testExternalNullRegionARestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search all spans. (A) - */ - @Test - public void testExternalNullRegionA() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search restricted to null spans. (A) - */ - @Test - public void testMultiRegionARestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - // On an inner corner. - field.getData(1, 2).setRegionID(2); - control.getData(1, 2).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search all spans. (A) - */ - @Test - public void testMultiRegionA() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - // On an inner corner. - field.getData(1, 2).setRegionID(2); - control.getData(1, 2).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. - * Search restricted to null spans. (B) - */ - @Test - public void testEncompassedNullBRestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionB(); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 2); - assertTrue(field.getData(0, 3).regionID() == 2); - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == NULL_REGION); - assertTrue(field.getData(1, 3).regionID() == 2); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(2, 0).regionID() == 1); - assertTrue(field.getData(2, 1).regionID() == NULL_REGION); - assertTrue(field.getData(2, 2) == null); - assertTrue(field.getData(2, 3).regionID() == 1); - assertTrue(field.getData(2, 4).regionID() == 1); - assertTrue(field.getData(3, 0).regionID() == 1); - assertTrue(field.getData(3, 1).regionID() == 1); - assertTrue(field.getData(3, 2) == null); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 1); - assertTrue(field.getData(4, 1).regionID() == NULL_REGION); - assertTrue(field.getData(4, 2) == null); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - assertTrue(field.getData(5, 0).regionID() == 1); - assertTrue(field.getData(5, 1).regionID() == 1); - assertTrue(field.getData(5, 2).regionID() == NULL_REGION); - assertTrue(field.getData(5, 3).regionID() == 1); - assertTrue(field.getData(5, 4).regionID() == 1); - assertTrue(field.getData(6, 0).regionID() == 1); - assertTrue(field.getData(6, 1).regionID() == 1); - assertTrue(field.getData(6, 2).regionID() == 1); - assertTrue(field.getData(6, 3).regionID() == 1); - assertTrue(field.getData(6, 4).regionID() == 1); - } - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. - * Search all spans. (B) - */ - @Test - public void testEncompassedNullB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionB(); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 1); - assertTrue(field.getData(0, 3).regionID() == 1); - assertTrue(field.getData(0, 4).regionID() == 1); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == NULL_REGION); - assertTrue(field.getData(1, 3).regionID() == 1); - assertTrue(field.getData(1, 4).regionID() == 1); - assertTrue(field.getData(2, 0).regionID() == 2); - assertTrue(field.getData(2, 1).regionID() == NULL_REGION); - assertTrue(field.getData(2, 2) == null); - assertTrue(field.getData(2, 3).regionID() == 1); - assertTrue(field.getData(2, 4).regionID() == 1); - assertTrue(field.getData(3, 0).regionID() == 2); - assertTrue(field.getData(3, 1).regionID() == 2); - assertTrue(field.getData(3, 2) == null); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == NULL_REGION); - assertTrue(field.getData(4, 2) == null); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - assertTrue(field.getData(5, 0).regionID() == 2); - assertTrue(field.getData(5, 1).regionID() == 2); - assertTrue(field.getData(5, 2).regionID() == NULL_REGION); - assertTrue(field.getData(5, 3).regionID() == 1); - assertTrue(field.getData(5, 4).regionID() == 1); - assertTrue(field.getData(6, 0).regionID() == 2); - assertTrue(field.getData(6, 1).regionID() == 2); - assertTrue(field.getData(6, 2).regionID() == 1); - assertTrue(field.getData(6, 3).regionID() == 1); - assertTrue(field.getData(6, 4).regionID() == 1); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search restricted to null spans. - * (B) - */ - @Test - public void testIntertedBRestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search all spans. - * (B) - */ - @Test - public void testIntertedB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search restricted to null regions. (B) - */ - @Test - public void testMultiRegionBRestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - // One an outer corner. - field.getData(5, 3).setRegionID(2); - control.getData(5, 3).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search all spans. (B) - */ - @Test - public void testMultiRegionB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - // One an outer corner. - field.getData(5, 3).setRegionID(2); - control.getData(5, 3).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * A null region fully encompassed by a single region. (RegionID = 1) - */ - private static OpenHeightfield getEncompassedNullRegionA() - { - /* - * W - * 0 1 2 3 4 - * --------- - * 4 | a a a a a - * 3 | a x x x a x - null region span - * D 2 | a a x x a a - region 1 span - * 1 | a a a x a All linked. - * 0 | a a a a a - * - */ - - float[] gridBoundsMin = { -1, -2, -3 }; - float[] gridBoundsMax = { 11, 12, 13 }; - - OpenHeightfield field = new OpenHeightfield(gridBoundsMin - , gridBoundsMax - , 0.2f - , 0.1f); - - for (int w = 0; w < 5; w++) - { - for (int d = 0; d < 5; d++) - { - OpenHeightSpan span = new OpenHeightSpan(w, d + 1); - span.setRegionID(1); - field.addData(w, d, span); - } - } - linkAllBaseSpans(field); - - field.getData(1, 3).setRegionID(NULL_REGION); - field.getData(2, 3).setRegionID(NULL_REGION); - field.getData(3, 3).setRegionID(NULL_REGION); - field.getData(2, 2).setRegionID(NULL_REGION); - field.getData(3, 2).setRegionID(NULL_REGION); - field.getData(3, 1).setRegionID(NULL_REGION); - - field.setRegionCount(2); - - return field; - } - - /** - * A null region fully encompassed by a single region. (RegionID = 1) - */ - private static OpenHeightfield getEncompassedNullRegionB() - { - /* - * W - * 0 1 2 3 4 5 6 7 - * --------------- - * 4 | a a a a a a a a - * 3 | a a a x a a a a x - null region span - * D 2 | a x v v v x a a v - null region, no span. - * 1 | a a x a x a a a a - region 1 span - * 0 | a a a a a a a a All linked. - * - */ - - float[] gridBoundsMin = { -1, -2, -3 }; - float[] gridBoundsMax = { 11, 12, 13 }; - - OpenHeightfield field = new OpenHeightfield(gridBoundsMin - , gridBoundsMax - , 0.2f - , 0.1f); - - for (int w = 0; w < 8; w++) - { - for (int d = 0; d < 5; d++) - { - if (w == 2 && d == 2 - || w == 3 && d == 2 - || w == 4 && d == 2) - continue; - OpenHeightSpan span = new OpenHeightSpan(w, d + 1); - span.setRegionID(1); - field.addData(w, d, span); - } - } - linkAllBaseSpans(field); - - field.getData(1, 2).setRegionID(NULL_REGION); - field.getData(2, 1).setRegionID(NULL_REGION); - field.getData(3, 3).setRegionID(NULL_REGION); - field.getData(4, 1).setRegionID(NULL_REGION); - field.getData(5, 2).setRegionID(NULL_REGION); - - field.setRegionCount(2); - - return field; - } - - /** - * Changes all {@link OpenHeightSpan#NULL_REGION} spans - * to "1" and all spans in region "1" to {@link OpenHeightSpan#NULL_REGION}. - */ - private static void invertRegion(OpenHeightfield field) - { - OpenHeightFieldIterator iter = field.dataIterator(); - - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (span.regionID() == NULL_REGION) - span.setRegionID(1); - else - span.setRegionID(NULL_REGION); - } - - } - -} diff --git a/critterai/.svn/pristine/d6/d62df07ea2237eeaa11212b6cfad27038064d643.svn-base b/critterai/.svn/pristine/d6/d62df07ea2237eeaa11212b6cfad27038064d643.svn-base deleted file mode 100644 index 9dc582c6..00000000 --- a/critterai/.svn/pristine/d6/d62df07ea2237eeaa11212b6cfad27038064d643.svn-base +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// Applies to - /// a . - /// - /// - /// - /// This is a system processor. - /// - /// - public sealed class LowObstaclesWalkable - : NMGenProcessor - { - internal const int ProcessorPriority = NMBuild.MinPriority - 100; - - private static LowObstaclesWalkable mInstance = new LowObstaclesWalkable(); - - private LowObstaclesWalkable() - : base(typeof(LowObstaclesWalkable).Name, ProcessorPriority) - { - } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// Will be applied during the state. - /// - /// - /// The current build state. - /// The context to process. - /// False on error, otherwise true. - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - if (state != NMGenState.HeightfieldBuild) - return true; - - if (context.Heightfield.MarkLowObstaclesWalkable(context - , context.Config.WalkableStep)) - { - context.Log(Name + ": Marked low obstacles as walklable.", this); - return true; - } - - context.Log(Name + ": Mark low obstacles failed.", this); - return false; - - } - - /// - /// The processor instance. - /// - public static LowObstaclesWalkable Instance { get { return mInstance; } } - } -} diff --git a/critterai/.svn/pristine/d7/d793a88af7bb76b5ebc69acd5e5aaa8ad815c0c0.svn-base b/critterai/.svn/pristine/d7/d793a88af7bb76b5ebc69acd5e5aaa8ad815c0c0.svn-base deleted file mode 100644 index 332545a4..00000000 --- a/critterai/.svn/pristine/d7/d793a88af7bb76b5ebc69acd5e5aaa8ad815c0c0.svn-base +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.interop -{ - /// - /// Indicates how an object's unmanaged resources have been allocated and are managed. - /// - public enum AllocType : byte - { - /// - /// Unmanaged resources were allocated locally and must be freed locally. - /// - Local = 0, - - /// - /// Unmanaged resources were allocated by an external library and a call must be made - /// to the library to free them. - /// - External = 1, - - /// - /// Unmanaged resources were allocated and are managed by an external library. There is - /// no local responsiblity to directly free the resources. - /// - /// - /// - /// Objects of this type are usually allocated and owned by another unmanaged object. So - /// its resources are freed by its owner when its owner is freed. - /// - /// - ExternallyManaged = 2 - } -} diff --git a/critterai/.svn/pristine/d8/d8f61e00680ef97ae441aa51312f43f75e72497f.svn-base b/critterai/.svn/pristine/d8/d8f61e00680ef97ae441aa51312f43f75e72497f.svn-base deleted file mode 100644 index be0b6a31..00000000 --- a/critterai/.svn/pristine/d8/d8f61e00680ef97ae441aa51312f43f75e72497f.svn-base +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild -{ - /// - /// A contiguous range of tiles, defined by tile grid indices. - /// - public struct TileZone - { - /// - /// The minimum x-index of the zone. - /// - public int xmin; - - /// - /// The mimimum z-index of the zone. - /// - public int zmin; - - /// - /// The maximum x-index of the zone. - /// - public int xmax; - - /// - /// The maximum z-index of the zone. - /// - public int zmax; - - /// - /// Constructor. - /// - /// The minimum x-index of the zone. - /// The mimimum z-index of the zone. - /// The maximum x-index of the zone. - /// The maximum z-index of the zone. - public TileZone(int xmin, int zmin, int xmax, int zmax) - { - this.xmin = xmin; - this.zmin = zmin; - this.xmax = xmax; - this.zmax = zmax; - } - - /// - /// The number of tiles along the x-axis. - /// - public int Width { get { return (xmax - xmin) + 1; } } - - /// - /// The number of tiles along the z-axis. - /// - public int Depth { get { return (zmax - zmin) + 1; } } - } -} diff --git a/critterai/.svn/pristine/d9/d93ba639f8558a1059b87b0fadb0d83c0f2d12e5.svn-base b/critterai/.svn/pristine/d9/d93ba639f8558a1059b87b0fadb0d83c0f2d12e5.svn-base deleted file mode 100644 index 9d6557e7..00000000 Binary files a/critterai/.svn/pristine/d9/d93ba639f8558a1059b87b0fadb0d83c0f2d12e5.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/d9/d9444742a5b897c6280724a49f57a8155517d21f.svn-base b/critterai/.svn/pristine/d9/d9444742a5b897c6280724a49f57a8155517d21f.svn-base deleted file mode 100644 index 700ad695..00000000 Binary files a/critterai/.svn/pristine/d9/d9444742a5b897c6280724a49f57a8155517d21f.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/db/db50a9a7d1809d45ddbaa145bf95d2eb01bc07e9.svn-base b/critterai/.svn/pristine/db/db50a9a7d1809d45ddbaa145bf95d2eb01bc07e9.svn-base deleted file mode 100644 index 974859d3..00000000 --- a/critterai/.svn/pristine/db/db50a9a7d1809d45ddbaa145bf95d2eb01bc07e9.svn-base +++ /dev/null @@ -1,14 +0,0 @@ -This directory contains the documentation source and build -artifacts. - -Sandcastle is used for the documentation build. - -The following tools are required: - -Sandcastle: http://sandcastle.codeplex.com/ -Sandcastle Help File Builder: http://shfb.codeplex.com/ - -Sandcastle Styles Patch - -http://sandcastlestyles.codeplex.com/ - Home Page -http://sandcastlestyles.codeplex.com/releases/view/47767 - Patch Used diff --git a/critterai/.svn/pristine/db/db8fbb7a6d59283e7e68218ce507c73114ef70cd.svn-base b/critterai/.svn/pristine/db/db8fbb7a6d59283e7e68218ce507c73114ef70cd.svn-base deleted file mode 100644 index ff82116d..00000000 --- a/critterai/.svn/pristine/db/db8fbb7a6d59283e7e68218ce507c73114ef70cd.svn-base +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - This topic covers some of the Unity specfic configuration settings found in the - T:NavmeshBuild asset. - - - - - - - See the NMGenParams documentation for information on the standard configuration settings. - - - - - - -
      - - Controls and Target Assignment - - - - - The upper portion of the inspector contains the main build controls and build target. - - - - - - - - The bake target is the asset that will get the result of the build. (The navigation mesh.) Any ScritableObject that - implements the T:org.critterai.nav.u3d.INavmeshData interface can be used. The normal - target will be a T:CAIBakedNavmesh asset. Note that this is a navigation asset, not an NMGen asset, - so it can be distributed as part of the project compile and be referenced by scene components. - - - - There are two types of builds. A standard build is performed directly from the inspector and will run a foreground build of the entire - navigation mesh. (Can't do anything else in the Unity editor until the build is complete.) The advanced build provides extra debug options, - background build capabilities, and the ability to partially rebuild multi-tile navigation meshes. The advanced build uses a special - editor window for the build. - - - - The Log Mesh State button will log the current state of the build target to the console. (Polygon count, bounds, etc.) - - - - The Build & Bake button will run a full build and bake of the navigation mesh in the foreground using the current scene as the input source. - (There will be a warning at the top of the inspector if the current scene is not the same as the last input scene.) - - - - If Trace is enabled, then detailed trace messages will be sent to the console. This is useful for debugging the build. - - - - -
      - -
      - - NMGen Configuration - - - - - - - - This section will not be avaiable if the build type is set to advanced. - - - - - - The configuration section contains the standard NMGen confiugration settings plus a some Unity specific options. - - - - - - - - The very first NMGen configuration settings you should take a look at are the Agent Settings. - Most other settings are derived, at least in part, from these. Unlike the NMGenParams core class, these agent settings are in world - units, not cell units. Set the values based on your agent maximums. (Maximum height, maximum radius, etc.) - - - - The next settings you'll want to take a look at are the Resolution and Tile Settings. You can derive these yourself with the help of - the NMGenParams documentation. But if you've already set up the scene you can use the Derive button to get a good starting point. - The values will be derived based on a combination of the agent settings and bounds of the input geometry. - - - - - - - A Tile Size of zero results in a single tile mesh. - - - - - - There are various toggle options in the Advanced configuration section. These will automatically add NMGen processors to the build as follows: - - - - Ledges Not Walkable -> T:org.critterai.nmbuild.FilterLedgeSpans - Low Height Not Walkable -> T:org.critterai.nmbuild.FilterLowHeightSpans - Low Obstacles Walkable -> T:org.critterai.nmbuild.LowObstaclesWalkable - Apply Poly Flag -> T:org.critterai.nmbuild.ApplyPolygonFlags (Flag: 0x01) - - - - If you don't need a lot of height detail in your navigation mesh you can uncheck the Include Detail Mesh option. This will - make the final navigation mesh more memory efficient. - - - - The Clean button can be used to round values to more reasonable values. (E.g. 0.2929384839 to 0.29) - - - - The Reset button will reset the NMGen configuration to its original default values. - - - - -
      - -
      - - Input Configuration - - - - - The input configuration contains the scene query and processor asset assignments. - - - - - - - - The assets assigned in this section can be created using menu items founds under CritterAI -> Create NMGen Assets. Note that some - assets are effectively singletons with no configuration. In such cases there is no need to create more than one per project; and the inspector won't let - you add them twice to the same build. - - - - It is perfectly fine to share scene query and input processors between multiple T:NavmeshBuild assets. - - - - The most common scene query is T:TagSceneQuery. The scene query is optional. If none is provided then - the search will be global. E.g. All MeshFilters in the scene, all terrains in the scene, etc. - - - - There must be at least one input processor for the build. For simple builds this is usually a compiler. The most commonly used compiler is - T:MeshCompiler. You can add as many processors as you wish. The processors will be run in - ascending priority. This is especially useful for area assignment since it allows higher priority areas to overwrite lower priority areas. - - - - The inspector won't let you add the the same input processor asset to a build twice. - - - - The Auto-Clean option is used to automatically clean up invalid triangles in the input geometry. Sometimes modeling programs can let invalid triangles slip in; - triangles that are no problem for the renderer but cause problems for NMGen. For example, triangles that contain the same vertex twice will be removed. - - - - -
      - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/db/dbff15eac49f4393107659759d83868b1b62c23d.svn-base b/critterai/.svn/pristine/db/dbff15eac49f4393107659759d83868b1b62c23d.svn-base deleted file mode 100644 index 8ffe3cb3..00000000 --- a/critterai/.svn/pristine/db/dbff15eac49f4393107659759d83868b1b62c23d.svn-base +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using org.critterai.u3d; - -/// -/// Represents an off-mesh connection used during the NMGen build process. -/// -[ExecuteInEditMode] -public sealed class OFMConnection - : NMGenComponent -{ - [SerializeField] - private Vector3 mEnd; - - [SerializeField] - private float mRadius = 1.0f; - [SerializeField] - private bool mIsBidirectional; - - [SerializeField] - private bool mOverrideArea; - - [SerializeField] - private byte mArea = MaxArea; - - [SerializeField] - private int mUserId; - - [SerializeField] - private int mFlags = 1; - - /// - /// The connection start point. - /// - public Vector3 StartPoint { get { return transform.position; } } - - /// - /// The connection end point. - /// - public Vector3 EndPoint - { - get { return mEnd; } - set { mEnd = value; } - } - - /// - /// The connection point radii. - /// - public float Radius - { - get { return mRadius; } - set { mRadius = Mathf.Max(0, value); } - } - - /// - /// True if the conneciton can be traversed in both directions, or false if only traversable - /// from the start to the end point. - /// - public bool IsBidirectional - { - get { return mIsBidirectional; } - set { mIsBidirectional = value; } - } - - /// - /// True if the locally defined area should be applied to the connection, or false if - /// the build's default area should be used. - /// - public bool OverrideArea - { - get { return mOverrideArea; } - set { mOverrideArea = value; } - } - - /// - /// The area to apply to the connection. - /// - public byte Area - { - get { return mArea; } - set { mArea = ClampArea(value); } - } - - /// - /// The connection flags. - /// - public ushort Flags - { - get { return (ushort)mFlags; } - set{ mFlags = value; } - } - - /// - /// The connection user id. [Limit: >= 0] - /// - public int UserId - { - get { return mUserId; } - set { mUserId = Mathf.Max(0, value); } - } - - void OnRenderObject() - { - if (!debugEnabled && !debugEnabledLocal) - return; - - Vector3 pos = transform.position; - - const float markerScale = 0.5f; - - // The color for area zero is hard to see. So using black. - Color color = (Area == 0 ? new Color(0, 0, 0, 0.8f) : ColorUtil.IntToColor(Area, 0.8f)); - - DebugDraw.SimpleMaterial.SetPass(0); - - GL.Begin(GL.LINES); - - GL.Color(color); - - DebugDraw.AppendXMarker(pos, markerScale); - DebugDraw.AppendCircle(pos, mRadius); - - DebugDraw.AppendArc(pos, mEnd, 0.25f - , (mIsBidirectional ? 0.6f : 0) - , 0.6f); - - DebugDraw.AppendCircle(mEnd, mRadius); - - GL.End(); - } -} diff --git a/critterai/.svn/pristine/dc/dc9228dd0730c3c4a13a8c05d40584ff88f70cea.svn-base b/critterai/.svn/pristine/dc/dc9228dd0730c3c4a13a8c05d40584ff88f70cea.svn-base deleted file mode 100644 index 7afd166a..00000000 --- a/critterai/.svn/pristine/dc/dc9228dd0730c3c4a13a8c05d40584ff88f70cea.svn-base +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Loads and compiles all and -/// components in the scene, based on the standard scene query behavior. (Editor Only) -/// -public sealed class AreaMarkerCompiler - : ScriptableObject, IInputBuildProcessor -{ - /// - /// The priority of the processor. - /// - public int Priority { get { return NMBuild.MinPriority; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// Duplicates not allowed. (Always false.) - /// - public bool DuplicatesAllowed { get { return false; } } - - /// - /// Processes the context. - /// - /// - /// - /// Processes during the - /// and states. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (context != null) - { - switch (state) - { - case InputBuildState.CompileInput: - - Compile(context); - break; - - case InputBuildState.LoadComponents: - - Load(context); - break; - } - } - - return true; - } - - private void Load(InputBuildContext context) - { - context.info.loaderCount++; - - int count = context.LoadFromScene(); - - context.Log(string.Format("Loaded {0} area markers.", count), this); - } - - private void Compile(InputBuildContext context) - { - context.info.compilerCount++; - - List items = context.components; - - int count = 0; - - // The components can't provide the processor directly because processors are editor-only. - - foreach (Component item in items) - { - if (item is CylinderAreaMarker) - { - CylinderAreaMarker.MarkerData data = ((CylinderAreaMarker)item).GetMarkerData(); - - AreaCylinderMarker processor = AreaCylinderMarker.Create(item.name - , data.priority - , data.area - , data.centerBase - , data.radius - , data.height); - - context.processors.Add(processor); - - count++; - } - else if (item is BoxAreaMarker) - { - BoxAreaMarker.MarkerData data = ((BoxAreaMarker)item).GetMarkerData(); - - AreaConvexMarker processor = AreaConvexMarker.Create(item.name - , data.priority - , data.area - , data.verts - , data.ymin - , data.ymax); - - context.processors.Add(processor); - - count++; - } - } - - context.Log(string.Format("Loaded {0} area markers.", count), this); - } -} diff --git a/critterai/.svn/pristine/dd/ddc4e67d8c479c8e3f263729d98d5d14b8289688.svn-base b/critterai/.svn/pristine/dd/ddc4e67d8c479c8e3f263729d98d5d14b8289688.svn-base deleted file mode 100644 index c4574432..00000000 --- a/critterai/.svn/pristine/dd/ddc4e67d8c479c8e3f263729d98d5d14b8289688.svn-base +++ /dev/null @@ -1,1157 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.MathUtil.EPSILON_STD; - -/** - * Represents a mutable 3-dimensional vector. - *

      Contains various static operations applicable to 3D vectors.

      - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, no divide by zero checks, etc.

      - *

      All operations support the use of the same object reference in multiple arguments. - * For example: Vector3.normalize(vectorArray, 1, vectorArray, 1) will normalize the vector at - * position 1 in the vectorArray.

      - *

      Instances of this class are not thread safe. Static operations are thread safe.

      - */ -public class Vector3 -{ - - /** - * The x-value for the vector (x, y, z). - */ - public float x; - - /** - * The y-value for the vector (x, y, z). - */ - public float y; - - - /** - * The z-value for the vector (x, y, z). - */ - public float z; - - /** - * Constructor for the vector (0, 0, 0). (Default) - */ - public Vector3() - { - x = 0.0f; - y = 0.0f; - z = 0.0f; - } - - /** - * Constructor. - * @param x The x-value for the vector (x, y, z). - * @param y The y-value for the vector (x, y, z). - * @param z The z-value for the vector (x, y, z). - */ - public Vector3(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - } - - /** - * Constructs a vector from an array entry. - * @param vectorArray An array of vectors in the form (x, y, z). - * @param index The index of the vector entry to use. The expected stride is three. - * So the extraction point will be index*3. - * @throws IllegalArgumentException If the array size or index is invalid. - */ - public Vector3(float[] vectorArray, int index) - throws IllegalArgumentException - { - if (vectorArray == null || index*3+2 >= vectorArray.length) - throw new IllegalArgumentException("Invalid array or index."); - x = vectorArray[index*3]; - y = vectorArray[index*3+1]; - z = vectorArray[index*3+2]; - } - - /** - * Adds the provided vector to this vector. - *

      The values of this vector are mutated.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param z The z-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector3 add(float x, float y, float z) - { - this.x += x; - this.y += y; - this.z += z; - return this; - } - - /** - * Adds the provided vector to this vector. - *

      The values of this vector are mutated.

      - * @param v The vector to add to this vector. - * @return A reference to this vector. - */ - public Vector3 add(Vector3 v) - { - return add(v.x, v.y, v.z); - } - - /** - * Divides this vector by the provided value. - *

      The values of this vector are mutated.

      - * @param byValue The value to divide the elements of this vector by. - * @return A reference to this vector. - */ - public Vector3 divide(float byValue) - { - this.x /= byValue; - this.y /= byValue; - this.z /= byValue; - return this; - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param x The x-value for the vector (x, y, z). - * @param y The y-value for the vector (x, y, z). - * @param z The z-value for the vector (x, y, z). - * @return The dot product of this vector and the provided vector. - */ - public float dot(float x, float y, float z) - { - return (this.x * x) + (this.y * y) + (this.z * z); - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param v The vector. - * @return The dot product of this vector and the provided vector. - */ - public float dot(Vector3 v) - { - return dot(v.x, v.y, v.z); - } - - /** - * Determines whether or not this vector is equal to the provided vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(float x, float y, float z) - { - - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(x) - || Float.floatToIntBits(this.y) != Float.floatToIntBits(y) - || Float.floatToIntBits(this.z) != Float.floatToIntBits(z)) - return false; - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Vector3)) return false; - Vector3 other = (Vector3) obj; - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.getX())) - return false; - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.getY())) - return false; - if (Float.floatToIntBits(z) != Float.floatToIntBits(other.getZ())) - return false; - return true; - } - - /** - * Determines whether or not this vector is equal to the provided vector. - *

      This operation is slightly faster than the {@link #equals(Object)} form.

      - * @param v The vector to compare to. (A value of null will result in a runtime error.) - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(Vector3 v) - { - return equals(v.x, v.y, v.z); - } - - /** - * Inserts the content of this vector into the specified array. - *

      Warning: No argument validations are performed.

      - * @param out The array to insert the vector into. - * @param outIndex The insertion point. The expected stride is 3. So the insertion - * point will be outIndex*3. - * @return A reference to the out argument. - */ - public float[] get(float[] out, int outIndex) - { - out[outIndex*3] = x; - out[outIndex*3+1] = y; - out[outIndex*3+2] = z; - return out; - } - - /** - * The x-value for this vector. - * @return The x-value for this vector. - */ - public float getX() { return x; } - - /** - * The y-value for this vector. - * @return The y-value for this vector. - */ - public float getY() { return y; } - - /** - * The z-value for this vector. - * @return The z-value for this vector. - */ - public float getZ() { return z; } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(x); - result = prime * result + Float.floatToIntBits(y); - result = prime * result + Float.floatToIntBits(z); - return result; - } - - /** - * Returns TRUE if the length of this vector is zero. - * @return TRUE if the length of this vector is zero. Otherwise FALSE. - */ - public boolean isZeroLength() - { - return (x == 0 && y == 0 && z == 0); - } - - /** - * Returns the square of this vector's length. (length * length) - * @return The square of this vector's length. - */ - public float lengthSq() - { - return (x * x) + (y * y) + (z * z); - } - - /** - * Multiplies (scales) this vector by the provided value. - *

      The values of this vector are mutated.

      - * @param byValue The value to multiply the elements of this vector by. - * @return A reference to this vector. - */ - public Vector3 multiply(float byValue) - { - this.x *= byValue; - this.y *= byValue; - this.z *= byValue; - return this; - } - - /** - * Normalizes this vector such that its length is one. - *

      The values of this vector are mutated.

      - *

      WARNING: This is a costly operation

      - * @return A reference to this vector. - */ - public Vector3 normalize() - { - float length = (float)Math.sqrt((x * x) + (y * y) + (z * z)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - z /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - if (Math.abs(z) < EPSILON_STD) - z = 0; - - return this; - } - - /** - * Scales this vector to the provided length. - *

      The values of this vector are mutated.

      - *

      WARNING: This is a costly operation.

      - * @param length The length to scale the vector to. - * @return A reference to this vector. - */ - public Vector3 scaleTo(float length) - { - if (length == 0 || isZeroLength()) - { - x = 0; - y = 0; - z = 0; - return this; - } - return multiply(length / (float)(Math.sqrt((x * x) + (y * y) + (z * z)))); - } - - /** - * Sets the values for this vector. - * @param x The x-value for this vector. - * @param y The y-value for this vector. - * @param z The z-value for this vector. - * @return A reference to this vector. - */ - public Vector3 set(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - /** - * Sets the values for this vector to match the provided vector. - * @param v The vector to match this vector to. - * @return A reference to this vector. - */ - public Vector3 set(Vector3 v) - { - x = v.x; - y = v.y; - z = v.z; - return this; - } - - /** - * Sets the x-value for this vector. - * @param value The new x-value for this vector. - */ - public void setX(float value) { x = value; } - - /** - * Sets the y-value for this vector. - * @param value The new y-value for this vector. - */ - public void setY(float value) { y = value; } - - /** - * Sets the z-value for this vector. - * @param value The new z-value for this vector. - */ - public void setZ(float value) { z = value; } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of the elements of this vector. - *

      The vectors are considered equal if the following condition is met: - * (vx >= x - tolerance && vx <= x + tolerance) - * && (vy >= y - tolerance && vy <= y + tolerance) - * && (vz >= z - tolerance && vz <= z + tolerance)

      - * @param vx The x-value for the vector (vx, vy, vz). - * @param vy The y-value for the vector (vx, vy, vz). - * @param vz The z-value for the vector (vx, vy, vz). - * @param tolerance The tolerance for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(float vx, float vy, float vz, float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < x - tolerance || vx > x + tolerance) - return false; - if (vy < y - tolerance || vy > y + tolerance) - return false; - if (vz < z - tolerance || vz > z + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of the elements of this vector. - *

      The vectors are considered equal if the following condition is met: - * (vx >= x - tolerance && vx <= x + tolerance) - * && (vy >= y - tolerance && vy <= y + tolerance) - * && (vz >= z - tolerance && vz <= z + tolerance)

      - * @param v The vector to compare against. - * @param tolerance The tolerance for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(Vector3 v, float tolerance) - { - return sloppyEquals(v.x, v.y, v.z, tolerance); - } - - /** - * Subtracts the provided vector from this vector. (this - providedVector) - *

      The values of this vector are mutated.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector3 subtract(float x, float y, float z) - { - this.x -= x; - this.y -= y; - this.z -= z; - return this; - } - - /** - * Subtracts the provided vector from this vector. (this - v) - *

      The values of this vector are mutated.

      - * @param v The vector to subtract from this vector. - * @return A reference to this vector. - */ - public Vector3 subtract(Vector3 v) - { - return subtract(v.x, v.y, v.z); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { return "(" + x + ", " + y + ", " + z + ")"; } - - /** - * Truncates the length of the vector to the provided value. - *

      The values of this vector are mutated.

      - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param maxLength The maximum allowed length of the resulting vector. - * @return A reference to this vector. - */ - public Vector3 truncateLength(float maxLength) - { - if (isZeroLength()) - return this; - if (maxLength == 0) - { - set(0, 0, 0); - return this; - } - float mlsq = maxLength * maxLength; - float csq = (x * x) + (y * y) + (z * z); - if (csq > mlsq) - multiply((float)(maxLength / Math.sqrt(csq))); - return this; - } - - /** - * Adds the vectors (ux, uy, uz) and (vx, vy, vz). - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(float ux, float uy, float uz - , float vx, float vy, float vz - , Vector3 out) - { - out.set(ux + vx, uy + vy, uz + vz); - return out; - } - - /** - * Adds the value to all elements of the vector. - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param value The value to add to each of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(float x, float y, float z, float value, Vector3 out) - { - out.set(x + value, y + value, z + value); - return out; - } - - /** - * Adds the value to all elements of the vector. - * @param v The vector to add the value to. - * @param value The value to add to each of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(Vector3 v, float value, Vector3 out) - { - return add(v.x, v.y, v.z, value, out); - } - - /** - * Adds the two provided vectors. - * @param u Vector u - * @param v Vector v - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(Vector3 u, Vector3 v, Vector3 out) - { - return add(u.x, u.y, u.z, v.x, v.y, v.z, out); - } - - /** - * Performs a vector "righthanded" cross product. (u x v) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - *

      WARNING: No argument validations are peformed.

      - * @param vx The x-value of the vector (ux, uy, uz). - * @param vy The y-value of the vector (ux, uy, uz). - * @param vz The z-value of the vector (ux, uy, uz). - * @param ux The x-value of the vector (vx, vy, vz). - * @param uy The y-value of the vector (vx, vy, vz). - * @param uz The z-value of the vector (vx, vy, vz). - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result. The expected stride is three, so the - * insertion point will be outIndex*3. - * @return A reference to the out array. - */ - public static float[] cross( - float ux, float uy, float uz - , float vx, float vy, float vz - , float[] out - , int outIndex) - { - out[outIndex*3] = uy * vz - uz * vy; - out[outIndex*3+1] = -ux * vz + uz * vx; - out[outIndex*3+2] = ux * vy - uy * vx; - return out; - } - - /** - * Performs a vector "righthanded" cross product. (u x v) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 cross( - float ux, float uy, float uz - , float vx, float vy, float vz - , Vector3 out) - { - out.x = uy * vz - uz * vy; - out.y = -ux * vz + uz * vx; - out.z = ux * vy - uy * vx; - return out; - } - - /** - * Performs a vector "righthanded" cross product. (vectorA x vectorB) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - *

      WARNING: No argument validations are performed.

      - *

      All arrays are expected to have a stride of three. So vectors in an array - * are located at index*3.

      - * @param vectorsA An array of vectors in the form (x, y, z). - * @param vectorAIndex The index of vectorA within the vectorsA array. - * @param vectorsB An array of vectors in the form (x, y, z). - * @param vectorBIndex The index of vectorB within the vectorsB array. - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index in the out array to insert the result into. - * @return A reference to the out array. - */ - public static float[] cross(float[] vectorsA - , int vectorAIndex - , float[] vectorsB - , int vectorBIndex - , float[] out - , int outIndex) - { - return cross(vectorsA[vectorAIndex*3] - , vectorsA[vectorAIndex*3+1] - , vectorsA[vectorAIndex*3+2] - , vectorsB[vectorBIndex*3] - , vectorsB[vectorBIndex*3+1] - , vectorsB[vectorBIndex*3+2] - , out - , outIndex); - } - - /** - * Performs a vector "righthanded" cross product. (u x v) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - * @param u Vector U - * @param v Vector V - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 cross(Vector3 u, Vector3 v, Vector3 out) - { - return cross(u.x, u.y, u.z - , v.x, v.y, v.z - , out); - } - - /** - * Divides all elements of the vector by the provided value. - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 divide(float x, float y, float z, float byValue, Vector3 out) - { - out.set(x / byValue, y / byValue, z / byValue); - return out; - } - - /** - * Divides all elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 divide(Vector3 v, float byValue, Vector3 out) - { - return divide(v.x, v.y, v.z, byValue, out); - } - - /** - * Returns the dot product of the provided vectors. - *

      If you need to dot two vector objects, use {@link #dot(Vector3)}. - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @return The dot product of the provided vectors. - */ - public static float dot(float ux, float uy, float uz - , float vx, float vy, float vz) - { - return (ux * vx) + (uy * vy) + (uz * vz); - } - - /** - * Inserts the provided vectors into the out array. - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outStartIndex The vector index in the out array to start the insertion at. - * The expected stride is three, so insertion will start at outStartIndex*3. - * @param vectors The vectors to insert into the out array. There can be no nulls - * in this list. - * @return A reference to the out array. - */ - public static float[] flatten(float[] out, int outStartIndex, Vector3... vectors) - { - - outStartIndex *= 3; // Convert to pointer. - for (Vector3 v : vectors) - { - out[outStartIndex] = v.x; - out[outStartIndex+1] = v.y; - out[outStartIndex+2] = v.z; - outStartIndex += 3; - } - return out; - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param ax The x-value of the point (ax, ay, az). - * @param ay The y-value of the point (ax, ay, az). - * @param az The z-value of the point (ax, ay, az). - * @param bx The x-value of the point (bx, by, bz). - * @param by The y-value of the point (bx, by, bz). - * @param bz The z-value of the point (bx, by, bz). - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(float ax, float ay, float az - , float bx, float by, float bz) - { - float dx = ax - bx; - float dy = ay - by; - float dz = az - bz; - return (dx * dx + dy * dy + dz * dz); - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param a Point A - * @param b Point B - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(Vector3 a, Vector3 b) - { - return getDistanceSq(a.x, a.y, a.z, b.x, b.y, b.z); - } - - /** - * Returns the square of the length of the vector. (length * length) - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @return The square of the length of the vector. - */ - public static float getLengthSq(float x, float y, float z) - { - return (x * x + y * y + z * z); - } - - /** - * Gets the square of the length of a vector entry in an array. - *

      WARNINg: No validations are peformed on the out array or outIndex.

      - * @param vectors An array of vectors in the form (x, y, z) - * @param vectorIndex The index of the vector to get the length of. Stride expected is three, so - * the vector is expected to be located at vectorIndex*3. - * @return The square of the length of the vector entry in the array. - */ - public static float getLengthSq(float[] vectors, int vectorIndex) - { - return (vectors[vectorIndex*3] * vectors[vectorIndex*3]) - + (vectors[vectorIndex*3+1] * vectors[vectorIndex*3+1]) - + (vectors[vectorIndex*3+2] * vectors[vectorIndex*3+2]); - } - - /** - * Multiplies all elements of the vector by the provided value. - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 multiply(float x, float y, float z, float byValue, Vector3 out) - { - out.set(x * byValue, y * byValue, z * byValue); - return out; - } - - /** - * Multiplies all elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 multiply(Vector3 v, float byValue, Vector3 out) - { - return multiply(v.x, v.y, v.z, byValue, out); - } - - /** - * Normalizes the vector and stores the result - * at the specified location within the out array. - *

      WARNINg: No argument validations are peformed.

      - *

      WARNING: This is a costly operation

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result at. The stride is three, so - * the insertion point in out will be outIndex*3. - * @return A reference to the out array. - */ - public static float[] normalize(float x, float y, float z - , float[] out - , int outIndex) - { - float length = (float)Math.sqrt((x * x) + (y * y) + (z * z)); - if (length <= EPSILON_STD) - length = 1; - - int pOut = outIndex*3; - - out[pOut] = x / length; - out[pOut+1] = y / length; - out[pOut+2] = z / length; - - if (Math.abs(out[pOut]) < EPSILON_STD) - out[pOut] = 0; - if (Math.abs(out[pOut+1]) < EPSILON_STD) - out[pOut+1] = 0; - if (Math.abs(out[pOut+2]) < EPSILON_STD) - out[pOut+2] = 0; - - return out; - - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

      WARNING: This is a costly operation

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 normalize(float x, float y, float z, Vector3 out) - { - float length = (float)Math.sqrt(getLengthSq(x, y, z)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - z /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - if (Math.abs(z) < EPSILON_STD) - z = 0; - - out.set(x, y, z); - - return out; - } - - /** - * Normalizes the vector from the vectors array and stores the result - * at the specified location within the out array. - *

      WARNING: No argument validations are peformed.

      - *

      All arrays are expected to have a stride of three. So vectors in the array - * are located at index*3. - *

      WARNING: This is a costly operation

      - * @param vectors An array of vectors in the form (x, y, z). - * @param vectorIndex The vector index of the vector to be normalized. - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result at. - * @return A reference to the out array. - */ - public static float[] normalize(float[] vectors - , int vectorIndex - , float[] out - , int outIndex) - { - - float length = (float)Math.sqrt(getLengthSq(vectors, vectorIndex)); - if (length <= EPSILON_STD) - length = 1; - - int pOut = outIndex*3; - - out[pOut] = vectors[vectorIndex*3] / length; - out[pOut+1] = vectors[vectorIndex*3+1] / length; - out[pOut+2] = vectors[vectorIndex*3+2] / length; - - if (Math.abs(out[pOut]) < EPSILON_STD) - out[pOut] = 0; - if (Math.abs(out[pOut+1]) < EPSILON_STD) - out[pOut+1] = 0; - if (Math.abs(out[pOut+2]) < EPSILON_STD) - out[pOut+2] = 0; - - return out; - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

      WARNING: This is a costly operation

      - * @param v The vector to normalize. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 normalize(Vector3 v, Vector3 out) - { - return normalize(v.x, v.y, v.z, out); - } - - /** - * Scales the vector to the provided length. - *

      WARNING: This is a costly operation.

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 scaleTo(float x, float y, float z, float length, Vector3 out) - { - if (length == 0 || (x == 0 && y == 0 && z == 0)) - { - out.set(0, 0, 0); - return out; - } - return multiply(x, y, z - , (length / (float)(Math.sqrt(getLengthSq(x, y, z)))), out); - } - - /** - * Scales the vector to the provided length. - *

      WARNING: This is a costly operation.

      - * @param v The vector to scale. - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 scaleTo(Vector3 v, float length, Vector3 out) - { - return scaleTo(v.x, v.y, v.z, length, out); - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance of each other. - *

      The vectors are considered equal if the following condition is met: - * (vx >= ux - tolerance && vx <= ux + tolerance) - * && (vy >= uy - tolerance && vy <= uy + tolerance) - * && (vz >= uz - tolerance && vz <= uz + tolerance)

      - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float ux, float uy, float uz - , float vx, float vy, float vz - , float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < ux - tolerance || vx > ux + tolerance) - return false; - if (vy < uy - tolerance || vy > uy + tolerance) - return false; - if (vz < uz - tolerance || vz > uz + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance of each other. - * (v.x >= u.x - tolerance && v.x <= u.x + tolerance) - * && (v.y >= u.y - tolerance && v.y <= u.y + tolerance) - * && (v.z >= u.z - tolerance && v.z <= u.z + tolerance)

      - * @param u Vector u - * @param v Vector v - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(Vector3 u, Vector3 v, float tolerance) - { - return sloppyEquals(u.x, u.y, u.z, v.x, v.y, v.z, tolerance); - } - - /** - * Subtracts vector (vx, vy, vz) from vector (ux, uy, uz) and stores - * the result in the specified location within the out array. (u - v) - *

      WARNING: No argument validations are peformed.

      - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result at. The expected stride is three, - * so the insertion point in out will be outIndex*3. - * @return A reference to the out array. - */ - public static float[] subtract( - float ux, float uy, float uz - , float vx, float vy, float vz - , float[] out - , int outIndex) - { - out[outIndex*3] = ux - vx; - out[outIndex*3+1] = uy - vy; - out[outIndex*3+2] = uz - vz; - return out; - } - - /** - * Subtracts vector (vx, vy, vz) from vector (ux, uy, uz). (u - v) - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 subtract(float ux, float uy, float uz - , float vx, float vy, float vz - , Vector3 out) - { - out.set(ux - vx, uy - vy, uz - vz); - return out; - } - - /** - * Subtracts vectorB from vectorA. (vectorA - vectorB) - *

      WARNING: No argument validations are peformed.

      - *

      All arrays are expected to have a stride of three. So vectors in the array - * are located at index*3. - * @param vectorsA An array of vectors in the form (x, y, z). - * @param vectorAIndex The index of vectorA within the vectorsA array. - * @param vectorsB An array of vectors in the form (x, y, z). - * @param vectorBIndex The index of vectorB within the vectorsB array. - * @param out The vector array to store the result in. - * @param outIndex The vector index in the out array to insert the result at. - * @return A reference to the out array. - */ - public static float[] subtract(float[] vectorsA - , int vectorAIndex - , float[] vectorsB - , int vectorBIndex - , float[] out - , int outIndex) - { - out[outIndex*3] = vectorsA[vectorAIndex*3] - vectorsB[vectorBIndex*3]; - out[outIndex*3+1] = vectorsA[vectorAIndex*3+1] - vectorsB[vectorBIndex*3+1]; - out[outIndex*3+2] = vectorsA[vectorAIndex*3+2] - vectorsB[vectorBIndex*3+2]; - return out; - } - - /** - * Subtracts the two vectors. (u - v) - * @param u Vector to be subtracted from. - * @param v Vector to subtract. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 subtract(Vector3 u, Vector3 v, Vector3 out) - { - return subtract(u.x, u.y, u.z, v.x, v.y, v.z, out); - } - - /** - * Traslates point A toward point B by the specified factor of the - * distance between them. - *

      Examples:

      - *

      If the factor is 0.0, then the result will equal A.
      - * If the factor is 0.5, then the result will be the midpoint between A and B.
      - * If the factor is 1.0, then the result will equal B.

      - * @param ax The x-value of the point (ax, ay, az). - * @param ay The y-value of the point (ax, ay, az). - * @param az The z-value of the point (ax, ay, az). - * @param bx The x-value of the point (bx, by, bz). - * @param by The y-value of the point (bx, by, bz). - * @param bz The z-value of the point (bx, by, bz). - * @param factor The factor which governs the distance the point is translated - * from A toward B. - * @param out The vector to store the result in. - * @return A reference to the out argument. - */ - public static Vector3 translateToward(float ax, float ay, float az - , float bx, float by, float bz - , float factor - , Vector3 out) - { - Vector3.subtract(bx, by, bz, ax, ay, az, out); - out.multiply(factor); - return out.add(ax, ay, az); - } - - /** - * Truncates the length of the vector to the provided value. - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 truncateLength(float x, float y, float z - , float maxLength - , Vector3 out) - { - if (maxLength == 0 || (x == 0 && y == 0 && z == 0)) - { - out.set(0, 0, 0); - return out; - } - float mlsq = maxLength * maxLength; - float csq = getLengthSq(x, y, z); - if (csq <= mlsq) - { - out.set(x, y, z); - return out; - } - return multiply(x, y, z, (float)(maxLength / Math.sqrt(csq)), out); - } - - /** - * Truncates the length of the vector to the provided value. - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param v The vector to truncate. - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 truncateLength(Vector3 v, float maxLength, Vector3 out) - { - return truncateLength(v.x, v.y, v.z, maxLength, out); - } - -} diff --git a/critterai/.svn/pristine/de/deb29ba9fe4cbe41e8a59d411faffcadb6c13d30.svn-base b/critterai/.svn/pristine/de/deb29ba9fe4cbe41e8a59d411faffcadb6c13d30.svn-base deleted file mode 100644 index a7802d18..00000000 --- a/critterai/.svn/pristine/de/deb29ba9fe4cbe41e8a59d411faffcadb6c13d30.svn-base +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// The base class for markers that apply an area id during the - /// state of an NMGen build. - /// - public abstract class AreaMarker - : NMGenProcessor - { - private readonly byte mArea; - - /// - /// The area to apply. - /// - public byte Area { get { return mArea; } } - - /// - /// Constructor - /// - /// The processor name. - /// The processor priority. - /// The area to apply. - public AreaMarker(string name, int priority, byte area) - : base(name, priority) - { - mArea = NMGen.ClampArea(area); - } - } -} diff --git a/critterai/.svn/pristine/de/debdd76da151994743774083967bdb0439ed4b1e.svn-base b/critterai/.svn/pristine/de/debdd76da151994743774083967bdb0439ed4b1e.svn-base deleted file mode 100644 index d1d77eca..00000000 Binary files a/critterai/.svn/pristine/de/debdd76da151994743774083967bdb0439ed4b1e.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/de/def2c0e37749eeed0060df40bdd173fde2887f39.svn-base b/critterai/.svn/pristine/de/def2c0e37749eeed0060df40bdd173fde2887f39.svn-base deleted file mode 100644 index 45b4834d..00000000 --- a/critterai/.svn/pristine/de/def2c0e37749eeed0060df40bdd173fde2887f39.svn-base +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nav -{ - /// - /// Flags for path related waypoints. - /// - [System.Flags] - public enum WaypointFlag : byte - { - /// - /// The point is the start point in the path. - /// - Start = 0x01, - - /// - /// The point is the end point in the path. - /// - End = 0x02, - - /// - /// The point is the start of an off-mesh connection. - /// - /// - /// - /// This flag is useful in detecting when special locomotion handling needs to occur. - /// - /// - OffMesh = 0x04 - } -} diff --git a/critterai/.svn/pristine/df/df6c1b8eb0f4487367d7f46fad7f864a767052fc.svn-base b/critterai/.svn/pristine/df/df6c1b8eb0f4487367d7f46fad7f864a767052fc.svn-base deleted file mode 100644 index 4f3d1a32..00000000 --- a/critterai/.svn/pristine/df/df6c1b8eb0f4487367d7f46fad7f864a767052fc.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("cai-nmgen")] -[assembly: AssemblyDescription("Core navigation mesh generation features.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("critterai.org")] -[assembly: AssemblyProduct("CAINav")] -[assembly: AssemblyCopyright("Copyright © Stephen Pratt 2010-2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: AssemblyFileVersion("0.4.0.0")] diff --git a/critterai/.svn/pristine/df/dfb9fe1dc871f966d14c9d560806cf943d598831.svn-base b/critterai/.svn/pristine/df/dfb9fe1dc871f966d14c9d560806cf943d598831.svn-base deleted file mode 100644 index 3eebf02f..00000000 --- a/critterai/.svn/pristine/df/dfb9fe1dc871f966d14c9d560806cf943d598831.svn-base +++ /dev/null @@ -1,85 +0,0 @@ - - - - -CritterAI NMGen - - - - -

      NMGen is adaptation of Recast's static mesh functionality in the Java language for purposes of study and experimentation. It takes an arbitrary triangle mesh as input and outputs meshes representing the traversable surface of the original mesh.

      -

      Project Documentation
      -
      Project Source
      -License

      -

      -

      -

      Navigation Mesh Generation Process

      - -

      This process is an adaptation of portions of -Recast, a C++ navigation mesh generator -created and released by Mikko Mononen under the -MIT license.

      - -

      - The general process is as follows:

      -
        -
      1. - Voxelization - Create a solid heightfield from the source geometry.
      2. -
      3. - Generate Regions - Detect the top surface area of the solid heightfield and divide it up into contiguous regions.
      4. -
      5. - Generate Contours - Detect the contours of the regions and form them into simple polygons.
      6. -
      7. - Generate Polygon Mesh - Divide the contours into convex polygons.
      8. -
      9. Generate Detailed Mesh - Triangulate the polygon mesh and add height detail.
      10. -
      - -

      See The High Level Process -for more information.

      - -

      The class which implements this process is {@link org.critterai.nmgen.NavmeshGenerator}.

      - -

      Each stage of the process is implemented by data and builder classes. The output of one stage is required -as input for the next:

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      StageBuilder ClassData Class (output)Builder Input
      Voxelization{@link org.critterai.nmgen.SolidHeightfieldBuilder}{@link org.critterai.nmgen.SolidHeightfield}Source Geometry
      Region Generation{@link org.critterai.nmgen.OpenHeightfieldBuilder}{@link org.critterai.nmgen.OpenHeightfield}{@link org.critterai.nmgen.SolidHeightfield}
      Contour Generation{@link org.critterai.nmgen.ContourSetBuilder}{@link org.critterai.nmgen.ContourSet}{@link org.critterai.nmgen.OpenHeightfield} (Fully built.)
      Polygon Mesh Generation{@link org.critterai.nmgen.PolyMeshField}{@link org.critterai.nmgen.PolyMeshField}{@link org.critterai.nmgen.ContourSet}
      Detail Mesh Generation{@link org.critterai.nmgen.DetailMeshBuilder}{@link org.critterai.nmgen.TriangleMesh}{@link org.critterai.nmgen.PolyMeshField}
      - - - diff --git a/critterai/.svn/pristine/e0/e016f16394e751bb75277aab482e1cf586ecd5eb.svn-base b/critterai/.svn/pristine/e0/e016f16394e751bb75277aab482e1cf586ecd5eb.svn-base deleted file mode 100644 index 1356106e..00000000 --- a/critterai/.svn/pristine/e0/e016f16394e751bb75277aab482e1cf586ecd5eb.svn-base +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * Provides various geometry related classes and operations. - *

      A high priority is given to performance. In order to achieve the performance goal, the - * following standards have been implemented:

      - *
        - *
      • There is no validation of arguments outside of constructors. - * For example, the - * {@link org.critterai.math.geom.Line2#getRelationship(float, float, float, float, float, float, float, float, org.critterai.math.Vector2)} - * operation does not validate that the {@link org.critterai.math.Vector2} argument is non-null. - * If the argument is null a runtime error will occur.
      • - *
      • All static operations that return an object require the object be passed in as an "out" argument. - * The out object is updated with the result and its reference returned. This reduces the construction - * costs by allowing clients of the class to re-use the out objects for multiple calls.

        - *
      • - *
      - */ -package org.critterai.math.geom; \ No newline at end of file diff --git a/critterai/.svn/pristine/e0/e0a9e2bb648aee5ec763da0cbdb33f56f8375173.svn-base b/critterai/.svn/pristine/e0/e0a9e2bb648aee5ec763da0cbdb33f56f8375173.svn-base deleted file mode 100644 index d3f90b7a..00000000 --- a/critterai/.svn/pristine/e0/e0a9e2bb648aee5ec763da0cbdb33f56f8375173.svn-base +++ /dev/null @@ -1,544 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include "DetourObstacleAvoidance.h" -#include "DetourCommon.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include -#include -#include -#include - -static const float DT_PI = 3.14159265f; - -static int sweepCircleCircle(const float* c0, const float r0, const float* v, - const float* c1, const float r1, - float& tmin, float& tmax) -{ - static const float EPS = 0.0001f; - float s[3]; - dtVsub(s,c1,c0); - float r = r0+r1; - float c = dtVdot2D(s,s) - r*r; - float a = dtVdot2D(v,v); - if (a < EPS) return 0; // not moving - - // Overlap, calc time to exit. - float b = dtVdot2D(v,s); - float d = b*b - a*c; - if (d < 0.0f) return 0; // no intersection. - a = 1.0f / a; - const float rd = dtSqrt(d); - tmin = (b - rd) * a; - tmax = (b + rd) * a; - return 1; -} - -static int isectRaySeg(const float* ap, const float* u, - const float* bp, const float* bq, - float& t) -{ - float v[3], w[3]; - dtVsub(v,bq,bp); - dtVsub(w,ap,bp); - float d = dtVperp2D(u,v); - if (fabsf(d) < 1e-6f) return 0; - d = 1.0f/d; - t = dtVperp2D(v,w) * d; - if (t < 0 || t > 1) return 0; - float s = dtVperp2D(u,w) * d; - if (s < 0 || s > 1) return 0; - return 1; -} - - - -dtObstacleAvoidanceDebugData* dtAllocObstacleAvoidanceDebugData() -{ - void* mem = dtAlloc(sizeof(dtObstacleAvoidanceDebugData), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtObstacleAvoidanceDebugData; -} - -void dtFreeObstacleAvoidanceDebugData(dtObstacleAvoidanceDebugData* ptr) -{ - if (!ptr) return; - ptr->~dtObstacleAvoidanceDebugData(); - dtFree(ptr); -} - - -dtObstacleAvoidanceDebugData::dtObstacleAvoidanceDebugData() : - m_nsamples(0), - m_maxSamples(0), - m_vel(0), - m_ssize(0), - m_pen(0), - m_vpen(0), - m_vcpen(0), - m_spen(0), - m_tpen(0) -{ -} - -dtObstacleAvoidanceDebugData::~dtObstacleAvoidanceDebugData() -{ - dtFree(m_vel); - dtFree(m_ssize); - dtFree(m_pen); - dtFree(m_vpen); - dtFree(m_vcpen); - dtFree(m_spen); - dtFree(m_tpen); -} - -bool dtObstacleAvoidanceDebugData::init(const int maxSamples) -{ - dtAssert(maxSamples); - m_maxSamples = maxSamples; - - m_vel = (float*)dtAlloc(sizeof(float)*3*m_maxSamples, DT_ALLOC_PERM); - if (!m_vel) - return false; - m_pen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_pen) - return false; - m_ssize = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_ssize) - return false; - m_vpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_vpen) - return false; - m_vcpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_vcpen) - return false; - m_spen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_spen) - return false; - m_tpen = (float*)dtAlloc(sizeof(float)*m_maxSamples, DT_ALLOC_PERM); - if (!m_tpen) - return false; - - return true; -} - -void dtObstacleAvoidanceDebugData::reset() -{ - m_nsamples = 0; -} - -void dtObstacleAvoidanceDebugData::addSample(const float* vel, const float ssize, const float pen, - const float vpen, const float vcpen, const float spen, const float tpen) -{ - if (m_nsamples >= m_maxSamples) - return; - dtAssert(m_vel); - dtAssert(m_ssize); - dtAssert(m_pen); - dtAssert(m_vpen); - dtAssert(m_vcpen); - dtAssert(m_spen); - dtAssert(m_tpen); - dtVcopy(&m_vel[m_nsamples*3], vel); - m_ssize[m_nsamples] = ssize; - m_pen[m_nsamples] = pen; - m_vpen[m_nsamples] = vpen; - m_vcpen[m_nsamples] = vcpen; - m_spen[m_nsamples] = spen; - m_tpen[m_nsamples] = tpen; - m_nsamples++; -} - -static void normalizeArray(float* arr, const int n) -{ - // Normalize penaly range. - float minPen = FLT_MAX; - float maxPen = -FLT_MAX; - for (int i = 0; i < n; ++i) - { - minPen = dtMin(minPen, arr[i]); - maxPen = dtMax(maxPen, arr[i]); - } - const float penRange = maxPen-minPen; - const float s = penRange > 0.001f ? (1.0f / penRange) : 1; - for (int i = 0; i < n; ++i) - arr[i] = dtClamp((arr[i]-minPen)*s, 0.0f, 1.0f); -} - -void dtObstacleAvoidanceDebugData::normalizeSamples() -{ - normalizeArray(m_pen, m_nsamples); - normalizeArray(m_vpen, m_nsamples); - normalizeArray(m_vcpen, m_nsamples); - normalizeArray(m_spen, m_nsamples); - normalizeArray(m_tpen, m_nsamples); -} - - -dtObstacleAvoidanceQuery* dtAllocObstacleAvoidanceQuery() -{ - void* mem = dtAlloc(sizeof(dtObstacleAvoidanceQuery), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtObstacleAvoidanceQuery; -} - -void dtFreeObstacleAvoidanceQuery(dtObstacleAvoidanceQuery* ptr) -{ - if (!ptr) return; - ptr->~dtObstacleAvoidanceQuery(); - dtFree(ptr); -} - - -dtObstacleAvoidanceQuery::dtObstacleAvoidanceQuery() : - m_maxCircles(0), - m_circles(0), - m_ncircles(0), - m_maxSegments(0), - m_segments(0), - m_nsegments(0) -{ -} - -dtObstacleAvoidanceQuery::~dtObstacleAvoidanceQuery() -{ - dtFree(m_circles); - dtFree(m_segments); -} - -bool dtObstacleAvoidanceQuery::init(const int maxCircles, const int maxSegments) -{ - m_maxCircles = maxCircles; - m_ncircles = 0; - m_circles = (dtObstacleCircle*)dtAlloc(sizeof(dtObstacleCircle)*m_maxCircles, DT_ALLOC_PERM); - if (!m_circles) - return false; - memset(m_circles, 0, sizeof(dtObstacleCircle)*m_maxCircles); - - m_maxSegments = maxSegments; - m_nsegments = 0; - m_segments = (dtObstacleSegment*)dtAlloc(sizeof(dtObstacleSegment)*m_maxSegments, DT_ALLOC_PERM); - if (!m_segments) - return false; - memset(m_segments, 0, sizeof(dtObstacleSegment)*m_maxSegments); - - return true; -} - -void dtObstacleAvoidanceQuery::reset() -{ - m_ncircles = 0; - m_nsegments = 0; -} - -void dtObstacleAvoidanceQuery::addCircle(const float* pos, const float rad, - const float* vel, const float* dvel) -{ - if (m_ncircles >= m_maxCircles) - return; - - dtObstacleCircle* cir = &m_circles[m_ncircles++]; - dtVcopy(cir->p, pos); - cir->rad = rad; - dtVcopy(cir->vel, vel); - dtVcopy(cir->dvel, dvel); -} - -void dtObstacleAvoidanceQuery::addSegment(const float* p, const float* q) -{ - if (m_nsegments > m_maxSegments) - return; - - dtObstacleSegment* seg = &m_segments[m_nsegments++]; - dtVcopy(seg->p, p); - dtVcopy(seg->q, q); -} - -void dtObstacleAvoidanceQuery::prepare(const float* pos, const float* dvel) -{ - // Prepare obstacles - for (int i = 0; i < m_ncircles; ++i) - { - dtObstacleCircle* cir = &m_circles[i]; - - // Side - const float* pa = pos; - const float* pb = cir->p; - - const float orig[3] = {0,0}; - float dv[3]; - dtVsub(cir->dp,pb,pa); - dtVnormalize(cir->dp); - dtVsub(dv, cir->dvel, dvel); - - const float a = dtTriArea2D(orig, cir->dp,dv); - if (a < 0.01f) - { - cir->np[0] = -cir->dp[2]; - cir->np[2] = cir->dp[0]; - } - else - { - cir->np[0] = cir->dp[2]; - cir->np[2] = -cir->dp[0]; - } - } - - for (int i = 0; i < m_nsegments; ++i) - { - dtObstacleSegment* seg = &m_segments[i]; - - // Precalc if the agent is really close to the segment. - const float r = 0.01f; - float t; - seg->touch = dtDistancePtSegSqr2D(pos, seg->p, seg->q, t) < dtSqr(r); - } -} - -float dtObstacleAvoidanceQuery::processSample(const float* vcand, const float cs, - const float* pos, const float rad, - const float* vel, const float* dvel, - dtObstacleAvoidanceDebugData* debug) -{ - // Find min time of impact and exit amongst all obstacles. - float tmin = m_params.horizTime; - float side = 0; - int nside = 0; - - for (int i = 0; i < m_ncircles; ++i) - { - const dtObstacleCircle* cir = &m_circles[i]; - - // RVO - float vab[3]; - dtVscale(vab, vcand, 2); - dtVsub(vab, vab, vel); - dtVsub(vab, vab, cir->vel); - - // Side - side += dtClamp(dtMin(dtVdot2D(cir->dp,vab)*0.5f+0.5f, dtVdot2D(cir->np,vab)*2), 0.0f, 1.0f); - nside++; - - float htmin = 0, htmax = 0; - if (!sweepCircleCircle(pos,rad, vab, cir->p,cir->rad, htmin, htmax)) - continue; - - // Handle overlapping obstacles. - if (htmin < 0.0f && htmax > 0.0f) - { - // Avoid more when overlapped. - htmin = -htmin * 0.5f; - } - - if (htmin >= 0.0f) - { - // The closest obstacle is somewhere ahead of us, keep track of nearest obstacle. - if (htmin < tmin) - tmin = htmin; - } - } - - for (int i = 0; i < m_nsegments; ++i) - { - const dtObstacleSegment* seg = &m_segments[i]; - float htmin = 0; - - if (seg->touch) - { - // Special case when the agent is very close to the segment. - float sdir[3], snorm[3]; - dtVsub(sdir, seg->q, seg->p); - snorm[0] = -sdir[2]; - snorm[2] = sdir[0]; - // If the velocity is pointing towards the segment, no collision. - if (dtVdot2D(snorm, vcand) < 0.0f) - continue; - // Else immediate collision. - htmin = 0.0f; - } - else - { - if (!isectRaySeg(pos, vcand, seg->p, seg->q, htmin)) - continue; - } - - // Avoid less when facing walls. - htmin *= 2.0f; - - // The closest obstacle is somewhere ahead of us, keep track of nearest obstacle. - if (htmin < tmin) - tmin = htmin; - } - - // Normalize side bias, to prevent it dominating too much. - if (nside) - side /= nside; - - const float vpen = m_params.weightDesVel * (dtVdist2D(vcand, dvel) * m_invVmax); - const float vcpen = m_params.weightCurVel * (dtVdist2D(vcand, vel) * m_invVmax); - const float spen = m_params.weightSide * side; - const float tpen = m_params.weightToi * (1.0f/(0.1f+tmin*m_invHorizTime)); - - const float penalty = vpen + vcpen + spen + tpen; - - // Store different penalties for debug viewing - if (debug) - debug->addSample(vcand, cs, penalty, vpen, vcpen, spen, tpen); - - return penalty; -} - -int dtObstacleAvoidanceQuery::sampleVelocityGrid(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, float* nvel, - const dtObstacleAvoidanceParams* params, - dtObstacleAvoidanceDebugData* debug) -{ - prepare(pos, dvel); - - memcpy(&m_params, params, sizeof(dtObstacleAvoidanceParams)); - m_invHorizTime = 1.0f / m_params.horizTime; - m_vmax = vmax; - m_invVmax = 1.0f / vmax; - - dtVset(nvel, 0,0,0); - - if (debug) - debug->reset(); - - const float cvx = dvel[0] * m_params.velBias; - const float cvz = dvel[2] * m_params.velBias; - const float cs = vmax * 2 * (1 - m_params.velBias) / (float)(m_params.gridSize-1); - const float half = (m_params.gridSize-1)*cs*0.5f; - - float minPenalty = FLT_MAX; - int ns = 0; - - for (int y = 0; y < m_params.gridSize; ++y) - { - for (int x = 0; x < m_params.gridSize; ++x) - { - float vcand[3]; - vcand[0] = cvx + x*cs - half; - vcand[1] = 0; - vcand[2] = cvz + y*cs - half; - - if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+cs/2)) continue; - - const float penalty = processSample(vcand, cs, pos,rad,vel,dvel, debug); - ns++; - if (penalty < minPenalty) - { - minPenalty = penalty; - dtVcopy(nvel, vcand); - } - } - } - - return ns; -} - - -int dtObstacleAvoidanceQuery::sampleVelocityAdaptive(const float* pos, const float rad, const float vmax, - const float* vel, const float* dvel, float* nvel, - const dtObstacleAvoidanceParams* params, - dtObstacleAvoidanceDebugData* debug) -{ - prepare(pos, dvel); - - memcpy(&m_params, params, sizeof(dtObstacleAvoidanceParams)); - m_invHorizTime = 1.0f / m_params.horizTime; - m_vmax = vmax; - m_invVmax = 1.0f / vmax; - - dtVset(nvel, 0,0,0); - - if (debug) - debug->reset(); - - // Build sampling pattern aligned to desired velocity. - float pat[(DT_MAX_PATTERN_DIVS*DT_MAX_PATTERN_RINGS+1)*2]; - int npat = 0; - - const int ndivs = (int)m_params.adaptiveDivs; - const int nrings= (int)m_params.adaptiveRings; - const int depth = (int)m_params.adaptiveDepth; - - const int nd = dtClamp(ndivs, 1, DT_MAX_PATTERN_DIVS); - const int nr = dtClamp(nrings, 1, DT_MAX_PATTERN_RINGS); - const float da = (1.0f/nd) * DT_PI*2; - const float dang = atan2f(dvel[2], dvel[0]); - - // Always add sample at zero - pat[npat*2+0] = 0; - pat[npat*2+1] = 0; - npat++; - - for (int j = 0; j < nr; ++j) - { - const float r = (float)(nr-j)/(float)nr; - float a = dang + (j&1)*0.5f*da; - for (int i = 0; i < nd; ++i) - { - pat[npat*2+0] = cosf(a)*r; - pat[npat*2+1] = sinf(a)*r; - npat++; - a += da; - } - } - - // Start sampling. - float cr = vmax * (1.0f - m_params.velBias); - float res[3]; - dtVset(res, dvel[0] * m_params.velBias, 0, dvel[2] * m_params.velBias); - int ns = 0; - - for (int k = 0; k < depth; ++k) - { - float minPenalty = FLT_MAX; - float bvel[3]; - dtVset(bvel, 0,0,0); - - for (int i = 0; i < npat; ++i) - { - float vcand[3]; - vcand[0] = res[0] + pat[i*2+0]*cr; - vcand[1] = 0; - vcand[2] = res[2] + pat[i*2+1]*cr; - - if (dtSqr(vcand[0])+dtSqr(vcand[2]) > dtSqr(vmax+0.001f)) continue; - - const float penalty = processSample(vcand,cr/10, pos,rad,vel,dvel, debug); - ns++; - if (penalty < minPenalty) - { - minPenalty = penalty; - dtVcopy(bvel, vcand); - } - } - - dtVcopy(res, bvel); - - cr *= 0.5f; - } - - dtVcopy(nvel, res); - - return ns; -} - diff --git a/critterai/.svn/pristine/e1/e13fbcb059f3f8e60122248de8fc375fd61d9caa.svn-base b/critterai/.svn/pristine/e1/e13fbcb059f3f8e60122248de8fc375fd61d9caa.svn-base deleted file mode 100644 index 6639ddfc..00000000 --- a/critterai/.svn/pristine/e1/e13fbcb059f3f8e60122248de8fc375fd61d9caa.svn-base +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.u3d.editor; -using UnityEngine; -using UnityEditor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(BoxAreaMarker))] -public sealed class BoxAreaMarkerEditor - : AreaMarkerEditor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - OnGUIStandard((BoxAreaMarker)target); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - [DrawGizmo(GizmoType.NotSelected | GizmoType.SelectedOrChild | GizmoType.Pickable)] - static void DrawGizmo(BoxAreaMarker marker, GizmoType type) - { - DrawStandardGizmo(marker, type); - } - - [MenuItem(EditorUtil.NMGenGameObjectMenu + "Area Marker : Box" - , false - , EditorUtil.GameObjectGroup)] - static void CreateGameObject() - { - GameObject go = new GameObject("AreaMarker"); - go.transform.position = EditorUtil.GetCreatePosition(); - - go.AddComponent(); - - Selection.activeGameObject = go; - } -} diff --git a/critterai/.svn/pristine/e1/e16464abd29aa9e46fe4013e7768d1c7cc61182d.svn-base b/critterai/.svn/pristine/e1/e16464abd29aa9e46fe4013e7768d1c7cc61182d.svn-base deleted file mode 100644 index e706b999..00000000 Binary files a/critterai/.svn/pristine/e1/e16464abd29aa9e46fe4013e7768d1c7cc61182d.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e1/e1eaceddc1ee12d592b08f996d0f2287d5e302be.svn-base b/critterai/.svn/pristine/e1/e1eaceddc1ee12d592b08f996d0f2287d5e302be.svn-base deleted file mode 100644 index 3e91f467..00000000 Binary files a/critterai/.svn/pristine/e1/e1eaceddc1ee12d592b08f996d0f2287d5e302be.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e2/e2ea1f87139ac93fe95dfefff5d73d57e1584620.svn-base b/critterai/.svn/pristine/e2/e2ea1f87139ac93fe95dfefff5d73d57e1584620.svn-base deleted file mode 100644 index 8787c56f..00000000 Binary files a/critterai/.svn/pristine/e2/e2ea1f87139ac93fe95dfefff5d73d57e1584620.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e4/e44eb5baedb1ff19a0477af13e6dd9cd3a4b92a9.svn-base b/critterai/.svn/pristine/e4/e44eb5baedb1ff19a0477af13e6dd9cd3a4b92a9.svn-base deleted file mode 100644 index 0443caf5..00000000 --- a/critterai/.svn/pristine/e4/e44eb5baedb1ff19a0477af13e6dd9cd3a4b92a9.svn-base +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// Applies to - /// a . - /// - /// - /// - /// This is a system processor. - /// - /// - public sealed class FilterLowHeightSpans - : NMGenProcessor - { - private const int ProcessorPriority = FilterLedgeSpans.ProcessorPriority + 5; - - private static FilterLowHeightSpans mInstance = new FilterLowHeightSpans(); - - private FilterLowHeightSpans() - : base(typeof(FilterLowHeightSpans).Name, ProcessorPriority) - { - } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// Will be applied during the state. - /// - /// - /// The current build state. - /// The context to process. - /// False on error, otherwise true. - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - - if (state != NMGenState.HeightfieldBuild) - return true; - - if (context.Heightfield.MarkLowHeightSpansNotWalkable(context - , context.Config.WalkableHeight)) - { - context.Log(Name + ": Marked low height spans as not walklable.", this); - return true; - } - - context.Log(Name + ": Mark low height spans failed.", this); - return false; - } - - /// - /// The processor instance. - /// - public static FilterLowHeightSpans Instance { get { return mInstance; } } - } -} diff --git a/critterai/.svn/pristine/e4/e4acc234fb1954efde27fd63fa94b1f7122a09b1.svn-base b/critterai/.svn/pristine/e4/e4acc234fb1954efde27fd63fa94b1f7122a09b1.svn-base deleted file mode 100644 index ef906473..00000000 --- a/critterai/.svn/pristine/e4/e4acc234fb1954efde27fd63fa94b1f7122a09b1.svn-base +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Provides for the application of an algorithm to a contour. - */ -public interface IContourAlgorithm -{ - /** - * Apply an algorithm to a contour. - *

      The implementation is permitted to require that the the result - * vertices be seeded with existing data. In this case the argument - * becomes an in/out argument rather than just an out argument.

      - * @param sourceVerts The source vertices that represent the contour - * in the form (x, y, z, regionID). - * @param resultVerts The contour vertices produced by the operation - * in the form (x, y, z, sourceIndex). - *

      Source index is the index (not pointer) of the related source - * vertex in sourcVerts. E.g. If the vertex in resultsList references - * the vertex at position 12 of sourceVerts, then sourceIndex will - * be 3 (12 / 4).

      - */ - void apply(ArrayList sourceVerts, ArrayList resultVerts); -} diff --git a/critterai/.svn/pristine/e4/e4e520ab0675351df1c5d2b2d8bbe1929ee2c78b.svn-base b/critterai/.svn/pristine/e4/e4e520ab0675351df1c5d2b2d8bbe1929ee2c78b.svn-base deleted file mode 100644 index b84585e9..00000000 --- a/critterai/.svn/pristine/e4/e4e520ab0675351df1c5d2b2d8bbe1929ee2c78b.svn-base +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d.editor; -using org.critterai.nmbuild.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(MeshCompiler))] -public sealed class MeshCompilerEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - MeshCompiler targ = (MeshCompiler)target; - - EditorGUILayout.Separator(); - - GUILayout.Label("Priority: " + targ.Priority); - - EditorGUILayout.Separator(); - - EditorGUIUtility.LookLikeControls(120); - - targ.colocationOption = (MeshColocationOption) - EditorGUILayout.EnumPopup("Colocation priority", targ.colocationOption); - - EditorGUILayout.Separator(); - - string msg = "Input Build Processor\n\n" - + "Loads and compiles the " + typeof(MeshFilter).Name + " components in the scene."; - - if (targ.colocationOption == MeshColocationOption.Collider) - { - msg += "\n\nIf a supported collider is colocated with the mesh, then the collider" - + " will be compiled instead of the mesh. Supported colliders include:" - + " SphereCollider, BoxCollider, and MeshCollider."; - } - - GUILayout.Box(msg, EditorUtil.HelpStyle, GUILayout.ExpandWidth(true)); - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(targ); - } - - [MenuItem(EditorUtil.NMGenAssetMenu + "Compiler : MeshFilter", false, NMBEditorUtil.CompilerGroup)] - static void CreateAsset() - { - MeshCompiler item = EditorUtil.CreateAsset(NMBEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } -} diff --git a/critterai/.svn/pristine/e5/e53108d34e8038496f02726c1d75469b8e30a382.svn-base b/critterai/.svn/pristine/e5/e53108d34e8038496f02726c1d75469b8e30a382.svn-base deleted file mode 100644 index 3347b74f..00000000 Binary files a/critterai/.svn/pristine/e5/e53108d34e8038496f02726c1d75469b8e30a382.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e5/e55ab893dc899d66692cf63509435409476d840d.svn-base b/critterai/.svn/pristine/e5/e55ab893dc899d66692cf63509435409476d840d.svn-base deleted file mode 100644 index c3b30a44..00000000 Binary files a/critterai/.svn/pristine/e5/e55ab893dc899d66692cf63509435409476d840d.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e5/e598cd0a827749ceea5bbfb9cdeab7a00259decb.svn-base b/critterai/.svn/pristine/e5/e598cd0a827749ceea5bbfb9cdeab7a00259decb.svn-base deleted file mode 100644 index e82aa597..00000000 --- a/critterai/.svn/pristine/e5/e598cd0a827749ceea5bbfb9cdeab7a00259decb.svn-base +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -using System; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild -{ - /// - /// A processor that applies polygon flags to all polygons in a . - /// - /// - /// - /// The flags are additive. (I.e. poly.flags |= flags) - /// - /// - public sealed class ApplyPolygonFlags - : NMGenProcessor - { - private readonly ushort mFlags; - - /// - /// Constructor. - /// - /// The name of the processor. - /// The prioity. - /// The flags to apply. - public ApplyPolygonFlags(string name, int priority, ushort flags) - : base(name, priority) - { - mFlags = flags; - } - - /// - /// The flags to apply. - /// - public ushort Flags { get { return mFlags; } } - - /// - /// Always threadsafe. (True) - /// - public override bool IsThreadSafe { get { return true; } } - - /// - /// Process the build context. - /// - /// - /// - /// The flags will be applied during the state. - /// - /// - /// The current build state. - /// The context to process. - /// True - public override bool ProcessBuild(NMGenContext context, NMGenState state) - { - if (state != NMGenState.PolyMeshBuild) - return true; - - PolyMeshData data = context.PolyMesh.GetData(false); - - for (int i = 0; i < data.flags.Length; i++) - { - data.flags[i] |= mFlags; - } - - context.PolyMesh.Load(data); - context.Log(string.Format("{0}: Applied flag(s) to all polys. Flag(s): 0x{1:X}" - , Name, mFlags) - , this); - - return true; - } - } -} diff --git a/critterai/.svn/pristine/e6/e6e89911601d4128233596175cbf45ab2cf9f7f1.svn-base b/critterai/.svn/pristine/e6/e6e89911601d4128233596175cbf45ab2cf9f7f1.svn-base deleted file mode 100644 index 1735e35e..00000000 Binary files a/critterai/.svn/pristine/e6/e6e89911601d4128233596175cbf45ab2cf9f7f1.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e7/e713ecf71a5a4962e90700edc2ba7c7c0efb6dd3.svn-base b/critterai/.svn/pristine/e7/e713ecf71a5a4962e90700edc2ba7c7c0efb6dd3.svn-base deleted file mode 100644 index 6bd9d9e1..00000000 --- a/critterai/.svn/pristine/e7/e713ecf71a5a4962e90700edc2ba7c7c0efb6dd3.svn-base +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class ColliderHelper - { - private GameObject mSphere; - private GameObject mCube; - private Mesh mSphereMesh; - private Mesh mCubeMesh; - - public ColliderHelper() - { - mSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); - mSphereMesh = mSphere.GetComponent().sharedMesh; - - mCube = GameObject.CreatePrimitive(PrimitiveType.Cube); - mCubeMesh = mCube.GetComponent().sharedMesh; - } - - public void Dispose() - { - if (mSphere == null) - return; - - Object.DestroyImmediate(mSphere); - Object.DestroyImmediate(mCube); - - mSphere = null; - mCube = null; - mSphereMesh = null; - mCubeMesh = null; - } - - public bool Get(Collider filter, out CombineInstance result) - { - result = new CombineInstance(); - - if (mSphere == null || !IsSupported(filter)) - return false; - - if (filter is SphereCollider) - { - SphereCollider sphereCollider = (SphereCollider)filter; - - result.mesh = mSphereMesh; - result.transform = sphereCollider.transform.localToWorldMatrix - * Matrix4x4.TRS(sphereCollider.center - , Quaternion.identity - , Vector3.one * sphereCollider.radius * 2.0f); - - return true; - } - - if (filter is BoxCollider) - { - BoxCollider boxCollider = (BoxCollider)filter; - - result.mesh = mCubeMesh; - result.transform = boxCollider.transform.localToWorldMatrix - * Matrix4x4.TRS(boxCollider.center, Quaternion.identity, boxCollider.size); - - return true; - } - - if (filter is MeshCollider) - { - MeshCollider collider = (MeshCollider)filter; - - if (collider.sharedMesh) - { - result.mesh = collider.sharedMesh; - result.transform = collider.transform.localToWorldMatrix; - - return true; - } - } - - return false; - } - - public static bool IsSupported(Collider item) - { - return (item is SphereCollider || item is BoxCollider || item is MeshCollider); - } - } -} diff --git a/critterai/.svn/pristine/e7/e71d988eff6b1b40a73addb3860603cc5608f6a9.svn-base b/critterai/.svn/pristine/e7/e71d988eff6b1b40a73addb3860603cc5608f6a9.svn-base deleted file mode 100644 index 8e42ec02..00000000 Binary files a/critterai/.svn/pristine/e7/e71d988eff6b1b40a73addb3860603cc5608f6a9.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e9/e961f4b1318f2f45adf8ee73a85586f9d1882b15.svn-base b/critterai/.svn/pristine/e9/e961f4b1318f2f45adf8ee73a85586f9d1882b15.svn-base deleted file mode 100644 index 700d6a20..00000000 Binary files a/critterai/.svn/pristine/e9/e961f4b1318f2f45adf8ee73a85586f9d1882b15.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/e9/e9c1a785a7d4324ed2c4f6813c7f34ec033875c4.svn-base b/critterai/.svn/pristine/e9/e9c1a785a7d4324ed2c4f6813c7f34ec033875c4.svn-base deleted file mode 100644 index 8dae4e42..00000000 Binary files a/critterai/.svn/pristine/e9/e9c1a785a7d4324ed2c4f6813c7f34ec033875c4.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/ea/ea3ed57e857bcbd9edcc215219968526d93e3eac.svn-base b/critterai/.svn/pristine/ea/ea3ed57e857bcbd9edcc215219968526d93e3eac.svn-base deleted file mode 100644 index ecdd1f77..00000000 --- a/critterai/.svn/pristine/ea/ea3ed57e857bcbd9edcc215219968526d93e3eac.svn-base +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Path corridor data. - /// - /// - /// - /// Used as a marshalling buffer for corridor data. - /// - /// - /// Certain methods that take objects of this type require a fixed buffer size equal to - /// . So be careful when initializing and using objects of - /// this type. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public sealed class PathCorridorData - { - /// - /// The required maximum path size required to use with interop - /// method calls. - /// - public const int MarshalBufferSize = 256; - - /// - /// The current position within the path corridor. - /// - public Vector3 position; - - /// - /// The target position within the path corridor. - /// - public Vector3 target; - - /// - /// An ordered list of polygon references representing the corridor. - /// [(polyRef) * ] - /// - [MarshalAs(UnmanagedType.ByValArray, SizeConst = MarshalBufferSize)] - public uint[] path; - - /// - /// The number of polygons in the path. - /// - public int pathCount; - - /// - /// Creates an object with buffers sized for use with interop method calls. - /// (Maximum Path Size = ) - /// - public PathCorridorData() - { - path = new uint[MarshalBufferSize]; - } - - /// - /// Creates an object with a non-standard buffer size. - /// - /// The maximum path size the buffer can hold. - public PathCorridorData(int maxPathSize) - { - path = new uint[maxPathSize]; - } - } -} diff --git a/critterai/.svn/pristine/ea/ea47299072e885c7a78358844cc2829a69ac9781.svn-base b/critterai/.svn/pristine/ea/ea47299072e885c7a78358844cc2829a69ac9781.svn-base deleted file mode 100644 index d326008b..00000000 Binary files a/critterai/.svn/pristine/ea/ea47299072e885c7a78358844cc2829a69ac9781.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/ea/eaa70c0350eb4831246c730a71fc4b2160d8e37f.svn-base b/critterai/.svn/pristine/ea/eaa70c0350eb4831246c730a71fc4b2160d8e37f.svn-base deleted file mode 100644 index d29dc134..00000000 --- a/critterai/.svn/pristine/ea/eaa70c0350eb4831246c730a71fc4b2160d8e37f.svn-base +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - /// - /// The build type to use for a asset. - /// - internal enum NavmeshBuildType - { - /// - /// Standard foreground build. - /// - Standard = 0, - - /// - /// Advanced build using the . - /// - Advanced, - } -} diff --git a/critterai/.svn/pristine/eb/eb3f75134b2a2abd2141c96a5122538b070d2a4f.svn-base b/critterai/.svn/pristine/eb/eb3f75134b2a2abd2141c96a5122538b070d2a4f.svn-base deleted file mode 100644 index c07dc645..00000000 --- a/critterai/.svn/pristine/eb/eb3f75134b2a2abd2141c96a5122538b070d2a4f.svn-base +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Runtime.InteropServices; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nmgen.rcn -{ - internal static class HeightfieldEx - { - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern IntPtr nmhfAllocField(int width - , int depth - , [In] ref Vector3 boundsMin - , [In] ref Vector3 boundsMax - , float xzCellSize - , float yCellSize); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern void nmhfFreeField(IntPtr hf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfRasterizeTriangle(IntPtr context - , [In] Vector3[] verts - , byte area - , IntPtr hf - , int flagMergeThreshold); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfRasterizeTriMesh(IntPtr context - , [In] Vector3[] verts - , int vertCount - , [In] int[] tris - , [In] byte[] areas - , int triCount - , IntPtr hf - , int flagMergeThreshold); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfRasterizeNodes(IntPtr context - , IntPtr verts - , IntPtr tris - , IntPtr areas - , [In] ChunkyTriMeshNode[] nodes - , int nodeCount - , IntPtr hf - , int flagMergeThreshold); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfRasterizeTriMeshShort(IntPtr context - , [In] Vector3[] verts - , int vertCount - , [In] ushort[] tris - , [In] byte[] areas - , int triCount - , IntPtr hf - , int flagMergeThreshold); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfRasterizeTriangles(IntPtr context - , [In] Vector3[] verts - , [In] byte[] areas - , int triCount - , IntPtr hf - , int flagMergeThreshold); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfFilterLowHangingWalkableObstacles(IntPtr context - , int walkableStep - , IntPtr hf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfFilterLedgeSpans(IntPtr context - , int walkableHeight - , int walkableStep - , IntPtr hf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern bool nmhfFilterWalkableLowHeightSpans(IntPtr context - , int walkableHeight - , IntPtr hf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int nmhfGetHeightFieldSpanCount(IntPtr hf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int nmhfGetMaxSpansInColumn(IntPtr hf); - - [DllImport(InteropUtil.PLATFORM_DLL)] - public static extern int nmhfGetSpans(IntPtr hf - , int widthIndex - , int depthIndex - , [In, Out] HeightfieldSpan[] spanBuffer - , int bufferSize); - } -} diff --git a/critterai/.svn/pristine/eb/eb566d231b9b57de20eafec9eb098d20192520f9.svn-base b/critterai/.svn/pristine/eb/eb566d231b9b57de20eafec9eb098d20192520f9.svn-base deleted file mode 100644 index baec94a2..00000000 --- a/critterai/.svn/pristine/eb/eb566d231b9b57de20eafec9eb098d20192520f9.svn-base +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using org.critterai.nmgen; -using org.critterai.nav; - -namespace org.critterai.nmbuild -{ - /// - /// A task used to manage the build of an a tile from NMGen and connection data. - /// - /// - /// - /// This task performs the tile build step in the navigation mesh build pipeline. - /// - /// - public sealed class TileBuildTask - : BuildTask - { - private readonly int mTileX; - private readonly int mTileZ; - private readonly bool mIsThreadSafe; - private readonly bool mBVTreeEnabled; - private PolyMeshData mPolyData; - private PolyMeshDetailData mDetailData; - private ConnectionSet mConnections; - - private TileBuildTask(int tx, int tz - , PolyMeshData polyData - , PolyMeshDetailData detailData - , ConnectionSet connections - , bool bvTreeEnabled - , bool isThreadSafe - , int priority) - : base(priority) - { - mTileX = tx; - mTileZ = tz; - mPolyData = polyData; - mDetailData = detailData; - mConnections = connections; - mBVTreeEnabled = bvTreeEnabled; - mIsThreadSafe = isThreadSafe; - } - - /// - /// If true, the task is safe to run on its own thread. - /// - public override bool IsThreadSafe { get { return mIsThreadSafe; } } - - /// - /// The x-index of the tile within the tile grid. (x, z) - /// - public int TileX { get { return mTileX; } } - - /// - /// The z-index of the tile within the tile grid. (x, z) - /// - public int TileZ { get { return mTileZ; } } - - /// - /// Creates a new task. - /// - /// - /// - /// The task should only be marked as thread-safe if the data parameters are treated - /// as immutable while the task is running. - /// - /// - /// Creation will fail on null parameters, invalid tile indices, and an empty - /// polygon mesh. - /// - /// - /// The x-index of the tile within the tile grid. (x, z) - /// The z-index of the tile within the tile grid. (x, z) - /// The polygon mesh data. - /// The detail mesh data. (Optional) - /// The off-mesh connection set. - /// True if bounding volumes should be generated. - /// True if the task is safe to run on its own thread. - /// The task priority. - /// A new task, or null on error. - public static TileBuildTask Create(int tx, int tz - , PolyMeshData polyData - , PolyMeshDetailData detailData - , ConnectionSet conns - , bool bvTreeEnabled - , bool isThreadSafe - , int priority) - { - if (tx < 0 || tz < 0 - || polyData == null || polyData.polyCount == 0 - || conns == null) - { - return null; - } - - return new TileBuildTask(tx, tz - , polyData, detailData, conns, bvTreeEnabled, isThreadSafe, priority); - } - - /// - /// Performs a work increment. - /// - /// True if the task is not yet finished. Otherwise false. - protected override bool LocalUpdate() - { - // All the work is done in GetResult(). - return false; - } - - /// - /// Gets the result of the completed task. - /// - /// The result of the completed task. - /// True if the result is available, false if the task should abort with no - /// result. (I.e. An internal abort.) - protected override bool GetResult(out TileBuildAssets result) - { - BuildContext logger = new BuildContext(); - - result = new TileBuildAssets(); - - NavmeshTileBuildData tbd = - NMBuild.GetBuildData(logger, mTileX, mTileZ - , mPolyData, (mDetailData == null ? null : mDetailData), mConnections - , mBVTreeEnabled); - - AddMessages(logger.GetMessages()); - - if (tbd == null) - return false; - - NavmeshTileData td = NavmeshTileData.Create(tbd); - - if (td.Size == 0) - { - AddMessage(string.Format( - "Could not create {2} object. Cause unknown." - + " Tile: ({0},{1})" - , mTileX, mTileZ, td.GetType().Name)); - - return false; - } - - result = new TileBuildAssets(mTileX, mTileZ, td, tbd.PolyCount); - - return true; - } - - /// - /// Finalize the task. - /// - protected override void FinalizeTask() - { - mPolyData = null; - mDetailData = null; - mConnections = null; - } - } -} diff --git a/critterai/.svn/pristine/eb/eb7edb755feddc286a17243f697d46f698d36191.svn-base b/critterai/.svn/pristine/eb/eb7edb755feddc286a17243f697d46f698d36191.svn-base deleted file mode 100644 index a4799bf9..00000000 --- a/critterai/.svn/pristine/eb/eb7edb755feddc286a17243f697d46f698d36191.svn-base +++ /dev/null @@ -1,69 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {42218E47-156D-46ff-84E0-119D47B0E4EB} - Library - Properties - org.critterai - cai-nav - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - TRACE;DEBUG;NUNITY - prompt - 4 - AnyCPU - - - pdbonly - true - ..\bin\Release\ - TRACE;NUNITY - prompt - 4 - AnyCPU - ..\bin\Release\cai-nav.XML - - - - - 3.5 - - - - - - rcn\FakeName.cs - - - Properties\AssemblyInfo.cs - - - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - {319D361B-147F-45AC-854E-50C06FCA3393} - cai-nav-rcn - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/eb/ebe2585f6eef5378bd290bcb2801e87312cd86ff.svn-base b/critterai/.svn/pristine/eb/ebe2585f6eef5378bd290bcb2801e87312cd86ff.svn-base deleted file mode 100644 index 2c71844e..00000000 Binary files a/critterai/.svn/pristine/eb/ebe2585f6eef5378bd290bcb2801e87312cd86ff.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/ec/ecb3ec4d245cdebc9a10726ef2e2357502e41dab.svn-base b/critterai/.svn/pristine/ec/ecb3ec4d245cdebc9a10726ef2e2357502e41dab.svn-base deleted file mode 100644 index ad8b2809..00000000 --- a/critterai/.svn/pristine/ec/ecb3ec4d245cdebc9a10726ef2e2357502e41dab.svn-base +++ /dev/null @@ -1,89 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; -import static org.critterai.nmgen.Geometry.*; -import org.junit.Test; - -/** - * Tests functionality in the Geomtry class. - */ -public final class GeometryTests -{ - - private static final float TOLERANCE = 0.0001f; - - @Test - public void testPointSegmentDistance3DFloatBasic() - { - final float ax = -4; - final float ay = 1; - final float az = 2; - - final float bx = 2; - final float by = 1; - final float bz = 2; - - float px = 0; - float py = 1; - float pz = 2; - - float actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(0.0f, actual, TOLERANCE)); - - px = 0; - py = 2; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(1.0f, actual, TOLERANCE)); - - px = 0; - py = 0; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(1.0f, actual, TOLERANCE)); - - px = 4; - py = 1; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(4.0f, actual, TOLERANCE)); - - px = -6; - py = 1; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(4.0f, actual, TOLERANCE)); - - } - - /** - * Determines whether the values are within the specified tolerance - * of each other. - *

      The values are considered equal if the following condition is met: - * (b >= a - tolerance && b <= a + tolerance)

      - * @param a The a-value to compare the b-value against. - * @param b The b-value to compare against the a-value. - * @param tolerence The tolerance to use for the comparison. - * @return TRUE if the values are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float a, float b, float tolerence) - { - return !(b < a - tolerence || b > a + tolerence); - } - -} diff --git a/critterai/.svn/pristine/ec/ecddc9216e2440df0d47682e41df193605a6a602.svn-base b/critterai/.svn/pristine/ec/ecddc9216e2440df0d47682e41df193605a6a602.svn-base deleted file mode 100644 index 800415cc..00000000 --- a/critterai/.svn/pristine/ec/ecddc9216e2440df0d47682e41df193605a6a602.svn-base +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.u3d; - -/// -/// Base editor for components. -/// -/// -public class AreaMarkerEditor - : NMGenComponentEditor -{ - private static Vector3 markerSize = new Vector3(0.3f, 0.05f, 0.3f); - - /// - /// An area selector control - /// - protected CAINavEditorSettingsEditor.AreaGUIControl areaControl; - - /// - /// Run when the editor is enabled. - /// - protected virtual void OnEnable() - { - ((NMGenComponent)target).debugEnabledLocal = true; - - areaControl = CAINavEditorSettingsEditor.CreateAreaControl("Area"); - } - - /// - /// Controls behavior of the inspector. - /// - /// Editor target. - public void OnGUIStandard(NMGenAreaMarker targ) - { - EditorGUILayout.Separator(); - - bool changed = GUI.changed; - - NMGenComponent.debugEnabled = - EditorGUILayout.Toggle("Show All", NMGenComponent.debugEnabled); - - if (GUI.changed) - SceneView.RepaintAll(); - - GUI.changed = changed; - - EditorGUILayout.Separator(); - - // Note: Clamp before sending to property. - targ.Priority = EditorGUILayout.IntField("Priority", targ.Priority); - - targ.Area = areaControl.OnGUI(targ.Area); - - EditorGUILayout.Separator(); - } - - /// - /// Draws the standard gizmo for components. - /// - /// The marker to draw. - /// The gizmo type. - protected static void DrawStandardGizmo(NMGenAreaMarker marker, GizmoType type) - { - if (!NMGenAreaMarker.debugEnabled && (type & GizmoType.SelectedOrChild) == 0) - return; - - Gizmos.color = ColorUtil.IntToColor(marker.Area, 0.6f); - - Vector3 pos = marker.transform.position; - - Gizmos.DrawCube(pos, markerSize); - } -} diff --git a/critterai/.svn/pristine/ed/eda066c45103833e6cc0f6a8c2196deb0dbc1bff.svn-base b/critterai/.svn/pristine/ed/eda066c45103833e6cc0f6a8c2196deb0dbc1bff.svn-base deleted file mode 100644 index f54997d6..00000000 --- a/critterai/.svn/pristine/ed/eda066c45103833e6cc0f6a8c2196deb0dbc1bff.svn-base +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Defines the standard flags used for height field spans. - */ -public final class SpanFlags -{ - /** - * The span's upper surface (top or maximum) is considered to be - * traversable. Spans without this flag are considered to be obstructions - * that cannot be walked upon. - */ - public static final byte WALKABLE = 1; - - private SpanFlags() { } -} diff --git a/critterai/.svn/pristine/ee/eed68ebade05b04224518ad4e173378e2f44e8a0.svn-base b/critterai/.svn/pristine/ee/eed68ebade05b04224518ad4e173378e2f44e8a0.svn-base deleted file mode 100644 index 375370dc..00000000 --- a/critterai/.svn/pristine/ee/eed68ebade05b04224518ad4e173378e2f44e8a0.svn-base +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.geom; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class MiniInputCompile - { - private enum State - { - Builder, - Task, - Finished - } - - private const float MarginSize = ControlUtil.MarginSize; - - private readonly ControlContext mContext; - private readonly UnityBuildContext mLogger = new UnityBuildContext(); - - private InputBuilder mBuilder; - private InputBuildTask mTask; - - private InputAssets mAssets; - private InputGeometry mGeometry; - - private State mState; - - private double mChunkTime; - - public bool IsFinished { get { return (mState == State.Finished); } } - - public bool HasData { get { return mGeometry != null; } } - - public ConnectionSet Connections - { - get { return (mGeometry == null ? null : mAssets.conns); } - } - - public InputBuildInfo Info - { - get { return (mGeometry == null ? new InputBuildInfo() : mAssets.info); } - } - - public InputGeometry Geometry { get { return mGeometry; } } - - public INMGenProcessor[] Processors - { - get { return (mGeometry == null ? null : mAssets.processors); } - } - - public int TriCount - { - get { return (mGeometry == null? 0 : mGeometry.TriCount); } - } - - public MiniInputCompile(ControlContext context) - { - mContext = context; - - NavmeshBuild build = context.Build; - - if (!build) - { - FinalizeOnFail("The control context's build does not exist.", true); - return; - } - - InputBuildOption options = InputBuildOption.ThreadSafeOnly; - options |= (build.AutoCleanGeometry ? InputBuildOption.AutoCleanGeometry : 0); - - mBuilder = InputBuilder.Create(build.SceneQuery - , build.GetInputProcessors() - , options); - - if (mBuilder == null) - { - FinalizeOnFail("Could not create input builder.", true); - return; - } - - mState = State.Builder; - } - - public void Update() - { - if (mState == State.Finished) - // Nothing to do. - return; - - NavmeshBuild build = mContext.Build; - - if (!build) - { - FinalizeOnFail("Build has been deleted.", true); - return; - } - - if (mContext.Build.BuildState == NavmeshBuildState.Invalid) - { - FinalizeOnFail("Build has become invalid. Discarded input compile", true); - return; - } - - if (mState == State.Builder) - UpdateBuilder(); - else - UpdateTask(); - } - - private void UpdateTask() - { - if (!mTask.IsFinished) - return; - - mLogger.Log(mTask.Messages); - - if (mTask.TaskState == BuildTaskState.Aborted) - { - FinalizeOnFail("Input geometry build failed.", true); - return; - } - - mGeometry = mTask.Result; - - mLogger.PostTrace("Completed input geometry build.", mTask.Messages, mContext.Build); - mTask = null; - - mState = State.Finished; - } - - private void UpdateBuilder() - { - if (!mBuilder.IsFinished) - { - mBuilder.Build(); - return; - } - - mLogger.Log(mBuilder.Messages); - - NavmeshBuild build = mContext.Build; // Caller has validated. - - if (mBuilder.State == InputBuildState.Aborted) - { - FinalizeOnFail("Input data compile failed: Builder aborted.", true); - return; - } - - mAssets = mBuilder.Result; - - TriangleMesh mesh = mAssets.geometry; - - if (!InputGeometryBuilder.IsValid(mesh, mAssets.areas)) - { - FinalizeOnFail("Input geometry failed validation. (Malformed data.)", true); - return; - } - - InputGeometryBuilder gbuilder = InputGeometryBuilder.UnsafeCreate(mesh - , mAssets.areas - , build.Config.GetConfig().WalkableSlope - , true); - - if (gbuilder == null) - { - FinalizeOnFail("Could not create input geometry builder. (Internal error.)", true); - return; - } - - // Release unneeded assets. - mAssets.geometry = null; - mAssets.areas = null; - mBuilder = null; - - mTask = InputBuildTask.Create(gbuilder, BuildTaskProcessor.HighPriority); - - if (mTask == null) - FinalizeOnFail("Task creation failed. (Internal error.)", true); - else if (mContext.QueueTask(mTask)) - { - mLogger.PostTrace("Completed input build. Submitted geometry build task." - , mContext.Build); - mState = State.Task; - } - else - FinalizeOnFail("Task submission failed. (Internal error.)", true); - - } - - public void OnGUI(Rect area) - { - switch (mState) - { - case State.Builder: - - EditorGUI.ProgressBar(area - , InputBuilder.ToProgress(mBuilder.State) - , InputBuilder.ToLabel(mBuilder.State)); - - break; - - case State.Task: - - float delta = (float)(EditorApplication.timeSinceStartup - mChunkTime); - - if (delta > 15) - { - mChunkTime = EditorApplication.timeSinceStartup; - delta = 0; - } - - EditorGUI.ProgressBar(area - , (delta / 15) - , "Chunking geometry..."); - - break; - } - } - - public void Abort() - { - FinalizeOnFail("User requested abort.", false); - } - - private void FinalizeOnFail(string message, bool postError) - { - if (mTask != null) - { - mTask.Abort(message); - mTask = null; - } - - if (postError) - mLogger.PostError(message, mContext.Build); - - mBuilder = null; - mGeometry = null; - mAssets = new InputAssets(); - mState = State.Finished; - } - } -} diff --git a/critterai/.svn/pristine/ee/eee8fbb0bc8bf3cd11350a8fff8a1f35c021b526.svn-base b/critterai/.svn/pristine/ee/eee8fbb0bc8bf3cd11350a8fff8a1f35c021b526.svn-base deleted file mode 100644 index c6168107..00000000 --- a/critterai/.svn/pristine/ee/eee8fbb0bc8bf3cd11350a8fff8a1f35c021b526.svn-base +++ /dev/null @@ -1,620 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" - - -static const int RC_MAX_LAYERS = RC_NOT_CONNECTED; -static const int RC_MAX_NEIS = 16; - -struct rcLayerRegion -{ - unsigned char layers[RC_MAX_LAYERS]; - unsigned char neis[RC_MAX_NEIS]; - unsigned short ymin, ymax; - unsigned char layerId; // Layer ID - unsigned char nlayers; // Layer count - unsigned char nneis; // Neighbour count - unsigned char base; // Flag indicating if the region is hte base of merged regions. -}; - - -static void addUnique(unsigned char* a, unsigned char& an, unsigned char v) -{ - const int n = (int)an; - for (int i = 0; i < n; ++i) - if (a[i] == v) - return; - a[an] = v; - an++; -} - -static bool contains(const unsigned char* a, const unsigned char an, const unsigned char v) -{ - const int n = (int)an; - for (int i = 0; i < n; ++i) - if (a[i] == v) - return true; - return false; -} - -inline bool overlapRange(const unsigned short amin, const unsigned short amax, - const unsigned short bmin, const unsigned short bmax) -{ - return (amin > bmax || amax < bmin) ? false : true; -} - - - -struct rcLayerSweepSpan -{ - unsigned short ns; // number samples - unsigned char id; // region id - unsigned char nei; // neighbour id -}; - -/// @par -/// -/// See the #rcConfig documentation for more information on the configuration parameters. -/// -/// @see rcAllocHeightfieldLayerSet, rcCompactHeightfield, rcHeightfieldLayerSet, rcConfig -bool rcBuildHeightfieldLayers(rcContext* ctx, rcCompactHeightfield& chf, - const int borderSize, const int walkableHeight, - rcHeightfieldLayerSet& lset) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_BUILD_LAYERS); - - const int w = chf.width; - const int h = chf.height; - - rcScopedDelete srcReg = (unsigned char*)rcAlloc(sizeof(unsigned char)*chf.spanCount, RC_ALLOC_TEMP); - if (!srcReg) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'srcReg' (%d).", chf.spanCount); - return false; - } - memset(srcReg,0xff,sizeof(unsigned char)*chf.spanCount); - - const int nsweeps = chf.width; - rcScopedDelete sweeps = (rcLayerSweepSpan*)rcAlloc(sizeof(rcLayerSweepSpan)*nsweeps, RC_ALLOC_TEMP); - if (!sweeps) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'sweeps' (%d).", nsweeps); - return false; - } - - - // Partition walkable area into monotone regions. - int prevCount[256]; - unsigned char regId = 0; - - for (int y = borderSize; y < h-borderSize; ++y) - { - memset(prevCount,0,sizeof(int)*regId); - unsigned char sweepId = 0; - - for (int x = borderSize; x < w-borderSize; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - if (chf.areas[i] == RC_NULL_AREA) continue; - - unsigned char sid = 0xff; - - // -x - if (rcGetCon(s, 0) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(0); - const int ay = y + rcGetDirOffsetY(0); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 0); - if (chf.areas[ai] != RC_NULL_AREA && srcReg[ai] != 0xff) - sid = srcReg[ai]; - } - - if (sid == 0xff) - { - sid = sweepId++; - sweeps[sid].nei = 0xff; - sweeps[sid].ns = 0; - } - - // -y - if (rcGetCon(s,3) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(3); - const int ay = y + rcGetDirOffsetY(3); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, 3); - const unsigned char nr = srcReg[ai]; - if (nr != 0xff) - { - // Set neighbour when first valid neighbour is encoutered. - if (sweeps[sid].ns == 0) - sweeps[sid].nei = nr; - - if (sweeps[sid].nei == nr) - { - // Update existing neighbour - sweeps[sid].ns++; - prevCount[nr]++; - } - else - { - // This is hit if there is nore than one neighbour. - // Invalidate the neighbour. - sweeps[sid].nei = 0xff; - } - } - } - - srcReg[i] = sid; - } - } - - // Create unique ID. - for (int i = 0; i < sweepId; ++i) - { - // If the neighbour is set and there is only one continuous connection to it, - // the sweep will be merged with the previous one, else new region is created. - if (sweeps[i].nei != 0xff && prevCount[sweeps[i].nei] == (int)sweeps[i].ns) - { - sweeps[i].id = sweeps[i].nei; - } - else - { - if (regId == 255) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Region ID overflow."); - return false; - } - sweeps[i].id = regId++; - } - } - - // Remap local sweep ids to region ids. - for (int x = borderSize; x < w-borderSize; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - if (srcReg[i] != 0xff) - srcReg[i] = sweeps[srcReg[i]].id; - } - } - } - - // Allocate and init layer regions. - const int nregs = (int)regId; - rcScopedDelete regs = (rcLayerRegion*)rcAlloc(sizeof(rcLayerRegion)*nregs, RC_ALLOC_TEMP); - if (!regs) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'regs' (%d).", nregs); - return false; - } - memset(regs, 0, sizeof(rcLayerRegion)*nregs); - for (int i = 0; i < nregs; ++i) - { - regs[i].layerId = 0xff; - regs[i].ymin = 0xffff; - regs[i].ymax = 0; - } - - // Find region neighbours and overlapping regions. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - const rcCompactCell& c = chf.cells[x+y*w]; - - unsigned char lregs[RC_MAX_LAYERS]; - int nlregs = 0; - - for (int i = (int)c.index, ni = (int)(c.index+c.count); i < ni; ++i) - { - const rcCompactSpan& s = chf.spans[i]; - const unsigned char ri = srcReg[i]; - if (ri == 0xff) continue; - - regs[ri].ymin = rcMin(regs[ri].ymin, s.y); - regs[ri].ymax = rcMax(regs[ri].ymax, s.y); - - // Collect all region layers. - if (nlregs < RC_MAX_LAYERS) - lregs[nlregs++] = ri; - - // Update neighbours - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = x + rcGetDirOffsetX(dir); - const int ay = y + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); - const unsigned char rai = srcReg[ai]; - if (rai != 0xff && rai != ri) - addUnique(regs[ri].neis, regs[ri].nneis, rai); - } - } - - } - - // Update overlapping regions. - for (int i = 0; i < nlregs-1; ++i) - { - for (int j = i+1; j < nlregs; ++j) - { - if (lregs[i] != lregs[j]) - { - rcLayerRegion& ri = regs[lregs[i]]; - rcLayerRegion& rj = regs[lregs[j]]; - addUnique(ri.layers, ri.nlayers, lregs[j]); - addUnique(rj.layers, rj.nlayers, lregs[i]); - } - } - } - - } - } - - // Create 2D layers from regions. - unsigned char layerId = 0; - - static const int MAX_STACK = 64; - unsigned char stack[MAX_STACK]; - int nstack = 0; - - for (int i = 0; i < nregs; ++i) - { - rcLayerRegion& root = regs[i]; - // Skip alreadu visited. - if (root.layerId != 0xff) - continue; - - // Start search. - root.layerId = layerId; - root.base = 1; - - nstack = 0; - stack[nstack++] = (unsigned char)i; - - while (nstack) - { - // Pop front - rcLayerRegion& reg = regs[stack[0]]; - nstack--; - for (int j = 0; j < nstack; ++j) - stack[j] = stack[j+1]; - - const int nneis = (int)reg.nneis; - for (int j = 0; j < nneis; ++j) - { - const unsigned char nei = reg.neis[j]; - rcLayerRegion& regn = regs[nei]; - // Skip already visited. - if (regn.layerId != 0xff) - continue; - // Skip if the neighbour is overlapping root region. - if (contains(root.layers, root.nlayers, nei)) - continue; - // Skip if the height range would become too large. - const int ymin = rcMin(root.ymin, regn.ymin); - const int ymax = rcMin(root.ymax, regn.ymax); - if ((ymax - ymin) >= 255) - continue; - - if (nstack < MAX_STACK) - { - // Deepen - stack[nstack++] = (unsigned char)nei; - - // Mark layer id - regn.layerId = layerId; - // Merge current layers to root. - for (int k = 0; k < regn.nlayers; ++k) - addUnique(root.layers, root.nlayers, regn.layers[k]); - root.ymin = rcMin(root.ymin, regn.ymin); - root.ymax = rcMax(root.ymax, regn.ymax); - } - } - } - - layerId++; - } - - // Merge non-overlapping regions that are close in height. - const unsigned short mergeHeight = (unsigned short)walkableHeight * 4; - - for (int i = 0; i < nregs; ++i) - { - rcLayerRegion& ri = regs[i]; - if (!ri.base) continue; - - unsigned char newId = ri.layerId; - - for (;;) - { - unsigned char oldId = 0xff; - - for (int j = 0; j < nregs; ++j) - { - if (i == j) continue; - rcLayerRegion& rj = regs[j]; - if (!rj.base) continue; - - // Skip if teh regions are not close to each other. - if (!overlapRange(ri.ymin,ri.ymax+mergeHeight, rj.ymin,rj.ymax+mergeHeight)) - continue; - // Skip if the height range would become too large. - const int ymin = rcMin(ri.ymin, rj.ymin); - const int ymax = rcMin(ri.ymax, rj.ymax); - if ((ymax - ymin) >= 255) - continue; - - // Make sure that there is no overlap when mergin 'ri' and 'rj'. - bool overlap = false; - // Iterate over all regions which have the same layerId as 'rj' - for (int k = 0; k < nregs; ++k) - { - if (regs[k].layerId != rj.layerId) - continue; - // Check if region 'k' is overlapping region 'ri' - // Index to 'regs' is the same as region id. - if (contains(ri.layers,ri.nlayers, (unsigned char)k)) - { - overlap = true; - break; - } - } - // Cannot merge of regions overlap. - if (overlap) - continue; - - // Can merge i and j. - oldId = rj.layerId; - break; - } - - // Could not find anything to merge with, stop. - if (oldId == 0xff) - break; - - // Merge - for (int j = 0; j < nregs; ++j) - { - rcLayerRegion& rj = regs[j]; - if (rj.layerId == oldId) - { - rj.base = 0; - // Remap layerIds. - rj.layerId = newId; - // Add overlaid layers from 'rj' to 'ri'. - for (int k = 0; k < rj.nlayers; ++k) - addUnique(ri.layers, ri.nlayers, rj.layers[k]); - // Update heigh bounds. - ri.ymin = rcMin(ri.ymin, rj.ymin); - ri.ymax = rcMax(ri.ymax, rj.ymax); - } - } - } - } - - // Compact layerIds - unsigned char remap[256]; - memset(remap, 0, 256); - - // Find number of unique layers. - layerId = 0; - for (int i = 0; i < nregs; ++i) - remap[regs[i].layerId] = 1; - for (int i = 0; i < 256; ++i) - { - if (remap[i]) - remap[i] = layerId++; - else - remap[i] = 0xff; - } - // Remap ids. - for (int i = 0; i < nregs; ++i) - regs[i].layerId = remap[regs[i].layerId]; - - // No layers, return empty. - if (layerId == 0) - { - ctx->stopTimer(RC_TIMER_BUILD_LAYERS); - return true; - } - - // Create layers. - rcAssert(lset.layers == 0); - - const int lw = w - borderSize*2; - const int lh = h - borderSize*2; - - // Build contracted bbox for layers. - float bmin[3], bmax[3]; - rcVcopy(bmin, chf.bmin); - rcVcopy(bmax, chf.bmax); - bmin[0] += borderSize*chf.cs; - bmin[2] += borderSize*chf.cs; - bmax[0] -= borderSize*chf.cs; - bmax[2] -= borderSize*chf.cs; - - lset.nlayers = (int)layerId; - - lset.layers = (rcHeightfieldLayer*)rcAlloc(sizeof(rcHeightfieldLayer)*lset.nlayers, RC_ALLOC_PERM); - if (!lset.layers) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'layers' (%d).", lset.nlayers); - return false; - } - memset(lset.layers, 0, sizeof(rcHeightfieldLayer)*lset.nlayers); - - - // Store layers. - for (int i = 0; i < lset.nlayers; ++i) - { - unsigned char curId = (unsigned char)i; - - // Allocate memory for the current layer. - rcHeightfieldLayer* layer = &lset.layers[i]; - memset(layer, 0, sizeof(rcHeightfieldLayer)); - - const int gridSize = sizeof(unsigned char)*lw*lh; - - layer->heights = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM); - if (!layer->heights) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'heights' (%d).", gridSize); - return false; - } - memset(layer->heights, 0xff, gridSize); - - layer->areas = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM); - if (!layer->areas) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'areas' (%d).", gridSize); - return false; - } - memset(layer->areas, 0, gridSize); - - layer->cons = (unsigned char*)rcAlloc(gridSize, RC_ALLOC_PERM); - if (!layer->cons) - { - ctx->log(RC_LOG_ERROR, "rcBuildHeightfieldLayers: Out of memory 'cons' (%d).", gridSize); - return false; - } - memset(layer->cons, 0, gridSize); - - // Find layer height bounds. - int hmin = 0, hmax = 0; - for (int j = 0; j < nregs; ++j) - { - if (regs[j].base && regs[j].layerId == curId) - { - hmin = (int)regs[j].ymin; - hmax = (int)regs[j].ymax; - } - } - - layer->width = lw; - layer->height = lh; - layer->cs = chf.cs; - layer->ch = chf.ch; - - // Adjust the bbox to fit the heighfield. - rcVcopy(layer->bmin, bmin); - rcVcopy(layer->bmax, bmax); - layer->bmin[1] = bmin[1] + hmin*chf.ch; - layer->bmax[1] = bmin[1] + hmax*chf.ch; - layer->hmin = hmin; - layer->hmax = hmax; - - // Update usable data region. - layer->minx = layer->width; - layer->maxx = 0; - layer->miny = layer->height; - layer->maxy = 0; - - // Copy height and area from compact heighfield. - for (int y = 0; y < lh; ++y) - { - for (int x = 0; x < lw; ++x) - { - const int cx = borderSize+x; - const int cy = borderSize+y; - const rcCompactCell& c = chf.cells[cx+cy*w]; - for (int j = (int)c.index, nj = (int)(c.index+c.count); j < nj; ++j) - { - const rcCompactSpan& s = chf.spans[j]; - // Skip unassigned regions. - if (srcReg[j] == 0xff) - continue; - // Skip of does nto belong to current layer. - unsigned char lid = regs[srcReg[j]].layerId; - if (lid != curId) - continue; - - // Update data bounds. - layer->minx = rcMin(layer->minx, x); - layer->maxx = rcMax(layer->maxx, x); - layer->miny = rcMin(layer->miny, y); - layer->maxy = rcMax(layer->maxy, y); - - // Store height and area type. - const int idx = x+y*lw; - layer->heights[idx] = (unsigned char)(s.y - hmin); - layer->areas[idx] = chf.areas[j]; - - // Check connection. - unsigned char portal = 0; - unsigned char con = 0; - for (int dir = 0; dir < 4; ++dir) - { - if (rcGetCon(s, dir) != RC_NOT_CONNECTED) - { - const int ax = cx + rcGetDirOffsetX(dir); - const int ay = cy + rcGetDirOffsetY(dir); - const int ai = (int)chf.cells[ax+ay*w].index + rcGetCon(s, dir); - unsigned char alid = srcReg[ai] != 0xff ? regs[srcReg[ai]].layerId : 0xff; - // Portal mask - if (chf.areas[ai] != RC_NULL_AREA && lid != alid) - { - portal |= (unsigned char)(1< hmin) - layer->heights[idx] = rcMax(layer->heights[idx], (unsigned char)(as.y - hmin)); - } - // Valid connection mask - if (chf.areas[ai] != RC_NULL_AREA && lid == alid) - { - const int nx = ax - borderSize; - const int ny = ay - borderSize; - if (nx >= 0 && ny >= 0 && nx < lw && ny < lh) - con |= (unsigned char)(1<cons[idx] = (portal << 4) | con; - } - } - } - - if (layer->minx > layer->maxx) - layer->minx = layer->maxx = 0; - if (layer->miny > layer->maxy) - layer->miny = layer->maxy = 0; - } - - ctx->stopTimer(RC_TIMER_BUILD_LAYERS); - - return true; -} diff --git a/critterai/.svn/pristine/f0/f00fd6adde126a5fe3d7d41c3c623725bed4fc63.svn-base b/critterai/.svn/pristine/f0/f00fd6adde126a5fe3d7d41c3c623725bed4fc63.svn-base deleted file mode 100644 index 5b677c05..00000000 --- a/critterai/.svn/pristine/f0/f00fd6adde126a5fe3d7d41c3c623725bed4fc63.svn-base +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.critterai.math.Vector3; - -/** - * Provides operations related to triangles in 3-dimensional space. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No checks are performed to ensure the arguments represent a valid triangle, - * no null checks of arguments, etc.

      - *

      Static operations are thread safe.

      - */ -public final class Triangle3 -{ - - /** - * Returns the area of the triangle ABC. - *

      WARNING: This is an costly operation. If the value is only needed for comparison with other - * triangles, then use - * {@link #getAreaComp(float, float, float, float, float, float, float, float, float) getAreaComp()} - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param az The z-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param bz The z-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @param cz The z-value for vertex C in triangle ABC - * @return The area of the triangle ABC. - */ - public static float getArea( - float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz) - { - return (float)(Math.sqrt(getAreaComp(ax, ay, az, bx, by, bz, cx, cy, cz)) / 2); - } - - /** - * Returns a value suitable for comparing the relative size of two triangles. - * E.g. Is triangleA larger than triangleB. - *

      The value returned by this operation can be converted to area as follows: - * Area = Math.sqrt(value)/2

      - *

      Useful for quickly comparing the size of triangles.

      - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param az The z-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param bz The z-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @param cz The z-value for vertex C in triangle ABC - * @return A value suitable for comparing the relative size of two triangles. - */ - public static float getAreaComp( - float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz) - { - - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - - // Get directional vectors. - // A -> B - float ux = bx - ax; - float uy = by - ay; - float uz = bz - az; - // A -> C - float vx = cx - ax; - float vy = cy - ay; - float vz = cz - az; - - // Cross product. - float nx = uy * vz - uz * vy; - float ny = -ux * vz + uz * vx; - float nz = ux * vy - uy * vx; - - return Vector3.getLengthSq(nx, ny, nz); - - } - - /** - * Returns the normal for the triangle. (The vector perpendicular to - * the triangle's plane.) The direction of the normal is determined by - * the right-handed rule. - *

      WARNING: This is a costly operation.

      - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param az The z-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param bz The z-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @param cz The z-value for vertex C in triangle ABC - * @param out The vector to store the result in. - * @return A reference to the out argument. - */ - public static Vector3 getNormal(float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz - , Vector3 out) - { - - // Reference: http://en.wikipedia.org/wiki/Surface_normal#Calculating_a_surface_normal - // N = (B - A) x (C - A) with the final result normalized. - - Vector3.cross(bx - ax - , by - ay - , bz - az - , cx - ax - , cy - ay - , cz - az - , out); - out.normalize(); - - return out; - - } - - /** - * Returns the normal for the triangle. (The vector perpendicular to - * the triangle's plane.) The direction of the normal is determined by - * the right-handed rule. - *

      WARNING: This is a costly operation.

      - * @param vertices An array of vertices which contains a representation of triangles in the - * form (ax, ay, az, bx, by, bz, cx, cy, cz). The wrap direction is expected to be - * clockwise. - * @param startVertIndex The index of the first vertex in the triangle. - * @param out The vector to store the result in. - * @return A reference to the out argument. - */ - public static Vector3 getNormal(float[] vertices, int startVertIndex, Vector3 out) - { - - int pStartVert = startVertIndex*3; - return getNormal(vertices[pStartVert], vertices[pStartVert+1], vertices[pStartVert+2] - , vertices[pStartVert+3], vertices[pStartVert+4], vertices[pStartVert+5] - , vertices[pStartVert+6], vertices[pStartVert+7], vertices[pStartVert+8] - , out); - } - -} diff --git a/critterai/.svn/pristine/f0/f021a3deba7b907fadfd68c310d8869942af5417.svn-base b/critterai/.svn/pristine/f0/f021a3deba7b907fadfd68c310d8869942af5417.svn-base deleted file mode 100644 index 5118279b..00000000 --- a/critterai/.svn/pristine/f0/f021a3deba7b907fadfd68c310d8869942af5417.svn-base +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using Math = System.Math; -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.nav -{ - /// - /// Provides utilities related to navigation. - /// - public static class NavUtil - { - /// - /// Returns true if the status includes the success flag. - /// - /// The status to check. - /// True if the status includes the success flag. - public static bool Succeeded(NavStatus status) - { - return (status & NavStatus.Sucess) != 0; - } - - /// - /// Returns true if the status includes the failure flag. - /// - /// The status to check. - /// True if the status includes the failure flag. - public static bool Failed(NavStatus status) - { - return (status & NavStatus.Failure) != 0; - } - - /// - /// Returns true if the status includes the in-progress flag. - /// - /// The status to check. - /// True if the status includes the in-progress flag. - /// - public static bool IsInProgress(NavStatus status) - { - return (status & NavStatus.InProgress) != 0; - } - - /// - /// Clamps the value to the valid area range. - /// (0 <= value <= ) - /// - /// The value to clamp. - /// A valid area. - public static byte ClampArea(byte value) - { - return Math.Min(Navmesh.MaxArea, value); - } - - /// - /// Clamps the value to the valid area range. - /// (0 <= value <= ) - /// - /// The value to clamp. - /// A valid area. - public static byte ClampArea(int value) - { - return (byte)Math.Min(Navmesh.MaxArea, Math.Max(0, value)); - } - - /// - /// Derives the for a tile. - /// - /// - /// - /// This method is useful for getting the configuration required to build a single-tile - /// navigation mesh for the tile. - /// - /// - /// The tile. - /// The for the tile. - public static NavmeshParams DeriveConfig(NavmeshTileData tile) - { - NavmeshTileHeader header = tile.GetHeader(); - - return new NavmeshParams(header.boundsMin - , header.boundsMax.x - header.boundsMin.x - , header.boundsMax.z - header.boundsMin.z - , 1 // Max tiles. - , header.polyCount); - } - - /// - /// Tests that vector interop behaves as expected. - /// - /// - /// - /// If the test is successful the input and return vectors will be equal in value. - /// - /// - /// This method is used to validate that builds using custom vectors behaves correctly - /// with interop. (I.e. The custom vector is data compatible.) - /// - /// - /// The input vector. - /// - /// A vector equal to the input vector if interop is functioning as expected. - /// - public static Vector3 TestVector(Vector3 v) - { - Vector3 result = new Vector3(); - rcn.InteropUtil.dtvlVectorTest(ref v, ref result); - return result; - } - - /// - /// Tests that vector interop behaves as expected for vector arrays. - /// - /// - /// - /// If the test is successful the input and result arrays will be equal in length and - /// element values. (E.g. vectors[i] == result[i]) - /// - /// - /// This method is used to validate that builds using custom vectors behaves correctly - /// with interop. (I.e. The custom vector is data compatible.) - /// - /// - /// - /// The input vector array. [Length: >= ] - /// - /// The number of vectors in the array. - /// - /// The array to load the result into. [Length: >= ] - /// - public static void TestVectorArray(Vector3[] vectors, int vectorCount, Vector3[] result) - { - rcn.InteropUtil.dtvlVectorArrayTest(vectors, vectorCount, result); - } - } -} diff --git a/critterai/.svn/pristine/f1/f105a8fa4af8530a665349235341d223a244add4.svn-base b/critterai/.svn/pristine/f1/f105a8fa4af8530a665349235341d223a244add4.svn-base deleted file mode 100644 index 07b4a861..00000000 --- a/critterai/.svn/pristine/f1/f105a8fa4af8530a665349235341d223a244add4.svn-base +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Runtime.InteropServices; - -namespace org.critterai.nmgen -{ - /// - /// Respresents a span within a object. - /// - /// - /// - /// The span represents open, unobstructed space within a heightfield column. - /// - /// - /// See the documentation for a discussion of iterating spans - /// and searching span connections. - /// - /// - /// Useful instances of this type can only by obtained from a - /// object. - /// - /// - [StructLayout(LayoutKind.Sequential)] - public struct CompactSpan - { - private static readonly int[] offsetX = new int[4] { -1, 0, 1, 0 }; - private static readonly int[] offsetZ = new int[4] { 0, 1, 0, -1 }; - - /// - /// The value returned by if the specified direction is not - /// connected. - /// - public const int NotConnected = 0x3f; - - /// - /// The maximum for . - /// - /// - /// - /// If a span has no other span above it, its will return this value. - /// - /// - public const int MaxHeight = 0xffff; - - private ushort mFloor; - private ushort mRegion; - private uint mPacked; // [Cons, Height] - - /// - /// The height of the span's lower extent. (Measured from the heightfield's base.) - /// - /// - /// - /// The span's floor height in world units can be derived as follows: - /// - /// - /// fieldBoundsMin[1] + (Floor * fieldYCellSize) - /// - /// - public ushort Floor { get { return mFloor; } } - - /// - /// The id of the region the span belongs to. - /// - /// - /// - /// Non-null regions consist of connected, non-overlapping walkable spans. - /// - /// - /// A value of indicates the span is not part of any region, - /// or region data has not been built. - /// - /// - public ushort Region { get { return mRegion; } } - - /// - /// The packed neighbor connection data for the span. - /// - /// - /// - /// Normally is used to get the unpacked version of this data. - /// - /// - public uint Connections { get { return (mPacked & 0xffffff); } } - - /// - /// Gets neighbor connection data for the specified direction. - /// - /// - /// - /// Can be used to locate the neighbor span in the data structure. See the - /// documentation for details. - /// - /// - /// The direction. [Limits: 0 <= value < 4] - /// - /// The connection data for the specified direction, or if - /// there is no connection. - /// - public int GetConnection(int direction) - { - return (int)((Connections >> (direction * 6)) & 0x3f); - } - - /// - /// The height of the span's upper extent. (Measured from the span's floor.) - /// - /// - /// - /// The span's height in world units can be derived as follows: - /// - /// - /// fieldBoundsMin[1] + ((Floor + Height) * fieldYCellSize) - /// - /// - public byte Height { get { return (byte)(mPacked >> 24); } } - - /// - /// Gets the standard width offset for the specified direction. - /// - /// - /// - /// The direction value will be automatically wrapped. So the a value of 6 will be - /// interpreted as 2. - /// - /// - /// The direction. [Limits: 0 <= value < 4] - /// - /// The width offset to the apply to the current cell position to move in the direction. - /// - public static int GetDirOffsetX(int direction) - { - return offsetX[direction & 0x03]; - } - - /// - /// Gets the standard depth offset for the specified direction. - /// - /// - /// The direction value will be automatically wrapped. So the a value of 6 will be - /// interpreted as 2. - /// - /// - /// The direction. [Limits: 0 <= value < 4] - /// - /// The depth offset to the apply to the current cell position to move in the direction. - /// - public static int GetDirOffsetZ(int direction) - { - return offsetZ[direction & 0x03]; - } - } -} diff --git a/critterai/.svn/pristine/f2/f2867a9eecf522874f08cf6cf793680359dcc815.svn-base b/critterai/.svn/pristine/f2/f2867a9eecf522874f08cf6cf793680359dcc815.svn-base deleted file mode 100644 index cbe7cbfe..00000000 --- a/critterai/.svn/pristine/f2/f2867a9eecf522874f08cf6cf793680359dcc815.svn-base +++ /dev/null @@ -1,128 +0,0 @@ - - - - - Builds the CritterAI utility library. - Override the version property with -Dversion. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - - Project Home - and - - Source Code - -

      -

      - Copyright 2010 Stephen Pratt. All rights reserved. Use is subject to - - license terms. -

      -
      - - ]]> -
      -
      -
      - - - - - -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/f3/f301edbadc6862316b1d0bb690ef537986e8775b.svn-base b/critterai/.svn/pristine/f3/f301edbadc6862316b1d0bb690ef537986e8775b.svn-base deleted file mode 100644 index 034e1814..00000000 --- a/critterai/.svn/pristine/f3/f301edbadc6862316b1d0bb690ef537986e8775b.svn-base +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/critterai/.svn/pristine/f5/f50fb0199e3afdbfeb15bfb8f52e120792511326.svn-base b/critterai/.svn/pristine/f5/f50fb0199e3afdbfeb15bfb8f52e120792511326.svn-base deleted file mode 100644 index e835262c..00000000 --- a/critterai/.svn/pristine/f5/f50fb0199e3afdbfeb15bfb8f52e120792511326.svn-base +++ /dev/null @@ -1,15 +0,0 @@ - - - - -CritterAI Utility Library - - - - -

      The CritterAI Utilities library provides support functionality for various CritterAI projects.

      -

      Project Home
      -
      Project Source
      -License

      - - diff --git a/critterai/.svn/pristine/f5/f561b63f96321636d8df72a2e3ef306cf06b97d6.svn-base b/critterai/.svn/pristine/f5/f561b63f96321636d8df72a2e3ef306cf06b97d6.svn-base deleted file mode 100644 index 72090c14..00000000 --- a/critterai/.svn/pristine/f5/f561b63f96321636d8df72a2e3ef306cf06b97d6.svn-base +++ /dev/null @@ -1,68 +0,0 @@ - - - - Debug - AnyCPU - 9.0.21022 - 2.0 - {D2154397-4098-4170-BBB0-58714D84E4C8} - Library - Properties - org.critterai - cai-nav-u3d - v3.5 - 512 - - - true - full - false - ..\bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - ..\bin\Release\ - TRACE - prompt - 4 - ..\bin\Release\cai-nav-u3d.XML - - - - False - ..\..\..\..\..\..\Program Files (x86)\Unity\Editor\Data\Managed\UnityEngine.dll - - - - - - Properties\AssemblyInfo.cs - - - - - {AF812AB8-633B-4e23-ABA7-6D02082FB2EE} - cai-util-u3d - - - {42218E47-156D-46ff-84E0-119D47B0E4EB} - cai-nav - - - {C4B32B85-13F0-42b8-AC89-770BEFEAF022} - cai-util - - - - - \ No newline at end of file diff --git a/critterai/.svn/pristine/f5/f57295e9d07c150081d425103725d47f0156f45e.svn-base b/critterai/.svn/pristine/f5/f57295e9d07c150081d425103725d47f0156f45e.svn-base deleted file mode 100644 index d828c4df..00000000 --- a/critterai/.svn/pristine/f5/f57295e9d07c150081d425103725d47f0156f45e.svn-base +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System.Collections.Generic; -using org.critterai.nmbuild; -using org.critterai.nmbuild.u3d.editor; -using UnityEngine; - -/// -/// Loads and creates geometry from mesh filter components. (Editor Only) -/// -/// -/// -/// Loads mesh filters from the scene and compiles input geometry from attached meshes. -/// -/// -/// If colliders are set as preferred and a supported collider is colocated with the mesh filter, -/// the geometry will be created from the collider instead. Supported colliders include: -/// SphereCollider, BoxCollider, and MeshCollider. -/// -/// -[System.Serializable] -public sealed class MeshCompiler - : ScriptableObject, IInputBuildProcessor -{ - /// - /// Colocation option. (Whether or not to perfer colliders.) - /// - public MeshColocationOption colocationOption; - - /// - /// The priority of the processor. - /// - public int Priority { get { return NMBuild.MinPriority - 1; } } - - /// - /// The name of the processor - /// - public string Name { get { return name; } } - - /// - /// No duplicates allowed. (Always false.) - /// - public bool DuplicatesAllowed { get { return false; } } - - /// - /// Processes the context. - /// - /// - /// - /// Processes during the - /// and states. - /// - /// - /// The current state of the input build. - /// The input context to process. - /// False if the input build should abort. - public bool ProcessInput(InputBuildContext context, InputBuildState state) - { - if (context != null) - { - switch (state) - { - case InputBuildState.CompileInput: - - Compile(context); - break; - - case InputBuildState.LoadComponents: - - Load(context); - break; - } - } - - return true; - } - - private void Load(InputBuildContext context) - { - context.info.loaderCount++; - - int count = context.LoadFromScene(); - - context.Log(string.Format("{0}: Loaded {1} MeshFilters", name, count), this); - } - - private void Compile(InputBuildContext context) - { - context.info.compilerCount++; - - ColliderHelper colliderHelper = (colocationOption == MeshColocationOption.Collider) - ? new ColliderHelper() - : null; - - InputGeometryCompiler compiler = context.geomCompiler; - - List master = new List(context.components); - List areas = new List(context.areas); - - Queue filters = new Queue(); - - int count = 0; - int ignored = 0; - while (master.Count > 0) - { - byte area = 0; - - for (int i = master.Count - 1; i >= 0; i--) - { - Component item = master[i]; - - if (item is MeshFilter) - { - MeshFilter filter = (MeshFilter)item; - if (filter.sharedMesh == null) - { - ignored++; - areas.RemoveAt(i); - master.RemoveAt(i); - } - else - { - if (filters.Count == 0) - area = areas[i]; - - if (areas[i] == area) - { - count++; - filters.Enqueue(filter); - areas.RemoveAt(i); - master.RemoveAt(i); - } - } - } - else - { - areas.RemoveAt(i); - master.RemoveAt(i); - } - } - - if (filters.Count > 0) - CombineMeshes(filters, area, compiler, colliderHelper); - } - - if (colliderHelper != null) - colliderHelper.Dispose(); - - if (ignored > 0) - { - string msg = string.Format("{0}: Ignored {1} MeshFilters with a null mesh." - , name, ignored); - - context.Log(msg, this); - } - - context.Log(string.Format("{0}: Compiled {1} MeshFilters.", name, count), this); - } - - private void CombineMeshes(Queue filters - , byte area - , InputGeometryCompiler compiler - , ColliderHelper helper) - { - Queue combineInstances = new Queue(); - - while (filters.Count != 0) - { - MeshFilter filter = filters.Dequeue(); - - if (helper != null) - { - Collider collider = filter.GetComponent(); - - if (collider) - { - CombineInstance ci; - - if (helper.Get(collider, out ci)) - { - combineInstances.Enqueue(ci); - continue; - } - } - } - - // Note: Null shared meshes were filtered out by the calling method. - - for (int subIndex = 0; subIndex < filter.sharedMesh.subMeshCount; ++subIndex) - { - CombineInstance combineInstance = new CombineInstance(); - combineInstance.mesh = filter.sharedMesh; - combineInstance.transform = filter.transform.localToWorldMatrix; - combineInstance.subMeshIndex = subIndex; - - combineInstances.Enqueue(combineInstance); - } - } - - MeshUtil.CombineMeshes(combineInstances, area, compiler); - } -} diff --git a/critterai/.svn/pristine/f6/f66c4fd219e0442e0a0263f3348595715345e27d.svn-base b/critterai/.svn/pristine/f6/f66c4fd219e0442e0a0263f3348595715345e27d.svn-base deleted file mode 100644 index 579da405..00000000 --- a/critterai/.svn/pristine/f6/f66c4fd219e0442e0a0263f3348595715345e27d.svn-base +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using org.critterai.nav.rcn; -using org.critterai.interop; - -namespace org.critterai.nav -{ - /// - /// Defines area traversal cost and flag restrictions for navigation querys. - /// - /// - /// - /// The way filtering works, a navigation mesh polygon must have at least one flag set to ever - /// be considered by a query. So setting the include flags to 0 will always result in all - /// polygons being excluded. - /// - /// - /// The array form is used to access area cost. E.g. myFilter[5] = 2.5f - /// - /// - /// Warning: Behavior is undefined if an area index is out of range. The error may - /// result in a runtime error, or it may operate as if there is no problem whatsoever. - /// E.g. Setting and getting myFilter[myFilter.AreaCount] may get and set the value - /// normally. Do not write code that depends on this behavior since it may change in future - /// releases. - /// - /// - /// Behavior is undefined if used after disposal. - /// - /// - public sealed class NavmeshQueryFilter - : ManagedObject - { - /// - /// The default include flags. - /// - public const ushort DefaultIncludeFlags = 0xffff; - - /// - /// The default exclude flags. - /// - public const ushort DefaultExcludeFlags = 0; - - /// - /// The default area cost. - /// - public const float DefaultAreaCost = 1.0f; - - /// - ///dtQueryFilter object. - /// - internal IntPtr root = IntPtr.Zero; - - private int mAreaCount; - - /// - /// The number of in use areas. - /// - public int AreaCount - { - get { return mAreaCount; } - set { mAreaCount = Math.Min(Navmesh.MaxArea + 1, value); } - } - - /// - /// The traversal cost for each area, indexed by area. - /// [Default: ] - /// - /// The area. - /// The traversal cost of the area. - public float this[int index] - { - get { return NavmeshQueryFilterEx.dtqfGetAreaCost(root, index); } - set { NavmeshQueryFilterEx.dtqfSetAreaCost(root, index, value); } - } - - /// - /// The flags for polygons that should be included in the query. - /// [Default: ] - /// - /// - /// - /// A navigation mesh polygon must have at least one of these flags set in order to be - /// included in a query. All polygons will be excluded if this value is set to zero. - /// - /// - public ushort IncludeFlags - { - get { return NavmeshQueryFilterEx.dtqfGetIncludeFlags(root); } - set { NavmeshQueryFilterEx.dtqfSetIncludeFlags(root, value); } - } - - /// - /// The flags for polygons that should be excluded from the query. - /// [Default: ] - /// - /// - /// - /// If a polygon has any of these flags set it will be excluded by a query. - /// - /// - public ushort ExcludeFlags - { - get { return NavmeshQueryFilterEx.dtqfGetExcludeFlags(root); } - set { NavmeshQueryFilterEx.dtqfSetExcludeFlags(root, value); } - } - - /// - /// True if the object has been disposed and should no longer be used. - /// - public override bool IsDisposed - { - get { return (root == IntPtr.Zero); } - } - - /// - /// Constructor for a filter with the maximum number of areas. - /// ( + 1) - /// - public NavmeshQueryFilter() - : base(AllocType.Local) - { - root = NavmeshQueryFilterEx.dtqfAlloc(); - mAreaCount = Navmesh.MaxArea + 1; - } - - /// - /// Constructor. - /// - /// The number of used areas. - public NavmeshQueryFilter(int areaCount) - : base(AllocType.Local) - { - root = NavmeshQueryFilterEx.dtqfAlloc(); - mAreaCount = Math.Min(Navmesh.MaxArea + 1, mAreaCount); - } - - internal NavmeshQueryFilter(IntPtr filter, AllocType type) - : base(type) - { - root = filter; - mAreaCount = Navmesh.MaxArea + 1; - } - - /// - /// Destructor - /// - ~NavmeshQueryFilter() - { - RequestDisposal(); - } - - /// - /// Request all unmanaged resources controlled by the object be - /// immediately freed and the object marked as disposed. - /// - /// - /// - /// If the object was created using a public constructor the resources will be freed - /// immediately. - /// - /// - public override void RequestDisposal() - { - // Note: There is no external unmanaged allocation. - if (root != IntPtr.Zero && ResourceType == AllocType.Local) - NavmeshQueryFilterEx.dtqfFree(root); - root = IntPtr.Zero; - } - - /// - /// Creates a new filter with the same state as the current filter. - /// - /// A clone of the current filter. - public NavmeshQueryFilter Clone() - { - if (IsDisposed) - return null; - - int count = this.AreaCount; - - NavmeshQueryFilter result = new NavmeshQueryFilter(count); - result.ExcludeFlags = this.ExcludeFlags; - result.IncludeFlags = this.IncludeFlags; - - for (int i = 0; i < count; i++) - { - result[i] = this[i]; - } - - return result; - } - } -} diff --git a/critterai/.svn/pristine/f7/f764a5c1205c943737708553e8e502aabfb8df22.svn-base b/critterai/.svn/pristine/f7/f764a5c1205c943737708553e8e502aabfb8df22.svn-base deleted file mode 100644 index bf985c36..00000000 --- a/critterai/.svn/pristine/f7/f764a5c1205c943737708553e8e502aabfb8df22.svn-base +++ /dev/null @@ -1,207 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#define _USE_MATH_DEFINES -#include -#include -#include "Recast.h" -#include "RecastAssert.h" - -/// @par -/// -/// Allows the formation of walkable regions that will flow over low lying -/// objects such as curbs, and up structures such as stairways. -/// -/// Two neighboring spans are walkable if: rcAbs(currentSpan.smax - neighborSpan.smax) < waklableClimb -/// -/// @warning Will override the effect of #rcFilterLedgeSpans. So if both filters are used, call -/// #rcFilterLedgeSpans after calling this filter. -/// -/// @see rcHeightfield, rcConfig -void rcFilterLowHangingWalkableObstacles(rcContext* ctx, const int walkableClimb, rcHeightfield& solid) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_FILTER_LOW_OBSTACLES); - - const int w = solid.width; - const int h = solid.height; - - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - rcSpan* ps = 0; - bool previousWalkable = false; - unsigned char previousArea = RC_NULL_AREA; - - for (rcSpan* s = solid.spans[x + y*w]; s; ps = s, s = s->next) - { - const bool walkable = s->area != RC_NULL_AREA; - // If current span is not walkable, but there is walkable - // span just below it, mark the span above it walkable too. - if (!walkable && previousWalkable) - { - if (rcAbs((int)s->smax - (int)ps->smax) <= walkableClimb) - s->area = previousArea; - } - // Copy walkable flag so that it cannot propagate - // past multiple non-walkable objects. - previousWalkable = walkable; - previousArea = s->area; - } - } - } - - ctx->stopTimer(RC_TIMER_FILTER_LOW_OBSTACLES); -} - -/// @par -/// -/// A ledge is a span with one or more neighbors whose maximum is further away than @p walkableClimb -/// from the current span's maximum. -/// This method removes the impact of the overestimation of conservative voxelization -/// so the resulting mesh will not have regions hanging in the air over ledges. -/// -/// A span is a ledge if: rcAbs(currentSpan.smax - neighborSpan.smax) > walkableClimb -/// -/// @see rcHeightfield, rcConfig -void rcFilterLedgeSpans(rcContext* ctx, const int walkableHeight, const int walkableClimb, - rcHeightfield& solid) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_FILTER_BORDER); - - const int w = solid.width; - const int h = solid.height; - const int MAX_HEIGHT = 0xffff; - - // Mark border spans. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next) - { - // Skip non walkable spans. - if (s->area == RC_NULL_AREA) - continue; - - const int bot = (int)(s->smax); - const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT; - - // Find neighbours minimum height. - int minh = MAX_HEIGHT; - - // Min and max height of accessible neighbours. - int asmin = s->smax; - int asmax = s->smax; - - for (int dir = 0; dir < 4; ++dir) - { - int dx = x + rcGetDirOffsetX(dir); - int dy = y + rcGetDirOffsetY(dir); - // Skip neighbours which are out of bounds. - if (dx < 0 || dy < 0 || dx >= w || dy >= h) - { - minh = rcMin(minh, -walkableClimb - bot); - continue; - } - - // From minus infinity to the first span. - rcSpan* ns = solid.spans[dx + dy*w]; - int nbot = -walkableClimb; - int ntop = ns ? (int)ns->smin : MAX_HEIGHT; - // Skip neightbour if the gap between the spans is too small. - if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight) - minh = rcMin(minh, nbot - bot); - - // Rest of the spans. - for (ns = solid.spans[dx + dy*w]; ns; ns = ns->next) - { - nbot = (int)ns->smax; - ntop = ns->next ? (int)ns->next->smin : MAX_HEIGHT; - // Skip neightbour if the gap between the spans is too small. - if (rcMin(top,ntop) - rcMax(bot,nbot) > walkableHeight) - { - minh = rcMin(minh, nbot - bot); - - // Find min/max accessible neighbour height. - if (rcAbs(nbot - bot) <= walkableClimb) - { - if (nbot < asmin) asmin = nbot; - if (nbot > asmax) asmax = nbot; - } - - } - } - } - - // The current span is close to a ledge if the drop to any - // neighbour span is less than the walkableClimb. - if (minh < -walkableClimb) - s->area = RC_NULL_AREA; - - // If the difference between all neighbours is too large, - // we are at steep slope, mark the span as ledge. - if ((asmax - asmin) > walkableClimb) - { - s->area = RC_NULL_AREA; - } - } - } - } - - ctx->stopTimer(RC_TIMER_FILTER_BORDER); -} - -/// @par -/// -/// For this filter, the clearance above the span is the distance from the span's -/// maximum to the next higher span's minimum. (Same grid column.) -/// -/// @see rcHeightfield, rcConfig -void rcFilterWalkableLowHeightSpans(rcContext* ctx, int walkableHeight, rcHeightfield& solid) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_FILTER_WALKABLE); - - const int w = solid.width; - const int h = solid.height; - const int MAX_HEIGHT = 0xffff; - - // Remove walkable flag from spans which do not have enough - // space above them for the agent to stand there. - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - for (rcSpan* s = solid.spans[x + y*w]; s; s = s->next) - { - const int bot = (int)(s->smax); - const int top = s->next ? (int)(s->next->smin) : MAX_HEIGHT; - if ((top - bot) <= walkableHeight) - s->area = RC_NULL_AREA; - } - } - } - - ctx->stopTimer(RC_TIMER_FILTER_WALKABLE); -} diff --git a/critterai/.svn/pristine/f7/f7a0af1eb51c4348404e6c5bf4758841682bcd66.svn-base b/critterai/.svn/pristine/f7/f7a0af1eb51c4348404e6c5bf4758841682bcd66.svn-base deleted file mode 100644 index b28dd55f..00000000 --- a/critterai/.svn/pristine/f7/f7a0af1eb51c4348404e6c5bf4758841682bcd66.svn-base +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - - - The navigation mesh is the primary data model for the navigation system. The only user - component that deals directly with the mesh on a regular basis is the component that is - responsible for creating the mesh and managing its state. Normal navigation clients, - the one's needing to perform pathfinding and such, rarely if ever interact directly with the - navigation mesh. - - - Core Class: Navmesh - - - -
      - - The Data Model - - - -
      - - Tiles - - - - - At the core of the navigation mesh is the tile. Tiles hold the vast majority of structural - and state information. In fact, the Navmesh class is little more than a tile manager. - It may consist of a single tile, or many tiles laid out in a grid that can be swapped in and out - at runtime. - - - - The tile based structure of the navigation mesh adds a lot of flexibility. As mentioned, - tiles can be swapped in and out at runtime. This means that the mesh can represent a large - area, but not all tiles have to be loaded and active, reducing the mesh's memory footprint. This also allows - for a situation where individual tiles can be rebuilt without the need to rebuild the entire mesh. - - - - -
      - -
      - - Structural Elements - - - - - The tile's structural data is what defines the navigation graph used for pathfinding. It consists - of two types of elements: Polygons and off-mesh connections. - - - - The core of the structure is a mesh of convex polygons with between three and - F:org.critterai.nmgen.NMGen.MaxAllowedVertsPerPoly vertices. This - mesh is in the same format as NMGen's PolyMesh structure, and usually represents an abstraction - of a scene's static geometry. - - - - Off-mesh connections are optional. They consist of two connected endpoints, at least one of which resides within a - polygon in the polygon mesh. Off-mesh connections are added to the navigation graph as a single edge and - represent special travel routes not defined by scene geometry. Think: The route an agent travels if it jumps - over a railing that normally blocks movement. - - - - -
      - -
      - - State Data - - - - - Tiles also contain state data. This data is associated with individual polygons and off-mesh connections. State - data includes area and flags. - - - - Areas are used to associate traversal cost to structural elements. This effects pathfinding. For example, - the area representing swampland can have a higher cost than the area representing smooth surfaces such as meadowland. - - - - Flags can be used to control when a structural element is traversable. For example, a - flag can be set on the polygon below a door to indicate that it is closed and locked. Or a flag can indicate - that only agents of a particular type are allowed to traverse the element. - - - - It is important to note that areas and flags have no meaning within the navigation mesh - itself. The interpretation of the values is dependant on the NavmeshQueryFilter - used by each navigation client. For example: One filter may define a cost of 10 for area id 5, while another may define - a cost of 2 for the same area. One flag may be set when a door is closed with one filter checking for the flag during - pathfinding, while another filter, used by a ghost, ignores the flag completely. - - - - -
      - -
      - - Structure Versus State - - - - Why is it important to know the difference between structural elements and state data? - - - The first reason is that it is possible to save and load state separately from structure. One common use case is to - have a serialized version of the full navigation mesh that represents its default state. Then serialized versions of various - states, such as the last runtime state, are used to overwrite the default state as needed. - - - - The main limitation is that a state is only valid for a particular structure. So you can't, for example, save the state, - change the tile structure, then load the original state into the new structure. - - - The second reason for understanding the difference between structure and state has to to with tile and polygon references... - - - -
      - -
      - - Tile and Polygon References - - - - - The last bit of information needed to understand the navigation mesh is the concept of tile and polygon references. These - values are one of the few data types that are defined by the navigation mesh rather than the tiles within the mesh. It is important to - understand what references are because they are used by various classes to automatically invalidate pathfinding data if the - structure of a navigation mesh changes. - - - - Essentially, tile and polygon references are unsigned integer 'handles' to structural elements within a navigation mesh. Tile references - are rarely used by navigation clients, while polygon references are all over the place. Polygon references are unique for the navigation mesh, - so they are useful for easily identifying a polygon without needing to know which tile it belongs to. - Despite the name, polygon references can refer to a either a polygon or an off-mesh connection. - - - - References can become invalid. If they are used after they are invalidated, then methods will return a failure status. - Polygon references are based on the tile reference. So they will be invalidated whenever their associated tile reference is invalidated. - - - - Structural changes govern the life of a reference. Changing the configuration of a navigation mesh or the internal structure of a tile - will invalidate all associated references. - - - - References are preserved during tile state changes such as changes flags and areas. They are also preserved during normal - runtime loading and unloading of tiles, and during normal serialization/de-serialization of a navigation mesh. - - - - -
      - -
      - -
      - -
      - - Creating a Navigation Mesh - - - - - There are various pipelines for creating a navigation mesh. If you are using Unity, the - Unity extensions make it easier. Otherwise, - the basic steps are as follows: - - - - Generate packed tile data: - - - - Generate PolyMesh and DetailMesh data using NMGen. - Optionally create a T:org.critterai.nmbuild.ConnectionSet. (Off-mesh connections.) - Load the data into a T:org.critterai.nav.NavmeshTileBuildData object. - Create a T:org.critterai.nav.NavmeshTileData object from the build data. - - - - The tile's structure and default state is now locked into a packed data format that is ready to be loaded into - a navigation mesh. - - - - - - Using the T:org.critterai.nav.NavmeshTileBuildData class - directly can be a bit daunting. The - - M:org.critterai.nmbuild.NMBuild.GetBuildData(org.critterai.nmgen.BuildContext,System.Int32,System.Int32,org.critterai.nmgen.PolyMeshData,org.critterai.nmgen.PolyMeshDetailData,org.critterai.nmbuild.ConnectionSet,System.Boolean) - - utility method provides a standard way of creating the build data. - - - - Create a navigation mesh: - - - Single tile navigation meshes are created using the the single step - M:org.critterai.nav.Navmesh.Create(org.critterai.nav.NavmeshTileBuildData,org.critterai.nav.Navmesh@) - method. - - - - Multi-tile navigation meshes are created then loaded using multiple methods. Use the - M:org.critterai.nav.Navmesh.Create(org.critterai.nav.NavmeshParams,org.critterai.nav.Navmesh@) - method to initialize an empty mesh. then add tile data using the - M:org.critterai.nav.Navmesh.AddTile(org.critterai.nav.NavmeshTileData,System.UInt32,System.UInt32@) - method. - - - - -
      - -
      - - Navigation Mesh Serialization - - - - - The Navmesh class supports byte serialization using the - M:org.critterai.nav.Navmesh.GetSerializedMesh - method. This saves the entire mesh. - - - - It is possible to serialize state separately from structure on a tile-by-tile basis. Get the tile - from the mesh using the M:org.critterai.nav.Navmesh.GetTile(System.Int32) method, then use the - M:org.critterai.nav.NavmeshTile.GetState(System.Byte[]) and - M:org.critterai.nav.NavmeshTile.SetState(System.Byte[]) methods. - - - - -
      - - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshTileBuildData - T:org.critterai.nav.NavmeshTileData - T:org.critterai.nav.NavmeshTile - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/.svn/pristine/f8/f88fbd78e8eb5bd82b1e1b24bff9d7d38f803534.svn-base b/critterai/.svn/pristine/f8/f88fbd78e8eb5bd82b1e1b24bff9d7d38f803534.svn-base deleted file mode 100644 index af555b7d..00000000 --- a/critterai/.svn/pristine/f8/f88fbd78e8eb5bd82b1e1b24bff9d7d38f803534.svn-base +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include "DetourCommon.h" -#include "DetourPathCorridor.h" -#include "DetourEx.h" - -extern "C" -{ - EXPORT_API dtPathCorridor* dtpcAlloc(const int maxPath) - { - dtPathCorridor* corridor = new dtPathCorridor(); - if (corridor) - corridor->init(maxPath); - return corridor; - } - - EXPORT_API void dtpcFree(dtPathCorridor* corridor) - { - if (corridor) - corridor->~dtPathCorridor(); - } - - EXPORT_API void dtpcReset(dtPathCorridor* corridor - , rcnNavmeshPoint pos) - { - // Note: The reset accepts the position without checking its validity. - if (corridor) - corridor->reset(pos.polyRef, &pos.point[0]); - } - - EXPORT_API int dtpcFindCorners(dtPathCorridor* corridor - , float* cornerVerts - , unsigned char* cornerFlags - , dtPolyRef* cornerPolys - , const int maxCorners - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (corridor) - return corridor->findCorners(cornerVerts - , cornerFlags - , cornerPolys - , maxCorners - , navquery - , filter); - - return -1; - } - - EXPORT_API void dtpcOptimizePathVisibility(dtPathCorridor* corridor - , const float* next - , const float pathOptimizationRange - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (corridor) - corridor->optimizePathVisibility(next - , pathOptimizationRange - , navquery - , filter); - } - - EXPORT_API int dtpcOptimizePathVisibilityExt(dtPathCorridor* corridor - , const float* next - , const float pathOptimizationRange - , float* cornerVerts - , unsigned char* cornerFlags - , dtPolyRef* cornerPolys - , const int maxCorners - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (!corridor) - return -1; - - corridor->optimizePathVisibility(next - , pathOptimizationRange - , navquery - , filter); - - return corridor->findCorners(cornerVerts - , cornerFlags - , cornerPolys - , maxCorners - , navquery - , filter); - - } - - EXPORT_API bool dtpcOptimizePathTopology(dtPathCorridor* corridor - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (!corridor) - return corridor->optimizePathTopology(navquery, filter); - return false; - } - - EXPORT_API int dtpcOptimizePathTopologyExt(dtPathCorridor* corridor - , float* cornerVerts - , unsigned char* cornerFlags - , dtPolyRef* cornerPolys - , const int maxCorners - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (!corridor) - return false; - - corridor->optimizePathTopology(navquery, filter); - - return corridor->findCorners(cornerVerts - , cornerFlags - , cornerPolys - , maxCorners - , navquery - , filter); - } - - EXPORT_API bool dtpcMoveOverOffmeshConnection(dtPathCorridor* corridor - , dtPolyRef offMeshConRef - , dtPolyRef* refs - , float* startPos - , float* endPos - , rcnNavmeshPoint* resultPos - , dtNavMeshQuery* navquery) - { - if (!corridor) - return false; - - bool success = corridor->moveOverOffmeshConnection(offMeshConRef - , refs - , startPos - , endPos - , navquery); - - dtVcopy(&resultPos->point[0], corridor->getPos()); - resultPos->polyRef = corridor->getFirstPoly(); - - return success; - } - - EXPORT_API int dtpcMovePosition(dtPathCorridor* corridor - , const float* npos - , rcnNavmeshPoint* pos - , float* cornerVerts - , unsigned char* cornerFlags - , dtPolyRef* cornerPolys - , const int maxCorners - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (!corridor) - return -1; - - corridor->movePosition(npos, navquery, filter); - - if (pos) - { - dtVcopy(&pos->point[0], corridor->getPos()); - pos->polyRef = corridor->getFirstPoly(); - } - - return corridor->findCorners(cornerVerts - , cornerFlags - , cornerPolys - , maxCorners - , navquery - , filter); - } - - EXPORT_API dtPolyRef dtpcMoveTargetPosition(dtPathCorridor* corridor - , const float* npos - , rcnNavmeshPoint* pos - , float* cornerVerts - , unsigned char* cornerFlags - , dtPolyRef* cornerPolys - , const int maxCorners - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (!corridor) - return -1; - - corridor->moveTargetPosition(npos, navquery, filter); - - if (pos) - { - dtVcopy(&pos->point[0], corridor->getTarget()); - pos->polyRef = corridor->getLastPoly(); - } - - return corridor->findCorners(cornerVerts - , cornerFlags - , cornerPolys - , maxCorners - , navquery - , filter); - - } - - EXPORT_API int dtpcMove(dtPathCorridor* corridor - , const float* npos - , const float* ntarget - , rcnNavmeshPoint* pos - , rcnNavmeshPoint* target - , float* cornerVerts - , unsigned char* cornerFlags - , dtPolyRef* cornerPolys - , const int maxCorners - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (!corridor) - return 0; - - if (ntarget) - corridor->moveTargetPosition(ntarget, navquery, filter); - - if (npos) - corridor->movePosition(npos, navquery, filter); - - if (pos) - { - dtVcopy(&pos->point[0], corridor->getPos()); - pos->polyRef = corridor->getFirstPoly(); - } - - if (target) - { - dtVcopy(&target->point[0], corridor->getTarget()); - target->polyRef = corridor->getLastPoly(); - } - - return corridor->findCorners(cornerVerts - , cornerFlags - , cornerPolys - , maxCorners - , navquery - , filter); - } - - EXPORT_API int dtpcSetCorridor(dtPathCorridor* corridor - , const float* target - , const dtPolyRef* polys - , const int npolys - , rcnNavmeshPoint* resultTarget - , float* cornerVerts - , unsigned char* cornerFlags - , dtPolyRef* cornerPolys - , const int maxCorners - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (!(corridor && polys)) - return -1; - - corridor->setCorridor(target, polys, npolys); - - if (resultTarget) - { - dtVcopy(&resultTarget->point[0], corridor->getTarget()); - resultTarget->polyRef = corridor->getLastPoly(); - } - - return corridor->findCorners(cornerVerts - , cornerFlags - , cornerPolys - , maxCorners - , navquery - , filter); - } - - //EXPORT_API dtPolyRef dtpcGetPos(dtPathCorridor* corridor - // , float* pos) - //{ - //if (!corridor || !pos) - // return 0; - - //dtVcopy(pos, corridor->getPos()); - //return corridor->getFirstPoly(); - //} - - //EXPORT_API dtPolyRef dtpcGetTarget(dtPathCorridor* corridor - // , float* target) - //{ - //if (!corridor || !target) - // return 0; - - //dtVcopy(target, corridor->getTarget()); - //return corridor->getLastPoly(); - //} - - //EXPORT_API dtPolyRef dtpcGetFirstPoly(dtPathCorridor* corridor) - //{ - //if (corridor) - // return corridor->getFirstPoly(); - //return 0; - //} - - //EXPORT_API dtPolyRef dtpcGetLastPoly(dtPathCorridor* corridor) - //{ - //if (corridor) - // return corridor->getLastPoly(); - //return 0; - //} - - EXPORT_API int dtpcGetPath(dtPathCorridor* corridor - , dtPolyRef* path - , int maxPath) - { - if (!corridor || !path || maxPath < 1) - return 0; - - int count = dtMin(maxPath, corridor->getPathCount()); - - memcpy(path, corridor->getPath(), sizeof(dtPolyRef) * count); - - return count; - } - - EXPORT_API int dtpcGetPathCount(dtPathCorridor* corridor) - { - if (corridor) - return corridor->getPathCount(); - return 0; - } - - EXPORT_API bool dtpcGetData(dtPathCorridor* corridor - , rcnPathCorridorData* result) - { - if (!corridor - || !result - || corridor->getPathCount() > MAX_RCN_PATH_CORRIDOR_SIZE) - { - return false; - } - - int count = corridor->getPathCount(); - - result->pathCount = count; - dtVcopy(result->position, corridor->getPos()); - dtVcopy(result->target, corridor->getTarget()); - memcpy(&result->path[0] - , corridor->getPath() - , sizeof(dtPolyRef) * count); - - return true; - } - - EXPORT_API bool dtpcIsValid(dtPathCorridor* corridor - , const int maxLookAhead - , dtNavMeshQuery* navquery - , const dtQueryFilter* filter) - { - if (corridor) - return corridor->isValid(maxLookAhead, navquery, filter); - return false; - } -} \ No newline at end of file diff --git a/critterai/.svn/pristine/f8/f8d2acecade41459f9d387c9ef2900e4779855cd.svn-base b/critterai/.svn/pristine/f8/f8d2acecade41459f9d387c9ef2900e4779855cd.svn-base deleted file mode 100644 index 76f9ac54..00000000 --- a/critterai/.svn/pristine/f8/f8d2acecade41459f9d387c9ef2900e4779855cd.svn-base +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using System.Collections.Generic; -using org.critterai.nmgen; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal static class MeshUtil - { - public static void CombineMeshes(Queue items - , byte area - , InputGeometryCompiler compiler) - { - const int MaxTris = 65000; - - List combineInstancesPart = new List(); - byte[] areas = NMGen.CreateAreaBuffer(MaxTris, area); - - while (items.Count != 0) - { - int vertCount = 0; - - while (items.Count > 0 - && (vertCount + items.Peek().mesh.vertexCount < MaxTris)) - { - vertCount += items.Peek().mesh.vertexCount; - combineInstancesPart.Add(items.Dequeue()); - } - - Mesh meshPart = new Mesh(); - - meshPart.CombineMeshes(combineInstancesPart.ToArray(), true, true); - - compiler.AddTriangles(meshPart.vertices, meshPart.vertexCount - , meshPart.triangles, areas, meshPart.triangles.Length / 3); - - Object.DestroyImmediate(meshPart); - - combineInstancesPart.Clear(); - } - } - } -} diff --git a/critterai/.svn/pristine/f8/f8f34f9695b20c3d4534fb560208f762df500383.svn-base b/critterai/.svn/pristine/f8/f8f34f9695b20c3d4534fb560208f762df500383.svn-base deleted file mode 100644 index f9602fda..00000000 --- a/critterai/.svn/pristine/f8/f8f34f9695b20c3d4534fb560208f762df500383.svn-base +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#if NUNITY -using Vector3 = org.critterai.Vector3; -#else -using Vector3 = UnityEngine.Vector3; -#endif - -namespace org.critterai.geom -{ - /// - /// Provides various 3D polygon utility methods. - /// - /// - /// - /// Unless otherwise noted, methods expect all polygon vertices to be co-planar. - /// - /// - /// Static methods are thread safe. - /// - /// - public static class Polygon3 - { - /// - /// Determines whether a polygon is convex. - /// - /// - /// - /// Behavior is undefined if vertices are not coplanar. - /// - /// - /// This method may improperly return false if the area of the triangle formed - /// by the first three vertices of the polygon is too small to detect on both the (x, z) - /// and (x, y) planes. - /// - /// - /// - /// An array of vertices that contains a representation of polygons with an arbitrary - /// number of sides. Wrap direction does not matter. - /// - /// The index of the first vertex in the polygon. - /// The number of vertices in the polygon. - /// True if the polygon is convex. - public static bool IsConvex(Vector3[] vertices, int startVert, int vertCount) - { - if (vertCount < 3) - return false; - if (vertCount == 3) - // It is a triangle, so it must be convex. - return true; - - // At this point we know that the polygon has at least 4 sides. - - /* - * Process will be to step through the sides, 3 vertices at a time. - * As long the signed area for the triangles formed by each set of - * vertices is the same (negative or positive), then the polygon - * is convex. - * - * Using a shortcut by projecting onto the (x, z) or (x, y) plane - * for all calculations. For a proper polygon, if the 2D - * projection is convex, the 3D polygon is convex. - * - * There is one special case: A polygon that is vertical. - * I.e. 2D on the (x, z) plane. - * This is detected during the first test. - */ - - bool offset = true; // Start by projecting to the (x, z) plane. - - float initDirection = Triangle2.GetSignedAreaX2( - vertices[startVert + 0].x - , vertices[startVert + 0].z - , vertices[startVert + 1].x - , vertices[startVert + 1].z - , vertices[startVert + 2].x - , vertices[startVert + 2].z); - - if (initDirection > -2 * MathUtil.Epsilon - && initDirection < 2 * MathUtil.Epsilon) - { - // The polygon is on or very close to the vertical plane. - // Switch to projecting on the (x, y) plane. - offset = false; - - initDirection = Triangle2.GetSignedAreaX2( - vertices[startVert + 0].x - , vertices[startVert + 0].y - , vertices[startVert + 1].x - , vertices[startVert + 1].y - , vertices[startVert + 2].x - , vertices[startVert + 2].y); - - // Design note: This is meant to be a strict zero test. - if (initDirection == 0) - // Some sort of problem. Should very rarely ever get here. - return false; - } - - int length = (startVert + vertCount); - for (int iVertA = startVert + 1; iVertA < length; iVertA++) - { - int iVertB = iVertA + 1; - - if (iVertB >= length) - // Wrap it back to the start. - iVertB = startVert; - - int iVertC = iVertB + 1; - - if (iVertC >= length) - // Wrap it back to the start. - iVertC = startVert; - - float direction = Triangle2.GetSignedAreaX2( - vertices[iVertA].x - , offset ? vertices[iVertA].z : vertices[iVertA].y - , vertices[iVertB].x - , offset ? vertices[iVertB].z : vertices[iVertB].y - , vertices[iVertC].x - , offset ? vertices[iVertC].z : vertices[iVertC].y); - - if (!(initDirection < 0 && direction < 0) && !(initDirection > 0 && direction > 0)) - // The sign of the current direction is not the same as the sign of the - // initial direction. Can't be convex. - return false; - } - - return true; - } - - /// - /// Returns the - /// centroid of a convex polygon. - /// - /// - /// - /// Behavior is undefined if the polygon is not convex. - /// - /// - /// Behavior is undefined if the vector being overwritten in the out array is a vertex - /// in the polygon. (Can only happen if the vertices and result arrays are the same object.) - /// - /// - /// - /// An array of vertices that contains a representation of a polygon with an arbitrary - /// number of sides. Wrap direction does not matter. - /// - /// The index of the first vertex in the polygon. - /// The number of vertices in the polygon. - /// The array to store the result in. - /// The index in the result array to store the result. - /// A reference to the result argument. - public static Vector3[] GetCentroid(Vector3[] vertices - , int startVert - , int vertCount - , Vector3[] result - , int resultVert) - { - // Reference: - // http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - result[resultVert] = new Vector3(0, 0, 0); - int length = (startVert+vertCount); - - for (int i = startVert; i < length; i++) - { - result[resultVert] += vertices[i]; - } - - result[resultVert].x /= vertCount; - result[resultVert].y /= vertCount; - result[resultVert].z /= vertCount; - - return result; - } - - /// - /// Returns the - /// centroid of a convex polygon. - /// - /// - /// - /// Behavior is undefined if the polygon is not convex. - /// - /// - /// - /// An array of vertices that contains a representation of a polygon with an arbitrary - /// number of sides. Wrap direction does not matter. - /// - /// The index of the first vertex in the polygon. - /// The number of vertices in the polygon. - /// The centroid of the polygon. - public static Vector3 GetCentroid(Vector3[] vertices, int startVert, int vertCount) - { - // Reference: - // http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - - Vector3 result = new Vector3(); - int vertLength = (startVert + vertCount); - - for (int i = startVert; i < vertLength; i++) - { - result += vertices[i]; - } - - result.x /= vertCount; - result.y /= vertCount; - result.z /= vertCount; - - return result; - } - - /// - /// Returns the - /// centroid of a convex polygon. - /// - /// - /// - /// Behavior is undefined if the polygon is not convex. - /// - /// - /// - /// An list of vertices that represent a polygon with an arbitrary number of sides. Wrap - /// direction does not matter. - /// - /// The centroid of the polygon. - public static Vector3 GetCentroid(params Vector3[] vertices) - { - // Reference: - // http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - Vector3 result = new Vector3(); - - int vertCount = 0; - for (int i = 0; i < vertices.Length; i++) - { - result += vertices[i]; - vertCount++; - } - - result.x /= vertCount; - result.y /= vertCount; - result.z /= vertCount; - - return result; - } - } -} diff --git a/critterai/.svn/pristine/f9/f994cdeb01dd3b7ac986333fa67b6a7d74097a9d.svn-base b/critterai/.svn/pristine/f9/f994cdeb01dd3b7ac986333fa67b6a7d74097a9d.svn-base deleted file mode 100644 index 8bdaf869..00000000 --- a/critterai/.svn/pristine/f9/f994cdeb01dd3b7ac986333fa67b6a7d74097a9d.svn-base +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2010-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; - -namespace org.critterai -{ - /// - /// Provides various CAI utility constants and methods. - /// - public static class CAIUtil - { - /// - /// Converts ticks to seconds. (seconts = ticks * TicksToSec) - /// - public const float TicksToSec = 1E-7f; - - /// - /// Converts ticks to milliseconds. (ms = ticks * TicksToMS) - /// - public const float TicksToMS = 1E-4f; - - /// - /// Converts seconds to ticks. (tick = seconds * SecToTicks) - /// - public const int SecToTicks = 10000000; - - /// - /// Converts milliseconds to ticks. (ticks = ms * MSToTicks) - /// - public const int MSToTicks = 10000; - - /// - /// Gets the number of milliseconds from the start tick to now. - /// - /// The start time in ticks. - /// The number of milliseconds since the start tick. - public static int GetNowDeltaMS(long start) - { - return (int)((DateTime.Now.Ticks - start) * TicksToMS); - } - - /// - /// Gets the number of seconds from the start tick to now. - /// - /// The start time in ticks. - /// The number of seconds since the start tick. - public static int GetNowDeltaSec(long start) - { - return (int)((DateTime.Now.Ticks - start) * TicksToSec); - } - } -} diff --git a/critterai/.svn/pristine/f9/f99f4f7c7b004bff7c138d9a8930be9693f09feb.svn-base b/critterai/.svn/pristine/f9/f99f4f7c7b004bff7c138d9a8930be9693f09feb.svn-base deleted file mode 100644 index b344d74a..00000000 Binary files a/critterai/.svn/pristine/f9/f99f4f7c7b004bff7c138d9a8930be9693f09feb.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/f9/f9c9b0ccf14a11c2c47d4ff3a3209436dba1f147.svn-base b/critterai/.svn/pristine/f9/f9c9b0ccf14a11c2c47d4ff3a3209436dba1f147.svn-base deleted file mode 100644 index c8672bf8..00000000 Binary files a/critterai/.svn/pristine/f9/f9c9b0ccf14a11c2c47d4ff3a3209436dba1f147.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/fa/fa0ac5e0d8ab9d2e1f629611dc00e1348cfad0e9.svn-base b/critterai/.svn/pristine/fa/fa0ac5e0d8ab9d2e1f629611dc00e1348cfad0e9.svn-base deleted file mode 100644 index 27665d8d..00000000 --- a/critterai/.svn/pristine/fa/fa0ac5e0d8ab9d2e1f629611dc00e1348cfad0e9.svn-base +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2011-2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai -{ - /// - /// Provides array related utility methods. - /// - /// - /// - /// Static methods are thread safe. - /// - /// - public static class ArrayUtil - { - /// - /// Compresses an array by removing all null values. - /// - /// - /// - /// Only valid for use with arrays of reference types. - /// - /// - /// No guarentees are made concerning the order of the items in the returned array. - /// - /// - /// The type of the array. - /// The array. - /// - /// A reference to original array if it contained no nulls, or a new array with all nulls - /// removed. - /// - public static T[] Compress(T[] items) - { - if (items == null) - return null; - - if (items.Length == 0) - return items; - - int count = 0; - - foreach (T item in items) - { - count += (item == null) ? 0 : 1; - } - - if (count == items.Length) - return items; - - T[] result = new T[count]; - - if (count == 0) - return result; - - count = 0; - foreach (T item in items) - { - if (item != null) - result[count++] = item; - } - - return result; - } - } -} diff --git a/critterai/.svn/pristine/fa/fa441d7aa2c185f250b6002f2a808e84a3de8f3e.svn-base b/critterai/.svn/pristine/fa/fa441d7aa2c185f250b6002f2a808e84a3de8f3e.svn-base deleted file mode 100644 index c6510151..00000000 Binary files a/critterai/.svn/pristine/fa/fa441d7aa2c185f250b6002f2a808e84a3de8f3e.svn-base and /dev/null differ diff --git a/critterai/.svn/pristine/fa/faff25580e5d009fcc75370640446c9f6cdae2ef.svn-base b/critterai/.svn/pristine/fa/faff25580e5d009fcc75370640446c9f6cdae2ef.svn-base deleted file mode 100644 index d2bb7c98..00000000 --- a/critterai/.svn/pristine/fa/faff25580e5d009fcc75370640446c9f6cdae2ef.svn-base +++ /dev/null @@ -1,387 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#define _USE_MATH_DEFINES -#include -#include -#include "Recast.h" -#include "RecastAlloc.h" -#include "RecastAssert.h" - -inline bool overlapBounds(const float* amin, const float* amax, const float* bmin, const float* bmax) -{ - bool overlap = true; - overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; - overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; - overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; - return overlap; -} - -inline bool overlapInterval(unsigned short amin, unsigned short amax, - unsigned short bmin, unsigned short bmax) -{ - if (amax < bmin) return false; - if (amin > bmax) return false; - return true; -} - - -static rcSpan* allocSpan(rcHeightfield& hf) -{ - // If running out of memory, allocate new page and update the freelist. - if (!hf.freelist || !hf.freelist->next) - { - // Create new page. - // Allocate memory for the new pool. - rcSpanPool* pool = (rcSpanPool*)rcAlloc(sizeof(rcSpanPool), RC_ALLOC_PERM); - if (!pool) return 0; - pool->next = 0; - // Add the pool into the list of pools. - pool->next = hf.pools; - hf.pools = pool; - // Add new items to the free list. - rcSpan* freelist = hf.freelist; - rcSpan* head = &pool->items[0]; - rcSpan* it = &pool->items[RC_SPANS_PER_POOL]; - do - { - --it; - it->next = freelist; - freelist = it; - } - while (it != head); - hf.freelist = it; - } - - // Pop item from in front of the free list. - rcSpan* it = hf.freelist; - hf.freelist = hf.freelist->next; - return it; -} - -static void freeSpan(rcHeightfield& hf, rcSpan* ptr) -{ - if (!ptr) return; - // Add the node in front of the free list. - ptr->next = hf.freelist; - hf.freelist = ptr; -} - -static void addSpan(rcHeightfield& hf, const int x, const int y, - const unsigned short smin, const unsigned short smax, - const unsigned char area, const int flagMergeThr) -{ - - int idx = x + y*hf.width; - - rcSpan* s = allocSpan(hf); - s->smin = smin; - s->smax = smax; - s->area = area; - s->next = 0; - - // Empty cell, add he first span. - if (!hf.spans[idx]) - { - hf.spans[idx] = s; - return; - } - rcSpan* prev = 0; - rcSpan* cur = hf.spans[idx]; - - // Insert and merge spans. - while (cur) - { - if (cur->smin > s->smax) - { - // Current span is further than the new span, break. - break; - } - else if (cur->smax < s->smin) - { - // Current span is before the new span advance. - prev = cur; - cur = cur->next; - } - else - { - // Merge spans. - if (cur->smin < s->smin) - s->smin = cur->smin; - if (cur->smax > s->smax) - s->smax = cur->smax; - - // Merge flags. - if (rcAbs((int)s->smax - (int)cur->smax) <= flagMergeThr) - s->area = rcMax(s->area, cur->area); - - // Remove current span. - rcSpan* next = cur->next; - freeSpan(hf, cur); - if (prev) - prev->next = next; - else - hf.spans[idx] = next; - cur = next; - } - } - - // Insert new span. - if (prev) - { - s->next = prev->next; - prev->next = s; - } - else - { - s->next = hf.spans[idx]; - hf.spans[idx] = s; - } -} - -/// @par -/// -/// The span addition can be set to favor flags. If the span is merged to -/// another span and the new @p smax is within @p flagMergeThr units -/// from the existing span, the span flags are merged. -/// -/// @see rcHeightfield, rcSpan. -void rcAddSpan(rcContext* /*ctx*/, rcHeightfield& hf, const int x, const int y, - const unsigned short smin, const unsigned short smax, - const unsigned char area, const int flagMergeThr) -{ -// rcAssert(ctx); - addSpan(hf, x,y, smin, smax, area, flagMergeThr); -} - -static int clipPoly(const float* in, int n, float* out, float pnx, float pnz, float pd) -{ - float d[12]; - for (int i = 0; i < n; ++i) - d[i] = pnx*in[i*3+0] + pnz*in[i*3+2] + pd; - - int m = 0; - for (int i = 0, j = n-1; i < n; j=i, ++i) - { - bool ina = d[j] >= 0; - bool inb = d[i] >= 0; - if (ina != inb) - { - float s = d[j] / (d[j] - d[i]); - out[m*3+0] = in[j*3+0] + (in[i*3+0] - in[j*3+0])*s; - out[m*3+1] = in[j*3+1] + (in[i*3+1] - in[j*3+1])*s; - out[m*3+2] = in[j*3+2] + (in[i*3+2] - in[j*3+2])*s; - m++; - } - if (inb) - { - out[m*3+0] = in[i*3+0]; - out[m*3+1] = in[i*3+1]; - out[m*3+2] = in[i*3+2]; - m++; - } - } - return m; -} - -static void rasterizeTri(const float* v0, const float* v1, const float* v2, - const unsigned char area, rcHeightfield& hf, - const float* bmin, const float* bmax, - const float cs, const float ics, const float ich, - const int flagMergeThr) -{ - const int w = hf.width; - const int h = hf.height; - float tmin[3], tmax[3]; - const float by = bmax[1] - bmin[1]; - - // Calculate the bounding box of the triangle. - rcVcopy(tmin, v0); - rcVcopy(tmax, v0); - rcVmin(tmin, v1); - rcVmin(tmin, v2); - rcVmax(tmax, v1); - rcVmax(tmax, v2); - - // If the triangle does not touch the bbox of the heightfield, skip the triagle. - if (!overlapBounds(bmin, bmax, tmin, tmax)) - return; - - // Calculate the footpring of the triangle on the grid. - int x0 = (int)((tmin[0] - bmin[0])*ics); - int y0 = (int)((tmin[2] - bmin[2])*ics); - int x1 = (int)((tmax[0] - bmin[0])*ics); - int y1 = (int)((tmax[2] - bmin[2])*ics); - x0 = rcClamp(x0, 0, w-1); - y0 = rcClamp(y0, 0, h-1); - x1 = rcClamp(x1, 0, w-1); - y1 = rcClamp(y1, 0, h-1); - - // Clip the triangle into all grid cells it touches. - float in[7*3], out[7*3], inrow[7*3]; - - for (int y = y0; y <= y1; ++y) - { - // Clip polygon to row. - rcVcopy(&in[0], v0); - rcVcopy(&in[1*3], v1); - rcVcopy(&in[2*3], v2); - int nvrow = 3; - const float cz = bmin[2] + y*cs; - nvrow = clipPoly(in, nvrow, out, 0, 1, -cz); - if (nvrow < 3) continue; - nvrow = clipPoly(out, nvrow, inrow, 0, -1, cz+cs); - if (nvrow < 3) continue; - - for (int x = x0; x <= x1; ++x) - { - // Clip polygon to column. - int nv = nvrow; - const float cx = bmin[0] + x*cs; - nv = clipPoly(inrow, nv, out, 1, 0, -cx); - if (nv < 3) continue; - nv = clipPoly(out, nv, in, -1, 0, cx+cs); - if (nv < 3) continue; - - // Calculate min and max of the span. - float smin = in[1], smax = in[1]; - for (int i = 1; i < nv; ++i) - { - smin = rcMin(smin, in[i*3+1]); - smax = rcMax(smax, in[i*3+1]); - } - smin -= bmin[1]; - smax -= bmin[1]; - // Skip the span if it is outside the heightfield bbox - if (smax < 0.0f) continue; - if (smin > by) continue; - // Clamp the span to the heightfield bbox. - if (smin < 0.0f) smin = 0; - if (smax > by) smax = by; - - // Snap the span to the heightfield height grid. - unsigned short ismin = (unsigned short)rcClamp((int)floorf(smin * ich), 0, RC_SPAN_MAX_HEIGHT); - unsigned short ismax = (unsigned short)rcClamp((int)ceilf(smax * ich), (int)ismin+1, RC_SPAN_MAX_HEIGHT); - - addSpan(hf, x, y, ismin, ismax, area, flagMergeThr); - } - } -} - -/// @par -/// -/// No spans will be added if the triangle does not overlap the heightfield grid. -/// -/// @see rcHeightfield -void rcRasterizeTriangle(rcContext* ctx, const float* v0, const float* v1, const float* v2, - const unsigned char area, rcHeightfield& solid, - const int flagMergeThr) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); - - const float ics = 1.0f/solid.cs; - const float ich = 1.0f/solid.ch; - rasterizeTri(v0, v1, v2, area, solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); -} - -/// @par -/// -/// Spans will only be added for triangles that overlap the heightfield grid. -/// -/// @see rcHeightfield -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, - const int* tris, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); - - const float ics = 1.0f/solid.cs; - const float ich = 1.0f/solid.ch; - // Rasterize triangles. - for (int i = 0; i < nt; ++i) - { - const float* v0 = &verts[tris[i*3+0]*3]; - const float* v1 = &verts[tris[i*3+1]*3]; - const float* v2 = &verts[tris[i*3+2]*3]; - // Rasterize. - rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); - } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); -} - -/// @par -/// -/// Spans will only be added for triangles that overlap the heightfield grid. -/// -/// @see rcHeightfield -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const int /*nv*/, - const unsigned short* tris, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); - - const float ics = 1.0f/solid.cs; - const float ich = 1.0f/solid.ch; - // Rasterize triangles. - for (int i = 0; i < nt; ++i) - { - const float* v0 = &verts[tris[i*3+0]*3]; - const float* v1 = &verts[tris[i*3+1]*3]; - const float* v2 = &verts[tris[i*3+2]*3]; - // Rasterize. - rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); - } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); -} - -/// @par -/// -/// Spans will only be added for triangles that overlap the heightfield grid. -/// -/// @see rcHeightfield -void rcRasterizeTriangles(rcContext* ctx, const float* verts, const unsigned char* areas, const int nt, - rcHeightfield& solid, const int flagMergeThr) -{ - rcAssert(ctx); - - ctx->startTimer(RC_TIMER_RASTERIZE_TRIANGLES); - - const float ics = 1.0f/solid.cs; - const float ich = 1.0f/solid.ch; - // Rasterize triangles. - for (int i = 0; i < nt; ++i) - { - const float* v0 = &verts[(i*3+0)*3]; - const float* v1 = &verts[(i*3+1)*3]; - const float* v2 = &verts[(i*3+2)*3]; - // Rasterize. - rasterizeTri(v0, v1, v2, areas[i], solid, solid.bmin, solid.bmax, solid.cs, ics, ich, flagMergeThr); - } - - ctx->stopTimer(RC_TIMER_RASTERIZE_TRIANGLES); -} diff --git a/critterai/.svn/pristine/fa/faff802ff6e4f5f36227913396accab3031e26da.svn-base b/critterai/.svn/pristine/fa/faff802ff6e4f5f36227913396accab3031e26da.svn-base deleted file mode 100644 index e86ea714..00000000 --- a/critterai/.svn/pristine/fa/faff802ff6e4f5f36227913396accab3031e26da.svn-base +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEditor; -using UnityEngine; -using org.critterai.nav; -using org.critterai.u3d.editor; - -namespace org.critterai.nmbuild.u3d.editor -{ - internal sealed class SingleTileBuildControl - : BuilderControl - { - private static GUIStyle mBoxStyle; - - private float mProgress = 0; - private double mLastTime = 0; - - public override bool Enter(ControlContext context, DebugViewContext debug) - { - if (base.Enter(context, debug)) - { - NavmeshBuild build = context.Build; - - if (build.TileSetDefinition != null || build.Config.TileSize > 0) - { - Debug.LogError(typeof(SingleTileBuildControl) + ": The build is tiled.", build); - return false; - } - - return true; - } - return false; - } - - protected override void OnGUIMain() - { - if (mBoxStyle == null) - { - mBoxStyle = new GUIStyle(EditorUtil.HelpStyle); - mBoxStyle.alignment = TextAnchor.MiddleCenter; - } - - TileBuildState bstate = Context.Build.BuildData.GetState(0, 0); - - switch (bstate) - { - case TileBuildState.NotBuilt: - - ShowStatus("Ready to build."); - break; - - case TileBuildState.Empty: - - ShowStatus("Build did not produce any results."); - break; - - case TileBuildState.Queued: - - ShowStatus("Build is queued for background processing."); - break; - - case TileBuildState.Error: - - ShowStatus("Build failed on error!"); - break; - - case TileBuildState.Baked: - - ShowStatus("Bake completed."); - break; - - case TileBuildState.Built: - - ShowStatus("Ready to bake."); - break; - - case TileBuildState.InProgress: - - ShowStatus("Build in progress..."); - - Rect area = Context.MainArea; - - area = new Rect(area.x + area.width * 0.25f - , area.y + area.height * 0.66f - , area.width * 0.50f - , 20); - - double now = EditorApplication.timeSinceStartup; - - // Progress will fill up once every 10 seconds. - // Just something for the user to look at. - mProgress += (float)(now - mLastTime) * 0.05f; - mProgress = (mProgress > 1 ? 0 : mProgress); - - mLastTime = now; - - EditorGUI.ProgressBar(area , mProgress , ""); - - break; - } - - GUILayout.Space(ControlUtil.MarginSize); - OnGUIMainStandard(); - } - - private void ShowStatus(string message) - { - GUI.Box(Context.MainArea, message, mBoxStyle); - } - - protected override void OnGUIButtons() - { - DebugContext.SetViews(ViewOption.Mesh); - - NavmeshBuild build = Context.Build; - - if (!build) - // Build deleted. - return; - - TileBuildData tdata = Context.Build.BuildData; - TileBuildState bstate = tdata.GetState(0, 0); - - bool canBake = - (bstate == TileBuildState.Built || bstate == TileBuildState.Baked); - - bool isBuilding = (Context.TaskCount > 0); - - ControlUtil.BeginButtonArea(Context.ButtonArea); - - EditorGUIUtility.LookLikeControls(75); - - bool guiEnabled = GUI.enabled; - - GUI.enabled = !isBuilding; - - GUIStyle style = (canBake || isBuilding) - ? GUI.skin.button : ControlUtil.HighlightedButton; - - if (GUILayout.Button("Build", style)) - { - mProgress = 0; - - mLastTime = EditorApplication.timeSinceStartup; - - if (!Context.QueueTask(0, 0, BuildTaskProcessor.LowPriority, Logger)) - Logger.PostError("Build task failed.", Context.Build); - } - - GUI.enabled = !isBuilding && canBake; - - style = GUI.enabled - ? ControlUtil.HighlightedButton : GUI.skin.button; - - if (GUILayout.Button("Bake", style)) - HandleBake(); - - GUILayout.Space(ControlUtil.MarginSize); - - GUI.enabled = isBuilding; - - if (GUILayout.Button("Abort Build")) - Context.AbortAllReqests("User requested."); - - GUI.enabled = guiEnabled; - - if (OnGUIStandardButtons()) - { - // Special case. Build was discarded. - ControlUtil.EndButtonArea(); - return; - } - - ControlUtil.OnGUIStandardButtons(Context, DebugContext, true); - - ControlUtil.EndButtonArea(); - } - - private void HandleBake() - { - NavmeshBuild build = Context.Build; - - NavmeshTileData[] tiles = new NavmeshTileData[1] - { - build.BuildData.GetTileData(0, 0) - }; - - NavmeshParams nconfig = NavUtil.DeriveConfig(tiles[0]); - - NavStatus status = build.BuildTarget.Load(nconfig, tiles, NMBEditorUtil.GetConfig(build)); - - if ((status & NavStatus.Failure) == 0) - { - EditorUtility.SetDirty((Object)build.BuildTarget); - // build.BuildData.SetAsBaked(); - build.BuildData.Reset(0, 0); // Don't need to keep the data. - } - else - Logger.PostError("Bake to target: Target reported failure.", (Object)build.BuildTarget); - } - } -} diff --git a/critterai/.svn/pristine/fd/fd0c1694c7472cbf6162db6a90ee6900649cf4a6.svn-base b/critterai/.svn/pristine/fd/fd0c1694c7472cbf6162db6a90ee6900649cf4a6.svn-base deleted file mode 100644 index 5ac03744..00000000 --- a/critterai/.svn/pristine/fd/fd0c1694c7472cbf6162db6a90ee6900649cf4a6.svn-base +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -/** - * Specifies the relationship between two lines. - */ -public enum LineRelType -{ - - /** - * Lines are parallel and overlap each other. (Share all points.) - */ - COLLINEAR, - - /** - * Lines intersect, but their segments do not. - */ - LINES_INTERSECT, - - /** - * Line segments intersect each other. - */ - SEGMENTS_INTERSECT, - - /** - * Line segment B is crossed by line A. - */ - ALINE_CROSSES_BSEG, - - /** - * Line segment A is crossed by line B. - */ - BLINE_CROSSES_ASEG, - - /** - * Lines are parallel and do NOT overlap each other. (Share no points.) - */ - PARALLEL, - - /** - * Lines do not intersect, but are not parallel. - * (Share no points. Only applicable to 3-dimensional lines.) - */ - SKEW -} diff --git a/critterai/.svn/pristine/fe/fe58af501c58dd8ab67394ce852339d398df12d9.svn-base b/critterai/.svn/pristine/fe/fe58af501c58dd8ab67394ce852339d398df12d9.svn-base deleted file mode 100644 index 1a7b2ab3..00000000 --- a/critterai/.svn/pristine/fe/fe58af501c58dd8ab67394ce852339d398df12d9.svn-base +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2011 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using System; -using System.Collections.Generic; -using System.Text; -using System.Runtime.InteropServices; - -namespace org.critterai.nav -{ - /// - /// Navigation mesh links. (Undocumented.) - /// - [StructLayout(LayoutKind.Sequential)] - public struct NavmeshLink - { - /// - /// The polygon reference of the neighbor. - /// - public uint polyRef; - - /// - /// The index of the next link. - /// - public uint next; - - /// - /// The index of the polygon edge that owns this link. - /// - public byte edge; - - /// - /// If a boundary link, defines which side the link is. - /// - public byte side; - - /// - /// If a boundary link, defines the sub-edge minimum. - /// - public byte boundsMin; - - /// - /// If a boundary link, defines the sub-edge maximum. - /// - public byte boundsMax; - } -} diff --git a/critterai/.svn/pristine/fe/fe5aeb785944b2f9fc929e959ac7ae4d33e236bb.svn-base b/critterai/.svn/pristine/fe/fe5aeb785944b2f9fc929e959ac7ae4d33e236bb.svn-base deleted file mode 100644 index 38c6014e..00000000 --- a/critterai/.svn/pristine/fe/fe5aeb785944b2f9fc929e959ac7ae4d33e236bb.svn-base +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -namespace org.critterai.nmbuild.u3d.editor -{ - internal interface IBuildControl - { - bool IsActive { get; } - bool Enter(ControlContext context, DebugViewContext debug); - void Exit(); - void Update(); - void OnGUI(); - } -} diff --git a/critterai/.svn/pristine/fe/fee1bf930c3568aa34eac67bba8beb5ca7373910.svn-base b/critterai/.svn/pristine/fe/fee1bf930c3568aa34eac67bba8beb5ca7373910.svn-base deleted file mode 100644 index 1c9ef5a1..00000000 --- a/critterai/.svn/pristine/fe/fee1bf930c3568aa34eac67bba8beb5ca7373910.svn-base +++ /dev/null @@ -1,164 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-util", "util\cai-util.csproj", "{C4B32B85-13F0-42B8-AC89-770BEFEAF022}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cai-nmgen-rcn", "nmgen-rcn\cai-nmgen-rcn.vcproj", "{B783B817-8746-4D54-A6CC-664C0A73186F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nmgen", "nmgen\cai-nmgen.csproj", "{9DFC1FE0-6469-4A04-AB13-9EAC59087802}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nav", "nav\cai-nav.csproj", "{42218E47-156D-46FF-84E0-119D47B0E4EB}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cai-nav-rcn", "nav-rcn\cai-nav-rcn.vcproj", "{319D361B-147F-45AC-854E-50C06FCA3393}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nmbuild", "nmbuild\cai-nmbuild.csproj", "{08B1606A-B8CD-4725-AF68-A9CC8CEAE336}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-util-u3d", "util-u3d\cai-util-u3d.csproj", "{AF812AB8-633B-4E23-ABA7-6D02082FB2EE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nmbuild-u3d-editor", "nmbuild-u3d-editor\cai-nmbuild-u3d-editor.csproj", "{8823F2CF-1139-41BF-BD47-A456B7FEE336}" - ProjectSection(ProjectDependencies) = postProject - {8093F287-EA45-46AB-AF58-710DA654392E} = {8093F287-EA45-46AB-AF58-710DA654392E} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nav-u3d", "nav-u3d\cai-nav-u3d.csproj", "{D2154397-4098-4170-BBB0-58714D84E4C8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nav-u3d-editor", "nav-u3d-editor\cai-nav-u3d-editor.csproj", "{8093F287-EA45-46AB-AF58-710DA654392E}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nmbuild-extras-u3d", "nmbuild-extras-u3d\cai-nmbuild-extras-u3d.csproj", "{2706B2D3-0F06-4B9B-867C-3B2641B18EA8}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-nmbuild-extras-u3d-editor", "nmbuild-extras-u3d-editor\cai-nmbuild-extras-u3d-editor.csproj", "{B588A21A-1C12-4B20-83CE-D84F387FEEA1}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "cai-util-u3d-editor", "util-u3d-editor\cai-util-u3d-editor.csproj", "{1FF01BFD-2593-406A-959E-D4D84CEB662C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 - Release|Any CPU = Release|Any CPU - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Debug|Win32.ActiveCfg = Debug|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {C4B32B85-13F0-42B8-AC89-770BEFEAF022}.Release|Win32.ActiveCfg = Release|Any CPU - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Win32.ActiveCfg = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Debug|Win32.Build.0 = Debug|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Any CPU.ActiveCfg = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Mixed Platforms.Build.0 = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Win32.ActiveCfg = Release|Win32 - {B783B817-8746-4D54-A6CC-664C0A73186F}.Release|Win32.Build.0 = Release|Win32 - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Debug|Win32.ActiveCfg = Debug|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {9DFC1FE0-6469-4A04-AB13-9EAC59087802}.Release|Win32.ActiveCfg = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Debug|Win32.ActiveCfg = Debug|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {42218E47-156D-46FF-84E0-119D47B0E4EB}.Release|Win32.ActiveCfg = Release|Any CPU - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Any CPU.ActiveCfg = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Win32.ActiveCfg = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Debug|Win32.Build.0 = Debug|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Any CPU.ActiveCfg = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Mixed Platforms.Build.0 = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Win32.ActiveCfg = Release|Win32 - {319D361B-147F-45AC-854E-50C06FCA3393}.Release|Win32.Build.0 = Release|Win32 - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Any CPU.Build.0 = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Debug|Win32.ActiveCfg = Debug|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Any CPU.ActiveCfg = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Any CPU.Build.0 = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {08B1606A-B8CD-4725-AF68-A9CC8CEAE336}.Release|Win32.ActiveCfg = Release|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Debug|Win32.ActiveCfg = Debug|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {AF812AB8-633B-4E23-ABA7-6D02082FB2EE}.Release|Win32.ActiveCfg = Release|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Debug|Win32.ActiveCfg = Debug|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {8823F2CF-1139-41BF-BD47-A456B7FEE336}.Release|Win32.ActiveCfg = Release|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Debug|Win32.ActiveCfg = Debug|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Release|Any CPU.Build.0 = Release|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {D2154397-4098-4170-BBB0-58714D84E4C8}.Release|Win32.ActiveCfg = Release|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Debug|Win32.ActiveCfg = Debug|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {8093F287-EA45-46AB-AF58-710DA654392E}.Release|Win32.ActiveCfg = Release|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Debug|Win32.ActiveCfg = Debug|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Release|Any CPU.Build.0 = Release|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {2706B2D3-0F06-4B9B-867C-3B2641B18EA8}.Release|Win32.ActiveCfg = Release|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Debug|Win32.ActiveCfg = Debug|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Release|Any CPU.Build.0 = Release|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {B588A21A-1C12-4B20-83CE-D84F387FEEA1}.Release|Win32.ActiveCfg = Release|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Debug|Win32.ActiveCfg = Debug|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Release|Any CPU.Build.0 = Release|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {1FF01BFD-2593-406A-959E-D4D84CEB662C}.Release|Win32.ActiveCfg = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/critterai/.svn/wc.db b/critterai/.svn/wc.db deleted file mode 100644 index a309bb85..00000000 Binary files a/critterai/.svn/wc.db and /dev/null differ diff --git a/critterai/README.TXT b/critterai/README.TXT deleted file mode 100644 index f2eb365f..00000000 --- a/critterai/README.TXT +++ /dev/null @@ -1,57 +0,0 @@ ->> Directory Layout <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -build - - Contains Visual Studio projects and build related source files for active - projects. - -doc - - Documentation project and source files. - -legacy - - Older projects that are no longer being actively worked on. - -src - - Source for active projects. - - The source directory layout is a bit odd. Most C# source is located - under /src/main/Assets/CAI. This layout mimics the layout within - a Unity project. It is structured in this way to support easy source - deployment to non-Windows Unity projects which can't use the pre-compiled - libraries. - ->> .NET Notes <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -No automatic builds or packaging. -Sandcastle for documentation build. - -DOCUMENTATION BUILD NOTES - -The following tools are required to build the API documentation: - -Sandcastle: http://sandcastle.codeplex.com/ -Sandcastle Help File Builder: http://shfb.codeplex.com/ - -Sandcastle Styles Patch - -http://sandcastlestyles.codeplex.com/ - Home Page -http://sandcastlestyles.codeplex.com/releases/view/47767 - Patch Used - ->> Unity Notes <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - -Libraries and namespaces containing 'u3d' depend on Unity Pro -(http://unity3d.com/). The free version of unity is not supported. - -The Visual Studio projects were created on Windows 64-bit, so the Unity DLL -reference will be broken on 32-bit Windows. - -For Unity 3.x, the normal location of the DLL for both operating systems is -as follows: - -Windows 32-bit: C:\Program Files\Unity\Editor\Data\Managed -Windows 64-bit: C:\Program Files (x86)\Unity\Editor\Data\Managed\ - - diff --git a/critterai/build/assemblyInfo/cai-nav-u3d-editor.cs b/critterai/build/assemblyInfo/cai-nav-u3d-editor.cs deleted file mode 100644 index 425ed7d3..00000000 Binary files a/critterai/build/assemblyInfo/cai-nav-u3d-editor.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-nav-u3d.cs b/critterai/build/assemblyInfo/cai-nav-u3d.cs deleted file mode 100644 index 31c86416..00000000 Binary files a/critterai/build/assemblyInfo/cai-nav-u3d.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-nav.cs b/critterai/build/assemblyInfo/cai-nav.cs deleted file mode 100644 index f392cd72..00000000 Binary files a/critterai/build/assemblyInfo/cai-nav.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-nmbuild-extras-u3d-editor.cs b/critterai/build/assemblyInfo/cai-nmbuild-extras-u3d-editor.cs deleted file mode 100644 index 1dd7d944..00000000 Binary files a/critterai/build/assemblyInfo/cai-nmbuild-extras-u3d-editor.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-nmbuild-extras-u3d.cs b/critterai/build/assemblyInfo/cai-nmbuild-extras-u3d.cs deleted file mode 100644 index b39694fe..00000000 Binary files a/critterai/build/assemblyInfo/cai-nmbuild-extras-u3d.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-nmbuild-u3d-editor.cs b/critterai/build/assemblyInfo/cai-nmbuild-u3d-editor.cs deleted file mode 100644 index 2bb3c814..00000000 Binary files a/critterai/build/assemblyInfo/cai-nmbuild-u3d-editor.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-nmbuild.cs b/critterai/build/assemblyInfo/cai-nmbuild.cs deleted file mode 100644 index bf411380..00000000 Binary files a/critterai/build/assemblyInfo/cai-nmbuild.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-nmgen.cs b/critterai/build/assemblyInfo/cai-nmgen.cs deleted file mode 100644 index 34b1ea25..00000000 Binary files a/critterai/build/assemblyInfo/cai-nmgen.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-util-u3d-editor.cs b/critterai/build/assemblyInfo/cai-util-u3d-editor.cs deleted file mode 100644 index 3d8f11a4..00000000 Binary files a/critterai/build/assemblyInfo/cai-util-u3d-editor.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-util-u3d.cs b/critterai/build/assemblyInfo/cai-util-u3d.cs deleted file mode 100644 index 1232a9ea..00000000 Binary files a/critterai/build/assemblyInfo/cai-util-u3d.cs and /dev/null differ diff --git a/critterai/build/assemblyInfo/cai-util.cs b/critterai/build/assemblyInfo/cai-util.cs deleted file mode 100644 index 5e895059..00000000 Binary files a/critterai/build/assemblyInfo/cai-util.cs and /dev/null differ diff --git a/critterai/build/dotNet/nav-rcn/cai-nav-rcn.vcproj b/critterai/build/dotNet/nav-rcn/cai-nav-rcn.vcproj deleted file mode 100644 index 034e1814..00000000 --- a/critterai/build/dotNet/nav-rcn/cai-nav-rcn.vcproj +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/critterai/build/dotNet/nmgen-rcn/cai-nmgen-rcn.vcproj b/critterai/build/dotNet/nmgen-rcn/cai-nmgen-rcn.vcproj deleted file mode 100644 index 942e0512..00000000 --- a/critterai/build/dotNet/nmgen-rcn/cai-nmgen-rcn.vcproj +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/critterai/build/misc/LCOPY.TXT b/critterai/build/misc/LCOPY.TXT deleted file mode 100644 index aca8c3f3..00000000 --- a/critterai/build/misc/LCOPY.TXT +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010-2011 Stephen A. Pratt - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file diff --git a/critterai/build/misc/RCOPY.TXT b/critterai/build/misc/RCOPY.TXT deleted file mode 100644 index 98819dad..00000000 --- a/critterai/build/misc/RCOPY.TXT +++ /dev/null @@ -1,5 +0,0 @@ -This distribution contians libraries and documentation for a CritterAI project. - -CritterAI Home: http://www.critterai.org/ -CritterAI Code: http://code.google.com/p/critterai/ -License: http://www.critterai.org/cailic diff --git a/critterai/build/unity/nav-rcn/cai-nav-rcn.vcproj b/critterai/build/unity/nav-rcn/cai-nav-rcn.vcproj deleted file mode 100644 index 034e1814..00000000 --- a/critterai/build/unity/nav-rcn/cai-nav-rcn.vcproj +++ /dev/null @@ -1,338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/critterai/build/unity/nmgen-rcn/cai-nmgen-rcn.vcproj b/critterai/build/unity/nmgen-rcn/cai-nmgen-rcn.vcproj deleted file mode 100644 index 942e0512..00000000 --- a/critterai/build/unity/nmgen-rcn/cai-nmgen-rcn.vcproj +++ /dev/null @@ -1,278 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/critterai/doc/ReadMe.txt b/critterai/doc/ReadMe.txt deleted file mode 100644 index 974859d3..00000000 --- a/critterai/doc/ReadMe.txt +++ /dev/null @@ -1,14 +0,0 @@ -This directory contains the documentation source and build -artifacts. - -Sandcastle is used for the documentation build. - -The following tools are required: - -Sandcastle: http://sandcastle.codeplex.com/ -Sandcastle Help File Builder: http://shfb.codeplex.com/ - -Sandcastle Styles Patch - -http://sandcastlestyles.codeplex.com/ - Home Page -http://sandcastlestyles.codeplex.com/releases/view/47767 - Patch Used diff --git a/critterai/doc/TOC.content b/critterai/doc/TOC.content deleted file mode 100644 index e6028a1a..00000000 --- a/critterai/doc/TOC.content +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/critterai/doc/Tokens.tokens b/critterai/doc/Tokens.tokens deleted file mode 100644 index 8e146098..00000000 --- a/critterai/doc/Tokens.tokens +++ /dev/null @@ -1,39 +0,0 @@ - - - - AABB - http://en.wikipedia.org/wiki/Bounding_volume - - - Discussion Group - http://groups.google.com/group/critterai - - - Mikko Mononen - http://digestingduck.blogspot.com/ - - - Project Home - http://www.critterai.org/ - - - CAINav Source - http://code.google.com/p/critterai/source/browse/ - - - Recast Navigation - http://code.google.com/p/recastnavigation/ - - - Unity - http://unity3d.com/ - - - Unity Pro - http://unity3d.com/ - - - Issues List - http://code.google.com/p/critterai/issues/list - - \ No newline at end of file diff --git a/critterai/doc/alldoc.shfbproj b/critterai/doc/alldoc.shfbproj deleted file mode 100644 index 6c34fe23..00000000 --- a/critterai/doc/alldoc.shfbproj +++ /dev/null @@ -1,374 +0,0 @@ - - - - Debug - AnyCPU - 2.0 - {fca7a86a-dedd-4cdc-a1e5-05acca3edf76} - 1.9.0.0 - - Documentation - Documentation - Documentation - - .\alldoc\ - cai - en-US - alldoc.log - 3.5 - Website - Aggregate documentation for all CritterAI projects. - - - -&lt%3bp&gt%3bSome libraries require &lt%3ba href=&quot%3bhttp://unity3d.com/&quot%3b target=&quot%3b_blank&quot%3b&gt%3bUnity&lt%3b/a&gt%3b.&lt%3b/p&gt%3b - - - -&lt%3bp&gt%3b -&lt%3ba href=&quot%3bhttp://www.critterai.org/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bProject Home -&lt%3b/a&gt%3b&lt%3bbr /&gt%3b -&lt%3ba href=&quot%3bhttp://code.google.com/p/critterai/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bProject Source&lt%3b/a&gt%3b&lt%3bbr /&gt%3b - -&lt%3ba href=&quot%3bhttp://www.critterai.org/cailic&quot%3b target=&quot%3b_parent&quot%3b&gt%3bLicense&lt%3b/a&gt%3b -&lt%3b/p&gt%3b - - - - - - - - - - - - - Copyright %28c%29 2010-2012 Stephen A. Pratt - &lt%3ba href=&quot%3bhttp://www.critterai.org/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bProject Home&lt%3b/a&gt%3b | &lt%3ba href=&quot%3bhttp://code.google.com/p/critterai/&quot%3b target=&quot%3b_parent&quot%3b&gt%3bSource Code&lt%3b/a&gt%3b | &lt%3ba href=&quot%3bhttp://www.critterai.org/cailic&quot%3b target=&quot%3b_parent&quot%3b&gt%3bLicense&lt%3b/a&gt%3b - CritterAI Documentation - Protected, SealedProtected - - Provides general utility features. - Provides computational geometry features. - Provides native interop utility features. - Provides core pathfinding and local steering features. - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use extensions related to navigation. (Pathfinding and local steering.) - Provides core features related to building navigation mesh data. (From source geometry.) - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use elements related to CAINav. (Navigation mesh generation, pathfinding, local steering, etc.) - Provides general <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use extentions. - Provides ease-of-use features related to building navigation meshes at design time. - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> ease-of-use features related to building navigation meshes at design time. - Provides <a href="http://unity3d.com/unity/" target="_blank">Unity</a> Editor ease-of-use extensions related to navigation. (Pathfinding and local steering.) - - HashedMemberName - True - hana - Summary, Parameter, Returns, AutoDocumentCtors, Namespace, TypeParameter, AutoDocumentDispose - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Explorer-StraightPath - Explorer - Straight Path - - - - - - - - - - - - - - - - - - - - - - - Value-MinRegionArea - Value: MinRegionArea - True - - - Heightfield-AABB - Heightfield: AABB - - - Heightfield-Columns - Heightfield: Columns - - - Heightfield-VoxelGrid - Heightfield: Voxel Grid - - - Heightfield-OpenField - Heightfield: Open Field - - - Heightfield-SolidField - Heightfield: Solid Field - - - Heightfield-SolidSpan - Heightfield: Solid Span - - - Heightfield-ColumnVoxels - Heightfield: ColumnVoxels - - - Stage-RawContour - Stage: Raw Contour - - - Stage-Regions - Stage: Regions - - - Stage-PolyMesh - Stage: Polygon Mesh - - - Stage-DetailMesh - Stage: Detail Mesh - - - Stage-OpenHeightfield - Stage: Open Heightfield - - - VoxelizedTriangle - Voxelized Triangle - - - Stage-SimplifiedContour - Stage: Simplified Contour - - - Example-AssignGeom - Example: Assign Geometry - - - Example-NMGenConfig - Example: NMGen Config - - - Example-InteriorEnvironment - Example: Interior Environment - - - Example-FinalMesh - Example: Final Mesh - - - PolyMeshDetail-Basic - Poly Mesh Detail-Basic - - - PolyMesh-Basic - Poly Mesh-Basic - - - Value-WalkableRadius - Value: WalkableRadius - True - - - Value-WalkableHeight - Value: Walkable Height - True - - - Value-WaklableStep - Value: Waklable Step - True - - - WrapDirection - Standard Wrap Direction - - - CaiNavComponents - High Level Components - - - Explorer-StraightPathLg - Explorer-Straight Path - - - Explorer-StraightPath - Explorer-Straight Path - - - CAINavDependencies - Dependencies - - - - - U3D-NavManagerOptions - U3D: NavSource Options - - - - - U3D-NavManagerStructure - U3D: NavSourceStructure - - - - - OffMeshConnection - Off Mesh Connection - - - - - NavmeshBuild-Standard - Standard Navmesh Build - - - - - NMGenBuildStandard - Standard NMGen Build - - - - - UnityNMGenMainAssets - Navmesh Build-Unity Main Assets - - - - - UnityInputBuildProcess - Unity Input Build Process - - - - - OverlappingAreaMarkers - Overlapping Area Markers - - - - - NavmeshBuildInspector - Navmesh Build Inspector - - - - - NavmeshBuildUpper - Navmesh Build Upper - - - NavmeshBuildInput - Navmesh Build Input - - - NavmeshBuildConfig - Navmesh Build Config - - - - - AdvancedBuild-Input - Advanced Build-Input - - - AdvancedBuild-Config - Advanced Build-Config - - - AdvancedBuild-Builder - Advanced Build-Builder - - - - - \ No newline at end of file diff --git a/critterai/doc/cainav/CAINav.aml b/critterai/doc/cainav/CAINav.aml deleted file mode 100644 index 74c8c6c1..00000000 --- a/critterai/doc/cainav/CAINav.aml +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - CAINav is a navigation system for use with .NET and UnityPro on Windows. - It provides navigation mesh generation, pathfinding, and local steering functionality. - - - - At the core of CAINav is the well regarded RecastNavigation by - Mikko. This library is mostly about adapting Recast Navigation for use with .NET and Unity. - So most of the core features are courtesy of Mikko's work. - - - - - - This is an alpha release meant for use by early adopters. - - - Not all features have undergone rigorous testing. Some features have little documentation. - Expect frequent changes to the API and potentially breaking changed to Unity components. - E.g. Unity components may need to be deleted and re-created when migrating to a new release. - - - Feedback provided through the DiscussionGroup will be much appreciated. - - - - - CAINavDownload (Zip) - - - - -
      - - Navigation Mesh Generation - - - - - - Generates polygon meshes representing the traversable surface of arbitrary source geometry. - - - Core features are independent of the pathfinding and steering components, providing more options for work flow and distribution. - - - A highly extendable build process suitable for creating complex navigation meshes at design time. - - - Unity extensions that provide designer (non-coder) friendly build processes. - - - - - -
      - -
      - - Pathfinding - - - - - A* and Dijsktra searches. - Various local environment queries for fast, no search movement. - Easy management of path corridors. - - Custom connections between different areas of the mesh for non-standard movement. - (Off-mesh connections.) - - The ability to enable/disable polygons on a per agent basis. (Polygon filtering.) - The ability to define polygon traversal costs on a per agent basis. - Tiling of meshes to efficiently deal with large areas. - - - - -
      - -
      - - Local Steering - - - - - Local steering/collision avoidance for up to 20 agents. - Independent agents that respond to the presence of other agents. - Following behavior and moving as a group. - - - - -
      - -
      - - Miscellany - - - - - Core features available for use with Unity Pro and .NET-only implemenations. - Many ease-of-use extensions for Unity. - - Unity plug-in deployment restrictions - http://unity3d.com/support/documentation/Manual/Plugins.html - apply. E.g. Can't be deployed to the Unity web player. - - CAINav is not officially supported for use in the Unity Editor on the Mac OS, - or at runtime on any platform other than Windows. This is not a technical limitation, but is - due to the lack of non-Windows systems for builds and testing. - - - Does not support temporary obstacles. - - - - - -
      - -
      - - Sample Pack - - - - - The Sample Pack contains demos that will let you play around with various - the navigation features. Simply extract the contents and run the demos. They provides a lot of nice visualizations. - - - - - - Kaspersky Internet Security may report a PDM.Keylogger security warning - http://forum.unity3d.com/threads/36180-PDM.Keylogger-problem - when Feature Explorer is run. Kaspersky must not like the way - Unity detects keyboard input, because I certainly haven't included any viruses. Honest...really... - - - - The Sample Pack pre-compiled demos have been tested on 64-bit Windows 7 and 32-bit - Windows Vista. - - - - - - CAINavExplorerDownload (Download/Zip) - - - -
      - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/CAINavOtherPlatforms.aml b/critterai/doc/cainav/CAINavOtherPlatforms.aml deleted file mode 100644 index f9927a4b..00000000 --- a/critterai/doc/cainav/CAINavOtherPlatforms.aml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - The only supported platforms are .NET and UnityPro on Windows. This topic exists - only because attempts are being made to keep CAINav interop friendly. - - - - - - The only provided distributions for CIANav are for the Windows OS. But follows are some - tips if you choose to try to get it working on other platforms. - - - - For the native code, you'll need to recompile the cai-nmgen-rcn and - cai-nav-rcn libraries for your target platform. - The native code is simple, with no Windows dependent headers. If you are inspecting the current libraries and wondering - about some unexpected dependancies, don't worry. They are compiled with the /clr (common languare runtime) flag - because it makes testing and debugging a whole lot easier. It isn't technically required. - - - - Some platforms, including iOS, require that the C# source code be added directly to the - Unity project. This is easy. - Simply browse to \cai-nav-x.x.x\source\src\main\Assets in the distribution and copy the CAI folder - into your project's Asset folder. - - - - - - - A lot of the code protection depends on internal scoping. So take care not to accidentally use internally scoped elements - if you are using a source distribution. - - - - - - Another item you need to be aware of is a serialization gotcha. Never use - the .NET ISerializable interface to serialize CAINav objects. Use the various - byte[] serialization methods instead. It will save you a lot - of headaches down the road if you need to transfer serialized assets between projects on different platforms. - - - - - - \ No newline at end of file diff --git a/critterai/doc/cainav/CAINavStructure.aml b/critterai/doc/cainav/CAINavStructure.aml deleted file mode 100644 index fc83bc30..00000000 --- a/critterai/doc/cainav/CAINavStructure.aml +++ /dev/null @@ -1,336 +0,0 @@ - - - - - - - - The first thing to understand about CAINav is that it is - not a plug-and-play solution. Well, NMGen in Unity is plug-and-play. But creating the - navigation mesh is just the starting point. To use the navigation mesh you'll need to implement your own - code. And to do that you'll need to understand CAINav's structure. - - - - All core features of CAINav can be used in .NET-only applications. But there are many - ease-of use extensions available for use only in Unity Pro. Any library or namespace containing 'u3d' are Unity-only. - - - - - - Definitions - - - Core features: Elements (classes, interfaces, etc.) that provide the core features. They are part of the .NET API - and are available for use by all users. - - - Common extensions: Elements that provide ease-of-use features for all users. - - Unity extensions: Elements that provide ease-of-use features specific to Unity users. - - - - - -
      - - The 10,000 Meter View - - - - - The below diagram shows the relationships of the core components from a construction/build - perspective. - - - - - - - - -
      - -
      - - 1 - Input Data - - - - - As a minimum you have to have some sort of source - geometry from which you can obtain vertex and triangle data. In Unity, the source geometry is - usually obtained from MeshFilters and Terrain objects. But anything that provides vertices and - triangles can be used. - - - - For more complex builds you may also need to provide other data such as off-mesh connections and - custom build processors. - - - - Common Extensions: - T:org.critterai.nmbuild.InputGeometry, - T:org.critterai.nmbuild.ProcessorSet - - - - The Unity extensions implement a flexible and extensible input build process that helps - gather everyting together for you. - - - - Triangle wrap direction on the xz-plane is used for the detection of which face of the triangle is - considered up. The y-axis is up/down. A picture is worth a thousand words. If your source geometry is wrapped differently - than shown, then it will need to be translated into this format before use in the NMGen - build process. - - - - - - CAINav uses the OpenGL coordinate system. - - - - - - - - - -
      - -
      - - 2 - NMGen Configuration - - - - - Source geometry may represent exterior natural geography or interior environments in any number - of different styles. The navigation clients may be human-type agents, vehicles, - wheeled robots, etc.; each with its own locomotion restrictions. For these reasons NMGen supports a large variety of - configuration settings that adjust how the navigation mesh data is generated. - - - - Core Classes: - T:org.critterai.nmgen.NMGenParams, - T:org.critterai.nmgen.NMGenTileParams - - - - -
      - -
      - - 3 - Polygon and Detail Meshes - - - - - The input data and NMGen configuration are used to create two types of meshes. The - polygon mesh provides the data needed for pathfinding operations. The optional detail mesh provides extra - height detail helpful for certain position queries. (Better height position at a higher memory cost.) - Together, these meshes provide the core structural data for the navigation mesh. - - - - Core Classes: - T:org.critterai.nmgen.PolyMesh, - T:org.critterai.nmgen.PolyMeshDetail - - - - - - - - -
      - -
      - - 4 - Off-Mesh Connections - - - - - In some cases there are special travel routes not based on the surface of the source geometry. For example, - an agent may be able to vault over a railing. Off-mesh connections can be used to represent - these routes and are connected to the navigation mesh as a single edge. - - - - Common Extensions: - T:org.critterai.nmbuild.ConnectionSet - - - - - - - - -
      - -
      - - 5 - Navigation Mesh Tiles - - - - - Tiles contain the data that makes up the navigation mesh. A navigation mesh - cannot exist without at least one tile. The ability to have multiple - tiles in a navigation mesh opens up a huge variety of options. Think: Navigation meshes that - cover large or complex areas, swapping tiles in and out at runtime. - - - - As a minimum, each tile contains a polygon mesh. It can also contain optional data such as - a detail mesh and off-mesh connections. - - - - Core Classes: - T:org.critterai.nav.NavmeshTileBuildData, - T:org.critterai.nav.NavmeshTileData, - T:org.critterai.nav.NavmeshTile - - - - -
      - -
      - - 6 - Navigation Mesh - - - - - A navigation mesh may contain a single rectangle tile, or a grid of square tiles. It is compact - and efficient with various methods of serializing, de-serializing, and swapping data in and out at - runtime. - - - Core Class: - T:org.critterai.nav.Navmesh - - - Unity Extensions: - T:CAIBakedNavmesh, - T:org.critterai.nav.u3d.INavmeshData - - - - -
      - -
      - - 7 - Navigation Mesh Query - - - - - The navigation mesh query is what all clients use to perform pathfinding and related - queries against the navigation mesh. Even if you use the crowd manager for steering, you'll - need to use a navigation mesh query for non-local pathfinding and other higher level planning. - - - - Core Class: - T:org.critterai.nav.NavmeshQuery - - - - - - - - -
      - -
      - - 8 - Query Filter - - - - - Filters allow pathfinding behavior to be altered at runtime without changing the structure of - the navigation mesh. They are used in most query methods to indicate which navigation mesh polygons - are considered accessible and which aren't. They also define the traversal cost of different types - of polygons. - - - Filters can be specific to individual agents or shared between groups of agents. - - - Core Class: - T:org.critterai.nav.NavmeshQueryFilter - - - - -
      - -
      - - 9 - Crowd Manger - - - - - The crowd manager implements local steering. You provide it with agents - to manage and local targets for the agents to move to, and it handles steering the agents in - order to avoid collisions with other agents. - - - - - - The use of the term "local" is important. CrowdManager can't do long distance path planning. - - - - Core Class: - T:org.critterai.nav.CrowdManager - - - - -
      - -
      - - Dependencies and Layers - - - - CAINav consists of multiple libraries, some optional. - - - - The plug-in and core libraries are required. The rest are technically optional. - Duplicate dependencies are not shown. - Some optional 'extras' available for Unity are not shown. - - - - - - - - -
      - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/CAINavTokens.tokens b/critterai/doc/cainav/CAINavTokens.tokens deleted file mode 100644 index 59eb81b6..00000000 --- a/critterai/doc/cainav/CAINavTokens.tokens +++ /dev/null @@ -1,56 +0,0 @@ - - - - Download CAINav - http://code.google.com/p/critterai/downloads/list - - - Sample Pack - http://code.google.com/p/critterai/downloads/list - - -T:org.critterai.nmgen.CompactHeightfield - - -T:org.critterai.nmbuild.ConnectionSet - - -T:org.critterai.nav.CrowdManager - - -T:org.critterai.nmgen.PolyMeshDetail - - -T:org.critterai.nmbuild.IncrementalBuilder - - -T:org.critterai.nmbuild.INMGenProcessor - - -T:org.critterai.nmbuild.InputGeometry - - -T:org.critterai.nav.Navmesh - - -T:org.critterai.nav.NavmeshQuery - - -T:org.critterai.nav.NavmeshQueryFilter - - -T:org.critterai.nav.PathCorridor - - -T:org.critterai.nmgen.PolyMesh - - -T:org.critterai.nmbuild.ProcessorSet - - -T:org.critterai.nmbuild.TileSetDefinition - - -T:org.critterai.nmgen.NMGenParams - - \ No newline at end of file diff --git a/critterai/doc/cainav/SwapingVectors.aml b/critterai/doc/cainav/SwapingVectors.aml deleted file mode 100644 index 4dd4d7df..00000000 --- a/critterai/doc/cainav/SwapingVectors.aml +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - Depending on the way CAINav is built, it will use either the UnityEngine vectors or the CAINav built-in vectors. - For Unity users, UnityEngine.Vector3 and UnityEngine.Vector2. For .NET-Only users, org.critterai.Vector3 and org.critterai.Vector2. This is great for Unity users, - but means that .NET-users will probably need to marshal between their native vector structures and the CAINav structures. - - - - Advanced users have another option. It may be possible, with only an hour or two of work per version upgrade, to swap your own native vectors - into CAINav. This topic will cover the steps to accomplish this. - - - - -
      - - Overview - - - - - In order to swap your own native vectors into CAINav, you'll need to follow these steps: - - - - Validate that your vector API is compatible. - Update the .NET Visual Studio Projects and code. (Mostly a simple search and replace.) - Build and validate vector data compatibility. - - - - - - - This topic only covers the Vector3 structure. The same basic process can be used for the Vector2 structure. Data compatibility validation is not - required for Vector2 since it is not involved in interop operations. - - - -
      - -
      - - Validate API Compatibility - - - - - The first step is to make sure your native vector's API is compatible with org.critterai.Vector3. To do this, open the .NET Visual Studio - project. It is located in the \build\dotNet directory of the distribution. The source file will be located in the cai-util project. The - Vector3 structure is kept very simple, so the likelihood of conflict is minimal. - - - - While you will be validating data compatibility later, it is a good idea to smoke check that now. (Do the order of the fields match?) - - - - -
      - -
      - - Update the Visual Studio Projects and Code - - - - - Add a reference to your vector library to each project in the Visual Studio solution. - - - - Throughout the CAINav code the following conditional compile statement is used to control which vector is used: - - - - #if NUNITY - using Vector3 = org.critterai.Vector3; - #else - using Vector3 = UnityEngine.Vector3; - #endif - - - - So all you need to do to swap in your own vector is to do a global search and replace. Find "using Vector3 = org.critterai.Vector3;", and - replace it with your own. For example: "using Vector3 = MyEngine.Vector3f;" - - - - Browse to the Vector3 source file in the cai-util project and comment out all code. This makes sure that errors don't accidentally result - in the CAINav vector still being referenced somewhere. - - - - Finally, build the solution. It your API is truly compatible, the build should complete without errors. - - - - -
      - -
      - - Validate Data Compatibility - - - - - The final step is to check data capatibility. (Is the internal data format of your vector the same as the CAINav vector?) To do this, write some - test code that uses the new libraries and run the M:org.critterai.nav.NavUtil.TestVector(UnityEngine.Vector3) and - M:org.critterai.nav.NavUtil.TestVectorArray(UnityEngine.Vector3[],System.Int32,UnityEngine.Vector3[]) test methods. - - - - If the input and output of these test methods matches exactly, then you are good to go. If the tests fail, then you know that there is some - sort of problem and you won't be able to use your native vectors. - - - - -
      - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/images/CAINavDependencies.png b/critterai/doc/cainav/images/CAINavDependencies.png deleted file mode 100644 index bcedc448..00000000 Binary files a/critterai/doc/cainav/images/CAINavDependencies.png and /dev/null differ diff --git a/critterai/doc/cainav/images/Explorer-StraightPath.jpg b/critterai/doc/cainav/images/Explorer-StraightPath.jpg deleted file mode 100644 index c3b30a44..00000000 Binary files a/critterai/doc/cainav/images/Explorer-StraightPath.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/Explorer-StraightPath.psd b/critterai/doc/cainav/images/Explorer-StraightPath.psd deleted file mode 100644 index e706b999..00000000 Binary files a/critterai/doc/cainav/images/Explorer-StraightPath.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/Explorer-StraightPathLg.jpg b/critterai/doc/cainav/images/Explorer-StraightPathLg.jpg deleted file mode 100644 index 9d6557e7..00000000 Binary files a/critterai/doc/cainav/images/Explorer-StraightPathLg.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/HighLevelComponents.png b/critterai/doc/cainav/images/HighLevelComponents.png deleted file mode 100644 index 700d6a20..00000000 Binary files a/critterai/doc/cainav/images/HighLevelComponents.png and /dev/null differ diff --git a/critterai/doc/cainav/images/WrapDirection.png b/critterai/doc/cainav/images/WrapDirection.png deleted file mode 100644 index 39c17a05..00000000 Binary files a/critterai/doc/cainav/images/WrapDirection.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/CAINavSettings.jpg b/critterai/doc/cainav/images/nav/CAINavSettings.jpg deleted file mode 100644 index 579933f2..00000000 Binary files a/critterai/doc/cainav/images/nav/CAINavSettings.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/CAINavSettings.psd b/critterai/doc/cainav/images/nav/CAINavSettings.psd deleted file mode 100644 index 8787c56f..00000000 Binary files a/critterai/doc/cainav/images/nav/CAINavSettings.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/NavManager-Options.jpg b/critterai/doc/cainav/images/nav/NavManager-Options.jpg deleted file mode 100644 index 1735e35e..00000000 Binary files a/critterai/doc/cainav/images/nav/NavManager-Options.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/NavManager-Options.psd b/critterai/doc/cainav/images/nav/NavManager-Options.psd deleted file mode 100644 index 996786a8..00000000 Binary files a/critterai/doc/cainav/images/nav/NavManager-Options.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/NavManager-Structure.jpg b/critterai/doc/cainav/images/nav/NavManager-Structure.jpg deleted file mode 100644 index d98d5866..00000000 Binary files a/critterai/doc/cainav/images/nav/NavManager-Structure.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/NavManager-Structure.psd b/critterai/doc/cainav/images/nav/NavManager-Structure.psd deleted file mode 100644 index 8e42ec02..00000000 Binary files a/critterai/doc/cainav/images/nav/NavManager-Structure.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/OffMeshConnection.jpg b/critterai/doc/cainav/images/nav/OffMeshConnection.jpg deleted file mode 100644 index 16fffafe..00000000 Binary files a/critterai/doc/cainav/images/nav/OffMeshConnection.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nav/OffMeshConnection.psd b/critterai/doc/cainav/images/nav/OffMeshConnection.psd deleted file mode 100644 index c081f5c2..00000000 Binary files a/critterai/doc/cainav/images/nav/OffMeshConnection.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/ConservativeVoxelization.jpg b/critterai/doc/cainav/images/nmgen/ConservativeVoxelization.jpg deleted file mode 100644 index 8e5d6cba..00000000 Binary files a/critterai/doc/cainav/images/nmgen/ConservativeVoxelization.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/ConservativeVoxelization.png b/critterai/doc/cainav/images/nmgen/ConservativeVoxelization.png deleted file mode 100644 index 2e12048c..00000000 Binary files a/critterai/doc/cainav/images/nmgen/ConservativeVoxelization.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Heightfield-BasicBox.jpg b/critterai/doc/cainav/images/nmgen/Heightfield-BasicBox.jpg deleted file mode 100644 index c3df5f33..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Heightfield-BasicBox.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Heightfield-Columns.jpg b/critterai/doc/cainav/images/nmgen/Heightfield-Columns.jpg deleted file mode 100644 index 837f3f25..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Heightfield-Columns.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Heightfield-Open.jpg b/critterai/doc/cainav/images/nmgen/Heightfield-Open.jpg deleted file mode 100644 index 68b8a483..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Heightfield-Open.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Heightfield-Solid.jpg b/critterai/doc/cainav/images/nmgen/Heightfield-Solid.jpg deleted file mode 100644 index 3347b74f..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Heightfield-Solid.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Heightfield-SolidSpan.jpg b/critterai/doc/cainav/images/nmgen/Heightfield-SolidSpan.jpg deleted file mode 100644 index 781b4bfe..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Heightfield-SolidSpan.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Heightfield-VoxelColumn.jpg b/critterai/doc/cainav/images/nmgen/Heightfield-VoxelColumn.jpg deleted file mode 100644 index 0ddcf5e0..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Heightfield-VoxelColumn.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Heightfield-VoxelGrid.jpg b/critterai/doc/cainav/images/nmgen/Heightfield-VoxelGrid.jpg deleted file mode 100644 index 532eae14..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Heightfield-VoxelGrid.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/NMGenBuildStandard.png b/critterai/doc/cainav/images/nmgen/NMGenBuildStandard.png deleted file mode 100644 index 1d939949..00000000 Binary files a/critterai/doc/cainav/images/nmgen/NMGenBuildStandard.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/NavmeshBuild-Standard.png b/critterai/doc/cainav/images/nmgen/NavmeshBuild-Standard.png deleted file mode 100644 index 5db540bf..00000000 Binary files a/critterai/doc/cainav/images/nmgen/NavmeshBuild-Standard.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/NavmeshBuild-UnityMainAssets.png b/critterai/doc/cainav/images/nmgen/NavmeshBuild-UnityMainAssets.png deleted file mode 100644 index 0fa7d7e5..00000000 Binary files a/critterai/doc/cainav/images/nmgen/NavmeshBuild-UnityMainAssets.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/PolyMesh-Basic.jpg b/critterai/doc/cainav/images/nmgen/PolyMesh-Basic.jpg deleted file mode 100644 index b2b7bb47..00000000 Binary files a/critterai/doc/cainav/images/nmgen/PolyMesh-Basic.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/PolyMesh-Basic.psd b/critterai/doc/cainav/images/nmgen/PolyMesh-Basic.psd deleted file mode 100644 index f46fe717..00000000 Binary files a/critterai/doc/cainav/images/nmgen/PolyMesh-Basic.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/PolyMeshDetail-Basic.jpg b/critterai/doc/cainav/images/nmgen/PolyMeshDetail-Basic.jpg deleted file mode 100644 index c06d7208..00000000 Binary files a/critterai/doc/cainav/images/nmgen/PolyMeshDetail-Basic.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/PolyMeshDetail-Basic.psd b/critterai/doc/cainav/images/nmgen/PolyMeshDetail-Basic.psd deleted file mode 100644 index 504fe04f..00000000 Binary files a/critterai/doc/cainav/images/nmgen/PolyMeshDetail-Basic.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-DetailMesh.jpg b/critterai/doc/cainav/images/nmgen/Stage-DetailMesh.jpg deleted file mode 100644 index d8982f9a..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-DetailMesh.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-DetailMesh.png b/critterai/doc/cainav/images/nmgen/Stage-DetailMesh.png deleted file mode 100644 index 7929cf31..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-DetailMesh.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-OpenHeightfield.jpg b/critterai/doc/cainav/images/nmgen/Stage-OpenHeightfield.jpg deleted file mode 100644 index 4b48505d..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-OpenHeightfield.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-OpenHeightfield.png b/critterai/doc/cainav/images/nmgen/Stage-OpenHeightfield.png deleted file mode 100644 index 93905d8a..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-OpenHeightfield.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-PolyMesh.jpg b/critterai/doc/cainav/images/nmgen/Stage-PolyMesh.jpg deleted file mode 100644 index b77cfad8..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-PolyMesh.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-PolyMesh.png b/critterai/doc/cainav/images/nmgen/Stage-PolyMesh.png deleted file mode 100644 index 3e91f467..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-PolyMesh.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-RawContour.jpg b/critterai/doc/cainav/images/nmgen/Stage-RawContour.jpg deleted file mode 100644 index a0c9ab7b..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-RawContour.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-RawContour.png b/critterai/doc/cainav/images/nmgen/Stage-RawContour.png deleted file mode 100644 index b344d74a..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-RawContour.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-Regions.gif b/critterai/doc/cainav/images/nmgen/Stage-Regions.gif deleted file mode 100644 index 4078dd60..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-Regions.gif and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-Regions.png b/critterai/doc/cainav/images/nmgen/Stage-Regions.png deleted file mode 100644 index c375b3da..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-Regions.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-SimplifiedContour.jpg b/critterai/doc/cainav/images/nmgen/Stage-SimplifiedContour.jpg deleted file mode 100644 index 4f5fa8d6..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-SimplifiedContour.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Stage-SimplifiedContour.png b/critterai/doc/cainav/images/nmgen/Stage-SimplifiedContour.png deleted file mode 100644 index a837694c..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Stage-SimplifiedContour.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/UnityInputBuildProcess.png b/critterai/doc/cainav/images/nmgen/UnityInputBuildProcess.png deleted file mode 100644 index 5013a0af..00000000 Binary files a/critterai/doc/cainav/images/nmgen/UnityInputBuildProcess.png and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-MinRegionArea.jpg b/critterai/doc/cainav/images/nmgen/Value-MinRegionArea.jpg deleted file mode 100644 index e5b6f691..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-MinRegionArea.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-MinRegionArea.psd b/critterai/doc/cainav/images/nmgen/Value-MinRegionArea.psd deleted file mode 100644 index c6510151..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-MinRegionArea.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-WaklableStep.jpg b/critterai/doc/cainav/images/nmgen/Value-WaklableStep.jpg deleted file mode 100644 index c8672bf8..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-WaklableStep.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-WaklableStep.psd b/critterai/doc/cainav/images/nmgen/Value-WaklableStep.psd deleted file mode 100644 index 8a1471b9..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-WaklableStep.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-WalkableHeight.jpg b/critterai/doc/cainav/images/nmgen/Value-WalkableHeight.jpg deleted file mode 100644 index 551a00a5..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-WalkableHeight.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-WalkableHeight.psd b/critterai/doc/cainav/images/nmgen/Value-WalkableHeight.psd deleted file mode 100644 index 371d4a77..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-WalkableHeight.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-WalkableRadius.jpg b/critterai/doc/cainav/images/nmgen/Value-WalkableRadius.jpg deleted file mode 100644 index d1d77eca..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-WalkableRadius.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/Value-WalkableRadius.psd b/critterai/doc/cainav/images/nmgen/Value-WalkableRadius.psd deleted file mode 100644 index 61f35f3d..00000000 Binary files a/critterai/doc/cainav/images/nmgen/Value-WalkableRadius.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Builder.jpg b/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Builder.jpg deleted file mode 100644 index 9e422de9..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Builder.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Builder.psd b/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Builder.psd deleted file mode 100644 index 082f609f..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Builder.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Config.jpg b/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Config.jpg deleted file mode 100644 index bbc7918e..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Config.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Config.psd b/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Config.psd deleted file mode 100644 index 880c024f..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Config.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Input.jpg b/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Input.jpg deleted file mode 100644 index 2c71844e..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Input.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Input.psd b/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Input.psd deleted file mode 100644 index fed2c1c7..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AdvancedBuild-Input.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AssignGeometrySource.jpg b/critterai/doc/cainav/images/nmgen/examples/AssignGeometrySource.jpg deleted file mode 100644 index 93caf08e..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AssignGeometrySource.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/AssignGeometrySource.psd b/critterai/doc/cainav/images/nmgen/examples/AssignGeometrySource.psd deleted file mode 100644 index 344bac57..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/AssignGeometrySource.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/FinalMesh-Lg.jpg b/critterai/doc/cainav/images/nmgen/examples/FinalMesh-Lg.jpg deleted file mode 100644 index 70ee1ec3..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/FinalMesh-Lg.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/FinalMesh.jpg b/critterai/doc/cainav/images/nmgen/examples/FinalMesh.jpg deleted file mode 100644 index c309b17e..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/FinalMesh.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/FinalMesh.psd b/critterai/doc/cainav/images/nmgen/examples/FinalMesh.psd deleted file mode 100644 index d23da721..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/FinalMesh.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment-Lg.jpg b/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment-Lg.jpg deleted file mode 100644 index 74cba4d4..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment-Lg.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment.jpg b/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment.jpg deleted file mode 100644 index 8dae4e42..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment.psd b/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment.psd deleted file mode 100644 index 3cb69880..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/InteriorEnvironment.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildConfig.jpg b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildConfig.jpg deleted file mode 100644 index 147505f0..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildConfig.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildConfig.psd b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildConfig.psd deleted file mode 100644 index 5bd12c71..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildConfig.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInput.jpg b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInput.jpg deleted file mode 100644 index c9f4c65f..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInput.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInput.psd b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInput.psd deleted file mode 100644 index fbdbfed1..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInput.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInspector.jpg b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInspector.jpg deleted file mode 100644 index cf806680..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInspector.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInspector.psd b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInspector.psd deleted file mode 100644 index 3961cffa..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildInspector.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildUpper.jpg b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildUpper.jpg deleted file mode 100644 index d326008b..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildUpper.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildUpper.psd b/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildUpper.psd deleted file mode 100644 index f54baeea..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/NavmeshBuildUpper.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/OverlappingAreaMarkers.jpg b/critterai/doc/cainav/images/nmgen/examples/OverlappingAreaMarkers.jpg deleted file mode 100644 index 010b0ab2..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/OverlappingAreaMarkers.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/OverlappingAreaMarkers.psd b/critterai/doc/cainav/images/nmgen/examples/OverlappingAreaMarkers.psd deleted file mode 100644 index d051b461..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/OverlappingAreaMarkers.psd and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/SetNMGenConfig.jpg b/critterai/doc/cainav/images/nmgen/examples/SetNMGenConfig.jpg deleted file mode 100644 index 4b262a51..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/SetNMGenConfig.jpg and /dev/null differ diff --git a/critterai/doc/cainav/images/nmgen/examples/SetNMGenConfig.psd b/critterai/doc/cainav/images/nmgen/examples/SetNMGenConfig.psd deleted file mode 100644 index 890e3788..00000000 Binary files a/critterai/doc/cainav/images/nmgen/examples/SetNMGenConfig.psd and /dev/null differ diff --git a/critterai/doc/cainav/nav/CrowdManager.aml b/critterai/doc/cainav/nav/CrowdManager.aml deleted file mode 100644 index 7762f1e3..00000000 --- a/critterai/doc/cainav/nav/CrowdManager.aml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - The crowd manager is the big beast of the navigation components. It not only handles a lot of the path management for you, but also - local steering and dynamic avoidance between navigation clients. I.e. It can keep your agents from running into each other. - - - - Core Class: CrowdManager - - - - The NavmeshQuery and PathCorridor classes provide perfectly good, easy to use path planning features. But in - the end they only give you points that your navigation client should be moving toward. When it comes to deciding things like client velocity - and steering to avoid other clients, that is up to you to implement. Unless, of course, you decide to use the crowd manager. - - - - Basically, you add an navigation client (agent) to the crowd manager, providing various configuration settings such as - maximum speed and acceleration. You also provide a local target to more toward. The crowd manager then provides, with every update, the new - agent position and velocity for the frame. The movement will be constrained to the navigation mesh, and steering will be applied to ensure - agents managed by the crowd manager do not collide with each other. - - - - This is very powerful feature set. But it comes with limitations. - - - - The biggest limitation is that you must give control of the agent's position and velocity completely over to the crowd manager. You can - update things like maximum speed and acceleration. But in order for the crowd manager to do its thing, it can't allow you to constantly be - giving it overrides to position and velocity. So you give up direct control of the agent's movement. It belongs to the crowd manager. - - - - The second biggest limitation revolves around the fact that the crowd manager deals with local planning. The agent's target should never - be more than 256 polygons aways from its current position. If it is, you risk your agent failing to reach its target. So you may - still need to do long distance planning and provide the crowd manager with intermediate targets. - - - - Other significant limitations: - - - - All agents using the crowd manager use the same NavmeshQueryFilter. - Crowd management is relatively expensive. The maximum agents under crowd management at any one time is - around 20. - - - - The CAINavExplorerDownload includes a Crowd Manager Demo that lets you see the manager in action. - - - - - - - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshQueryFilter - T:org.critterai.nav.CrowdManager - T:org.critterai.nav.CrowdAgent - T:org.critterai.nav.CrowdAgentParams - T:org.critterai.nav.CrowdAvoidanceParams - - - - - - - - - - \ No newline at end of file diff --git a/critterai/doc/cainav/nav/Nav.aml b/critterai/doc/cainav/nav/Nav.aml deleted file mode 100644 index 1afc3ed4..00000000 --- a/critterai/doc/cainav/nav/Nav.aml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - The navigation side of CAINav consists of features - used to create and use navigation meshes for pathfinding and local steering. - - Core: N:org.critterai.nav - - - Unity extensions: - N:org.critterai.nav.u3d - - - There are five main classes you'll be dealing with: - - - - - CAINav uses the OpenGL coordinate system. - - - - - The Navmesh class defines the structure and state of the navigation mesh. The only user component that deals directly with this class - on a regular basis is the component responsible for creating the mesh and managing its state. Normal navigation clients, the one's needing to perform pathfinding - and such, rarely if ever interact directly with the navigation mesh. - - - - The most important class to understand and become comfortable with is the NavmeshQuery class. It provides almost all of the - client navigation features, including A* and Dijkstra path searches, string pulling, point and polygon searches, raycasting, etc. - - - - The NavmeshQueryFilter is a seemingly minor class, but it has a large impact on navigation. Filters are used to define the costs of - traversing the mesh and flags that control which parts of the navigation mesh are included in operations. Multiple filters can be used to customize the - navigation behavior on a per client basis. - - - - The PathCorridor class provides a way of moving along a navigation path without worrying about the minutiae of managing the - path. - - - - The CrowdManager is the big beast of the navigation classes. It not only handles a lot of the path management for you, but also - local steering and dynamic avoidance between navigation clients. I.e. It can keep your agents from running into each other. - - - - - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshQueryFilter - T:org.critterai.nav.PathCorridor - T:org.critterai.nav.CrowdManager - - - - - - - - - - \ No newline at end of file diff --git a/critterai/doc/cainav/nav/Navmesh.aml b/critterai/doc/cainav/nav/Navmesh.aml deleted file mode 100644 index b28dd55f..00000000 --- a/critterai/doc/cainav/nav/Navmesh.aml +++ /dev/null @@ -1,279 +0,0 @@ - - - - - - - - The navigation mesh is the primary data model for the navigation system. The only user - component that deals directly with the mesh on a regular basis is the component that is - responsible for creating the mesh and managing its state. Normal navigation clients, - the one's needing to perform pathfinding and such, rarely if ever interact directly with the - navigation mesh. - - - Core Class: Navmesh - - - -
      - - The Data Model - - - -
      - - Tiles - - - - - At the core of the navigation mesh is the tile. Tiles hold the vast majority of structural - and state information. In fact, the Navmesh class is little more than a tile manager. - It may consist of a single tile, or many tiles laid out in a grid that can be swapped in and out - at runtime. - - - - The tile based structure of the navigation mesh adds a lot of flexibility. As mentioned, - tiles can be swapped in and out at runtime. This means that the mesh can represent a large - area, but not all tiles have to be loaded and active, reducing the mesh's memory footprint. This also allows - for a situation where individual tiles can be rebuilt without the need to rebuild the entire mesh. - - - - -
      - -
      - - Structural Elements - - - - - The tile's structural data is what defines the navigation graph used for pathfinding. It consists - of two types of elements: Polygons and off-mesh connections. - - - - The core of the structure is a mesh of convex polygons with between three and - F:org.critterai.nmgen.NMGen.MaxAllowedVertsPerPoly vertices. This - mesh is in the same format as NMGen's PolyMesh structure, and usually represents an abstraction - of a scene's static geometry. - - - - Off-mesh connections are optional. They consist of two connected endpoints, at least one of which resides within a - polygon in the polygon mesh. Off-mesh connections are added to the navigation graph as a single edge and - represent special travel routes not defined by scene geometry. Think: The route an agent travels if it jumps - over a railing that normally blocks movement. - - - - -
      - -
      - - State Data - - - - - Tiles also contain state data. This data is associated with individual polygons and off-mesh connections. State - data includes area and flags. - - - - Areas are used to associate traversal cost to structural elements. This effects pathfinding. For example, - the area representing swampland can have a higher cost than the area representing smooth surfaces such as meadowland. - - - - Flags can be used to control when a structural element is traversable. For example, a - flag can be set on the polygon below a door to indicate that it is closed and locked. Or a flag can indicate - that only agents of a particular type are allowed to traverse the element. - - - - It is important to note that areas and flags have no meaning within the navigation mesh - itself. The interpretation of the values is dependant on the NavmeshQueryFilter - used by each navigation client. For example: One filter may define a cost of 10 for area id 5, while another may define - a cost of 2 for the same area. One flag may be set when a door is closed with one filter checking for the flag during - pathfinding, while another filter, used by a ghost, ignores the flag completely. - - - - -
      - -
      - - Structure Versus State - - - - Why is it important to know the difference between structural elements and state data? - - - The first reason is that it is possible to save and load state separately from structure. One common use case is to - have a serialized version of the full navigation mesh that represents its default state. Then serialized versions of various - states, such as the last runtime state, are used to overwrite the default state as needed. - - - - The main limitation is that a state is only valid for a particular structure. So you can't, for example, save the state, - change the tile structure, then load the original state into the new structure. - - - The second reason for understanding the difference between structure and state has to to with tile and polygon references... - - - -
      - -
      - - Tile and Polygon References - - - - - The last bit of information needed to understand the navigation mesh is the concept of tile and polygon references. These - values are one of the few data types that are defined by the navigation mesh rather than the tiles within the mesh. It is important to - understand what references are because they are used by various classes to automatically invalidate pathfinding data if the - structure of a navigation mesh changes. - - - - Essentially, tile and polygon references are unsigned integer 'handles' to structural elements within a navigation mesh. Tile references - are rarely used by navigation clients, while polygon references are all over the place. Polygon references are unique for the navigation mesh, - so they are useful for easily identifying a polygon without needing to know which tile it belongs to. - Despite the name, polygon references can refer to a either a polygon or an off-mesh connection. - - - - References can become invalid. If they are used after they are invalidated, then methods will return a failure status. - Polygon references are based on the tile reference. So they will be invalidated whenever their associated tile reference is invalidated. - - - - Structural changes govern the life of a reference. Changing the configuration of a navigation mesh or the internal structure of a tile - will invalidate all associated references. - - - - References are preserved during tile state changes such as changes flags and areas. They are also preserved during normal - runtime loading and unloading of tiles, and during normal serialization/de-serialization of a navigation mesh. - - - - -
      - -
      - -
      - -
      - - Creating a Navigation Mesh - - - - - There are various pipelines for creating a navigation mesh. If you are using Unity, the - Unity extensions make it easier. Otherwise, - the basic steps are as follows: - - - - Generate packed tile data: - - - - Generate PolyMesh and DetailMesh data using NMGen. - Optionally create a T:org.critterai.nmbuild.ConnectionSet. (Off-mesh connections.) - Load the data into a T:org.critterai.nav.NavmeshTileBuildData object. - Create a T:org.critterai.nav.NavmeshTileData object from the build data. - - - - The tile's structure and default state is now locked into a packed data format that is ready to be loaded into - a navigation mesh. - - - - - - Using the T:org.critterai.nav.NavmeshTileBuildData class - directly can be a bit daunting. The - - M:org.critterai.nmbuild.NMBuild.GetBuildData(org.critterai.nmgen.BuildContext,System.Int32,System.Int32,org.critterai.nmgen.PolyMeshData,org.critterai.nmgen.PolyMeshDetailData,org.critterai.nmbuild.ConnectionSet,System.Boolean) - - utility method provides a standard way of creating the build data. - - - - Create a navigation mesh: - - - Single tile navigation meshes are created using the the single step - M:org.critterai.nav.Navmesh.Create(org.critterai.nav.NavmeshTileBuildData,org.critterai.nav.Navmesh@) - method. - - - - Multi-tile navigation meshes are created then loaded using multiple methods. Use the - M:org.critterai.nav.Navmesh.Create(org.critterai.nav.NavmeshParams,org.critterai.nav.Navmesh@) - method to initialize an empty mesh. then add tile data using the - M:org.critterai.nav.Navmesh.AddTile(org.critterai.nav.NavmeshTileData,System.UInt32,System.UInt32@) - method. - - - - -
      - -
      - - Navigation Mesh Serialization - - - - - The Navmesh class supports byte serialization using the - M:org.critterai.nav.Navmesh.GetSerializedMesh - method. This saves the entire mesh. - - - - It is possible to serialize state separately from structure on a tile-by-tile basis. Get the tile - from the mesh using the M:org.critterai.nav.Navmesh.GetTile(System.Int32) method, then use the - M:org.critterai.nav.NavmeshTile.GetState(System.Byte[]) and - M:org.critterai.nav.NavmeshTile.SetState(System.Byte[]) methods. - - - - -
      - - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshTileBuildData - T:org.critterai.nav.NavmeshTileData - T:org.critterai.nav.NavmeshTile - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nav/NavmeshQuery.aml b/critterai/doc/cainav/nav/NavmeshQuery.aml deleted file mode 100644 index a25f6dbf..00000000 --- a/critterai/doc/cainav/nav/NavmeshQuery.aml +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - The navigation mesh query is the most important class to understand since most navigation clients will interact with the query - rather than the navigation mesh itself. The mesh contains the data, but the query provides almost all of the features - necessary for pathfinding. - - - - Core Class: NavmeshQuery - - - - Query features fall into two general categories: Pathfinding and local search. - - - - Pathfinding involves standard A* and Dijkstra searches that find the best path(s) between two points. Paths are made up of - a list polygon references that represent a polygon corridor from the start to the end position. Path straightening is used to - convert the path into a list of waypoints. (I.e. String pulling.) - - - - The local search features offer various methods for locating polygons and points on polygons, and for querying - the local environment. I.e. Raycasting, finding the distance to the nearest wall, etc. - - - - Many of the query methods require a NavmeshQueryFilter. Filters define area traversal costs as well as flags - used for including/excluding polygons and off-mesh connections from results. - - - - The best way to understand the query class is to play around with it. The CAINavExplorerDownload includes the Query Explorer - demo that permits experimentation with all of the main query features. - - - - -
      - - Common Operations - - - - - This section contains some simple examples of common query operations. - - -
      - - Finding a Point in the Navigation Mesh - - - - - You can't do much without first getting a valid point on the navigation mesh. So the first step is to find one. - - - - - M:org.critterai.nav.NavmeshQuery.GetNearestPoint(UnityEngine.Vector3,UnityEngine.Vector3,org.critterai.nav.NavmeshQueryFilter,org.critterai.nav.NavmeshPoint@) - - - - - - // Where 'query' is a NavmeshQuery object and 'filter' is a NavmeshQueryFilter object. - // 'position' is a Vector3 indicating the world position of the client. - - NavmeshPoint result; - Vector3 extents = new Vector3(1, 1, 1); // Keep this to the minimum extents practical. - - NavStatus status = query.GetNearestPoly(position, extents, filter - , out result); - - if (result.polyRef == Navmesh.NullPoly) - { - // Handle error. Could not find a result. - // The status can be checked to see if there was an error. If not, then - // the cause is that the search extents did not overlap any polygons. - } - - // Use the result point, which includes a vector point and the reference of - // the polygon that contains the point. - - - - - -
      - -
      - - Basic Pathfinding - - - - - Even if you are planning to use PathCorridor or CrowdManager, - you'll always need to do long distance planning using the basic NavmeshQuery features. - First, get a path, then optionally straighten it. - - - - - // Where 'query' is a NavmeshQuery object and 'filter' is a NavmeshQueryFilter object. - // 'start' and 'end' are NavmeshPoints known to be on the navigation mesh. - - int pathCount; - // The path will be a list of polygon references. - uint[] path = new uint[100]; // Size for maximum allowed path length. - NavStatus status; - - if (start.polyRef == end.polyRef) - { - // No need to do any planning. - pathCount = 1; - path[0] = start.polyRef; - } - else - { - status = query.FindPath(start, end, filter, path - , out pathCount); - - if (NavUtil.Failed(status) || path.pathCount == 0) - { - // Handle pathfinding failure. - } - else if (end.polyRef != path[pathCount - 1]) - { - // Handle a partial path. - // The query either could not reach the end point, - // or the path buffer was too small to hold the - // entire path. (A check of 'status' will reveal if - // the buffer was too small.) - } - - } - - // If you need to straighten the path... - - const int MaxStraightPath = 4; // Just getting the first 4 waypoints. - int wpCount; - - // The waypoints. - Vector3[] wpPoints = new Vecotr3[MaxStraightPath]; - - // A list of polygon references. (The polygon being entered at each waypoint.) - uint[] wpPath = new uint[MaxStraightPath]; - - // The type of each waypoint. (Start, end, off-mesh connection.) - WaypointFlag[] wpFlags = new WaypointFlag[MaxStraightPath]; - - status = query.GetStraightPath(start.point - , goal.point - , path - , 0 // The index of the start of the path. - , pathCount // The length of the path. - , wpPoints - , wpFlags - , wpPath - , out wpCount); - - if (NavUtil.Failed(status) || wpCount == 0) - { - // Handle the failure. There should always be at least one waypoint - // (the goal) for a valid point/path combination, - } - - // Use the path and waypoints. - - - - - -
      - -
      - -
      - - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.NavmeshQueryFilter - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nav/PathCorridor.aml b/critterai/doc/cainav/nav/PathCorridor.aml deleted file mode 100644 index 08143295..00000000 --- a/critterai/doc/cainav/nav/PathCorridor.aml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - The path corridor provides a way of moving along a navigation path without worrying about the minutiae of managing the path. - - - - Core Class: PathCorridor - - - - In the simplest scenario, a path is a list of waypoints from a starting point to an end point. The waypoints form a connected - set of line segments along which a navigation client moves. But navigation is much more complex in the real world. There are - locomotion limitations, local steering restrictions, dynamic obstacle avoidance, and good old floating point errors. All of these - issues can make management of a path difficult. - - - - Navigation based on a polygon mesh provides a different abstraction than just a list of waypoints. The path returned by the - NavmeshQuery class is a list of polygons. Technically, a client can move freely anywhere within this corridor of polygons. - If a client strays outside the corridor, then the corridor can be patched up using local searches rather than full path replanning. - - - - The path corridor is loaded with a path, a start point, and a target point. It is then used to move the navigation client through - the corridor. It handles path straightening, constraining the client to the navigation mesh, and adjusting the corridor due to - inaccurate client locomotion. - - - - The PathCorridor API is well documented. The only thing worth repeating here is a warning: You can't just initialize a - corridor with a path and forget long distance path planning. Since the path corridor class uses local searches to maintain the corridor, - attempting to apply large delta movement to the corridor's position or target can result in a malformed corridor. Details are in the API - documentation. - - - - - - - T:org.critterai.nav.NavmeshQuery - T:org.critterai.nav.PathCorridor - T:org.critterai.nav.PathCorridorData - - - - - - - - - - \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/AreasAndBuild.aml b/critterai/doc/cainav/nmgen/AreasAndBuild.aml deleted file mode 100644 index 390936f1..00000000 --- a/critterai/doc/cainav/nmgen/AreasAndBuild.aml +++ /dev/null @@ -1,224 +0,0 @@ - - - - - - - - Areas in CAINav are represented by a byte value between zero and 63. In the navigation mesh they are assigned to polygons - and used to assign traversal cost. For example, all polygons assigned an area of 24 may be assigned a cost of 1.5 while polygons - assigned an area of 63 may be assigned a cost of 1.0. The meaning and cost associated with each area is defined by the end user. The only - exception is 0, which is always considered to mean 'unwalkable'. - - - - Areas are also used in the NMGen build process. But while their purpose and use in the navigation mesh is fairly straight forward, - things can get complicated in the build process. This topic covers various ways of using areas during the build process to get the navigation mesh you want. - - - - - - - Area constants can be found in the T:org.critterai.nmgen.NMGen and - T:org.critterai.nav.Navmesh classes. - - - - - - -
      - - Why Use Areas in the Build Process - - - - - If you assign everything to only a single area during the NMGen build process then polygons will form based solely - on the structure of the source geometry. Polygon edges will form along the borders of obstructions, in structural portals such as doorways, etc. - The surface type of the source geometry is unknown and can't be taken into account. So, for example, a single polygon may cover both - meadow and swamp surfaces, even though the cost of traversing the surfaces is different. - - - - Essentially, areas allow you to specify surface type so that the build process can make sure that polygons are formed such that they don't - overlap different area types. Polygon edges will always form at the boundry between different areas. - - - - The obvious benefit of forming polygons based on surface type is that it allows you to properly control traversal cost. But there are other purposes. - One example is flag assignment. Polygons have an associated 16-bit flags field. These flags are used to filter polygons during pathfinding. For example, you - can specify that all polygons with the 0x10 flag are inaccessible, so pathfinding will ignore the polygons. Areas can be used to ensure that polygons - form in a way that allow flags to be used properly. - - - - Let's say you have a bridge that can partially collapse. There is no way for the build process to know exaclty which part of the bridge can collapse, - so you can't guarentee that separate polygons will exist at the proper location. Unless, of course, you mark the collapse location with a different area - than the rest of the bridge. - - - - In the below example, cylinder and convex areas are marked into the mesh. The convex marker was given a higher priority so that it overwrites part - of the cyclinder area. - - - - - - - - As you can see, areas provide a powerful method of ensuring the final mesh structure is what you need it to be. - - - - -
      - -
      - - The Power of Zero - - - - - The zero area is called the 'NullArea' and has a special meaning to the NMGen build process. Any surface marked as NullArea - is unwalkable and no polygons will form. All NullArea surfaces are considered obstacles. - - - - The build process automatically handles NullArea assignment for most cases. The surface's slope may be too steep. (E.g. Walls) The - polygons formed on the surface may be too small to be of use. (E.g. Stairway railings or a counter top.) The surface may be inaccessible due - to height restrictions. (E.g. The floor under a table.) - - - - But sometimes you may want to manually block off an area. For example, let's say you have a surface covered by burning rubbish. The structure - of the surface may be walkable, but you never want it to be walkable. In cases such as this you can manually mark the surface as a NullArea and - the build process will treat it as an obstacle. - - - - The NullArea is treated differently than other areas in another way. Normal areas can be reassigned at will. You can assign a surface to area - 15 during one part of the build process then reassign part of it to area 22 later on. A NullArea can never be reassigned. Once a NullArea, always - a NullArea. You never have to worry about accidentally making a NullArea walkable again. - - - - -
      - -
      - - How to Assign Areas - - - - - There are three points in the build process where you can assign areas: - - - - - To the source geometry triangles when compiling the input. - To convex areas in the CompactField object. - To polygons in the PolyMesh object. - - - - - - - Technically, you can't perform a NMGen build without assigning areas. At some point in the build it will detect - that you haven't assigned areas and will assign all surfaces to a default area. - - - - -
      - - Source Geometry Area Assignment - - - - - The first point at which you can assign areas is during the input compile. You can assign each source geometry triangle to an area. - This is a great place to assign areas if your source geometry is inherently categorized by surface type. E.g. All bridge and sidewalk - meshes get one area while all water meshes get a different area. - - - - Both the T:org.critterai.nmbuild.InputGeometryCompiler and - InputGeometry classes provide ways to assign areas to triangles. The Unity build process - includes the ability to assign area by tag assignment or mesh. - - - - -
      - -
      - - Marking the CompactHeightfield - - - - - In some cases it either isn't possible or isn't appropriate to assign areas to the source geometry. The next option is to mark areas - directly into the CompactField during its post-processing step. The - T:org.critterai.nmbuild.AreaBoxMarker, - T:org.critterai.nmbuild.AreaCylinderMarker, and - T:org.critterai.nmbuild.AreaConvexMarker classes can be used to mark arbitrary convex areas - into the heightfield. - - - - This is the most accurate method of marking an area since marking occurs at the resolution of the heightfield. (I.e. The cell size.) - However, if abused it can create a lot of extra polygons. - - - - - - - The above area markers and the build process supports priority assignment, so it is possible to use overlapping markers. The overlapped - area will be assigned the area of the highest priority marker. - - - - - - -
      - -
      - - Area Assignment in the PolyMesh - - - - - Each polygon in the PolyMesh has an area assignment that is inherited from the earlier in the build process. This is the value - that will be assigned to the polygon once it is added to the navigation mesh. At this point the polygons are pretty much fixed, so it isn't particularly - useful to assign the NullArea. But sometimes it is useful to perform some final area adjustements. For example, if you assigned an area only - to ensure proper polygon formation, and the area isn't needed for adjusting traversal cost in the navigation mesh, you can re-assign the area to - a default area. (I.e. Clean things up.) - - - - -
      - -
      - -
      - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/BuildProcess.aml b/critterai/doc/cainav/nmgen/BuildProcess.aml deleted file mode 100644 index 1097a1ad..00000000 --- a/critterai/doc/cainav/nmgen/BuildProcess.aml +++ /dev/null @@ -1,317 +0,0 @@ - - - - - - - - This topic covers the core process used by NMGen to create polygon data that will represent the navigation mesh surface. - There are many variations on the mesh generation process, but they all include these steps. - - - - The IncrementalBuilder extension implements this process. - - - - The high level process is as follows: - - - - - - - Voxelization - http://www.cs.sunysb.edu/~vislab/projects/volume/Papers/Voxel/index.html - _blank - : Create a solid heightfield from the source geometry representing obstructed space. - - - Generate Regions: Detect the upper surface of the solid heightfield and divide it up - into regions of contiguous spans. - - - Generate Contours: Detect the contours of the regions and form them into - - simple polygons - http://en.wikipedia.org/wiki/Polygon#Convexity_and_types_of_non-convexity - _blank - . - - - Generate Polygon Mesh: Sub-divide the contours into convex polygons. - - Generate Height Detail: - - Triangulate - http://mathworld.wolfram.com/Triangulation.html - _blank - the polygon mesh and add height detail. (Optional) - - - - - - -
      - - Voxelization - - - - - Core Class: T:org.critterai.nmgen.Heightfield - - - During voxelization the source geometry is abstracted into a heightfield which represents - obstructed space. Then some initial culling of un-walkable surfaces is performed. - - - - Each triangle in the source geometry is voxelized using conservative voxelization and - added to the field. Conservative voxelization is an algorithm that ensures the triangle surfaces - are completely encompassed by the the generated voxels. - - - - After voxelization, the solid heightfield contains spans that completely encompass the - surface of all polygons in the source geometry. - - - - - - -
      - -
      - - Region Generation - - - - - Core Class: T:org.critterai.nmgen.CompactHeightfield - - - - The goal of this stage is to further define what portion of the solid surface is - traversable, and to segregate the traversable areas into contiguous regions of spans - (surfaces) that can eventually be formed into simple polygons. - - - - The first step is to translate the solid heightfield into an open heightfield which - represents the potential traversable surfaces on top of the solid space. An open heightfield - represents the potential floor area on the surface of solid space. - - - - In the below example, the green area represents the floor defined by the open spans. - These correspond to the top of all traversable spans in the solid heightfield. Note that walls, - areas under the tables, and some thin areas such as the balcony banisters were culled during - the solid heightfield generation process. Some un-walkable areas such as table tops, the stair - banisters, and thin wall ledges still show as traversable at this point. - - - - - - Next, further culling of un-walkable spans occurs. At the end of the process, open spans - are only considered traversable if they pass the following tests: - - - - - The span is not too close to an obstruction. (Such as walls, furniture, etc.) - (WalkableRadius) - - The span has sufficient unobstructed space above its floor. - (Agents can legally walk on the span without colliding with objects above the span.) - (WalkableHeight) - - - - - Neighbor information is generated for all surviving open spans to help group them - together into true surface areas. The algorithm takes into account a maximum vertical step - threshold to determine which spans can connect. (WalkableStep) - This permits structures such as stairs, curbs, table tops, etc. to be properly taken into - account. For example, spans that make up different steps in a stairway will be connected - as neighbors. But spans on a table top will not be connected to spans that make - up the adjacent floor. - - - - Regions are generated using the neighbor information and the watershed algorithm. - Region size is optimized and island regions too small to be of use (e.g. table tops) - are culled. (MinRegionArea) - - - - The below example shows regions. Note that regions flow up the stairs, even though - the spans that make up stairways don't actually connect. Also note that the table tops, - stair banisters, and all other un-walkable surfaces that made it through the - solid heightfield generation process have been successfully culled. (Black indicates - culled spans.) - - - - - - At the end of this stage, the traversable surface is represented by regions of - connected spans. - - - - -
      - - -
      - - Contour Generation - - - - Core Class: T:org.critterai.nmgen.ContourSet - - - - The contours of the regions are 'walked', forming simple polygons. This is the - first step in the process of moving from voxel space back into vector space. - - - - First, highly detailed polygons are generated from the regions. - - - - - - Next, various algorithms are used to accomplish the following: - - - - - - Simplify the edges between adjacent polygons. (The portals between regions.) - - - - Simplify the border edges (Border edges are the contour edges that connect to - empty or obstructed space.) (EdgeMaxDeviation) - - - - Optimize the length of the border edges. (Borders that are too long can form - non-optimal triangles later in the process.) (MaxEdgeLength) - - - - - - This next example shows the contours after these algorithms have been run. - - - - - - At the end of this stage, the traversable surface is represented by simple polygons. - - - - -
      - -
      - - Convex Polygon Generation - - - - - Core Class: PolyMesh - - - - Many algorithms can only be used with convex polygons. So this step subdivides - the simple polygons that make up the contours into a mesh of convex polygons. - - - - - - - This is the mesh used for most pathfinding purposes. - - - - - - Below you can see that a mixture of concave polygons have been formed from the contours. - - - - - - At the end of this stage, the traversable surface is represented by a mesh of - convex polygons. - - - - -
      - -
      - - Height Detail Generation - - - - - Core Class: DetailMesh - - - - In the final stage, the convex polygon mesh is triangulated using - - Delaunay triangulation - http://en.wikipedia.org/wiki/Delaunay_triangulation - _blank - so that height detail can be added. Vertices are added internally and to the - edges of polygons to ensure the original geometry's surface is adequately followed. - (DetailSampleDistance and DetailMaxDeviation) - - - - - - - Technically, this is an optional step. The detail mesh is not required for - pathfinding. But certain queries will return more accurate height data if the - detail mesh is available. - - - - - - - - -
      - - - - T:org.critterai.nmbuild.IncrementalBuilder - T:org.critterai.nmgen.PolyMesh - T:org.critterai.nmgen.PolyMeshDetail - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/CompileInput.aml b/critterai/doc/cainav/nmgen/CompileInput.aml deleted file mode 100644 index 7426dcd2..00000000 --- a/critterai/doc/cainav/nmgen/CompileInput.aml +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - The input compile step involves gathering together all the resources needed to build the - navigation mesh. This may be as simple as compiling the source geometry into the correct - format, or it may be very complex, such as gathering off-mesh connections, mapping triangle type - to area, gathering custom processors, etc. - - - - The results of this step are the InputGeometry, ProcessorSet, - and ConnectionSet objects. (Though finalization of the connection set can be delayed to a later step.) - - - - There is no standard implementation for compiling the input since the process is specific to the - design environment. In Unity the input is gathered from various project assets and scene objects, - such as mesh filters. In other environments it might be gathered directly from Maya or 3DSMax data. - - - - -
      - - Input Geometry - - - - - The InputGeometry object consists of standard triangle mesh data (vertices and indices) with additional triangle area assignment. It is - derived from the source geometry. - - - - The T:org.critterai.nmbuild.InputGeometryCompiler and - T:org.critterai.nmbuild.InputGeometryBuilder classes are used - to create the input geometry object. - - - - Each triangle in the input geometry is assigned an area based on surface type. Usually, triangles are assigned a default area, - such as F:org.critterai.nmgen.NMGen.MaxArea, then special triangles - are assigned special areas as needed. For example, 'meadow' and 'sidewalk' triangles may be the default area, while - 'water' and 'swamp' triangles are assigned to other areas. Assigning areas during the build process ensures that - polygons are properly formed for each type of surface. - - - - - // Example: Creating a simple input geometry object. - - // Where 'mesh' is a TriangleMesh object containing all of the input triangles. - - // Create an area buffer that assigns the default area id to all triangles. - byte[] areas = NMGen.CreateDefaultAreaBuffer(mesh.triCount); - - // Create the builder. - // All triangles with a slope over 45.5f will be re-assigned to NMGen.NullArea. - InputGeometryBuilder gbuilder = InputGeometryBuilder.Create(mesh, areas, 45.5f); - - // Build in a single step. - gbuilder.BuildAll(); - - // Get the result. - InputGeometry geom = gbuilder.Result; - - - - - The T:org.critterai.nmbuild.InputGeometryCompiler class can be used to - combine multiple triangle meshes into a single triangle mesh, including area assignment. - - - - -
      - -
      - - ProcessorSet - - - - - The ProcessorSet contains INMGenProcessor objects used to add special behavior to the - main build step. A processor may do something simple, such as applying default flags - to all polygons (T:org.critterai.nmbuild.ApplyPolygonFlags), or something - complex such as evaluating heightfield intermediates in order to auto-generate off-mesh connections. - - - - - // Example: Creating a processor set. - - // There is a standard set of processors needed for almost every build. - myProccessorList.Add(ProcessorSet.GetStandard(ProcessorSet.StandardOptions)); - - // You can also add other processors, including custom processors of your own. - myProccessorList.Add(myCustomProcessor); - myProcessorList.Add(myOtherCustomProcessor); - - // Create the set. - ProcessorSet processors = ProcessorSet.Create(myProcessorList.ToArray()); - - - - How these processors are used is described further in topic. - - - -
      - -
      - - ConnectionSet - - - - - The ConnectionSet defines the off-mesh connections that will be added to the navigation mesh. In some cases - they are fully defined during the input build process. In other cases they are generated by custom processor's - later in the build process. - - - - The T:org.critterai.nmbuild.ConnectionSetCompiler can be used to dynamically compile - connections for eventual inclusion in the connection set. - - - - -
      - - - - T:org.critterai.nmbuild.InputGeometry - T:org.critterai.nmbuild.ProcessorSet - T:org.critterai.nmbuild.ConnectionSet - T:org.critterai.nmbuild.IncrementalBuilder - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/CreateNavmesh.aml b/critterai/doc/cainav/nmgen/CreateNavmesh.aml deleted file mode 100644 index 83bda870..00000000 --- a/critterai/doc/cainav/nmgen/CreateNavmesh.aml +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - The final step in the NMGen build process is to create the navigation mesh. As a minimum you must have PolyMesh data. - DetailMesh and ConnectionSet data are optional. - - - - See the topic for the general creation process. This topic will cover two - helpful extensions. - - - - -
      - - Creating Tile Data - - - - - Before you can create a navigation mesh you need to convert your source data into tile data. There are various ways of doing this. - - - - One method is to use the - - M:org.critterai.nmbuild.NMBuild.GetBuildData(org.critterai.nmgen.BuildContext,System.Int32,System.Int32,org.critterai.nmgen.PolyMeshData,org.critterai.nmgen.PolyMeshDetailData,org.critterai.nmbuild.ConnectionSet,System.Boolean) - utility method. - - - - // Example: Using the tile build data utility method. - - BuildContext logger = new BuildContext(); - - NavmeshTileBuildData tbd = NMBuild.GetBuildData( - logger - tileX, tileZ // The tile location. (0, 0) for single tile meshes. - , polyData // A PolyMeshData object. - , detailData // Optional PolyMeshDetailData object. - , connections // Optional ConnectionSet object. - , true); - - if (tbd == null) - { - // Perform error handling. - // The build context will contain error messages. - } - - // Use the build data to create the navigation mesh... - - - - Another method is to use the the T:org.critterai.nmbuild.TileBuildTask class to create the tile data. This method - is especially useful if you are building a multi-tile navigation mesh or performing background builds. - - - - // Example: Using the tile build task. - - TileBuildTask task = TileBuildTask.Create( - tileX, tileZ // The tile location. (0, 0) for single tile meshes. - , polyData // A PolyMeshData object. - , detailData // Optional PolyMeshDetailData object. - , connections // Optional ConnectionSet object. - , false // Is the task tread-safe? Not applicable in this case. - , 0); // Task priority. Not applicable in this case. - - task.Run(); - - if (task.TaskState == BuildTaskState.Aborted) - { - // Perform error handling. - // Check task messages for details. - } - - // Get the tile assets. - TileBuildAssets tassets = task.Result; - - // Use the tile data to build the navigation mesh... - - - - -
      - -
      - - Creating the Navigation Mesh - - - - Once you have the tile data you can use one of two methods to create the final navigation mesh. - - - // Example: Create a single tile mesh. - - // Where 'buildData' is a NavmeshTileBuildData object. - - Navmesh navmesh; - NavStatus status = Navmesh.Create(buildData, out nm))); - - if ((status & NavStatus.Success) == 0) - { - // Perform error handling. - } - - // Use the navitgation mesh... - - - - - - // Example: Create an empty mesh, then add tiles. - - // Where 'tiles' is a list containing NavmeshTileData objects. - - NavmeshParams nconfig = new NavmeshParams(meshOrigin - , tileSetWidth, tileSetDepth - , tiles.Count - , maxPolysPerTile); - - Navmesh navmesh; - - NavStatus status = Navmesh.Create(nconfig, out navmesh) - - if ((status & NavStatus.Success) == 0) - { - // Perform error handling. - } - - // Add the tiles to the navigation mesh. - foreach (NavmeshTileData tile in tiles) - { - // Note: Allowing the navigation mesh to assign the tile reference. - uint trash; - navmesh.AddTile(tile, Navmesh.NullTile, out trash); - } - - // Use the navigation mesh. - - - - -
      - - - - T:org.critterai.nav.Navmesh - T:org.critterai.nav.NavmeshParams - T:org.critterai.nav.NavmeshTileBuildData - T:org.critterai.nav.NavmeshTileData - T:org.critterai.nmbuild.TileBuildTask - T:org.critterai.nmbuild.TileBuildAssets - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/HeightfieldIntro.aml b/critterai/doc/cainav/nmgen/HeightfieldIntro.aml deleted file mode 100644 index f549bd56..00000000 --- a/critterai/doc/cainav/nmgen/HeightfieldIntro.aml +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - In order to use the advanced navigation mesh build features you will need to understand the core NMGen build process, - and in order to understand that process you'll need to understand heightfields. There are two types of heightfields: - - voxel - http://en.wikipedia.org/wiki/Voxel - _blank - - field, and vertex fields. Voxel fields include - T:org.critterai.nmgen.Heightfield and - T:org.critterai.nmgen.CompactHeightfield objects. - Vertext fields include T:org.critterai.nmgen.ContourSet and - PolyMesh objects. - - - - -
      - - Basic Heightfield Structure - - - - - Consider an AABB at an arbitrary location in - - euclidean space - http://en.wikipedia.org/wiki/Euclidean_space - _blank - . Its bounds are defined by a minimum and maximum vertex. - - - - - - Now slice the box into vertical columns of uniform width and depth (XZCellSize). The columns make up a grid. - - - - - - Now slice the columns in uniform increments up the height axis (YCellSize), - breaking the columns into small axis-aligned boxes. The boxes represent a voxel field. - The vertices at the eight corners of the boxes represent a vertex field. - - - - - - Vertex fields are fairly easy to understand. They are simply a way of representing vertices laid out in a grid pattern. - But voxel fields require a bit more explanation... - - - - -
      - -
      - - The Solid Heightfield - - - - - In this documentation, the term voxel is usually discarded in favor of - span because spans are how voxel information is compressed by NMGen objects. - - - - Consider a column of voxels. The area defined by each voxel is either solid, - representing obstructed space, or open, representing space that does not contain any - obstructions. - - - - - - We merge the contiguous solid voxels within the column and we get a span of solid voxels. - - - - - - These solid spans, represented by the - T:org.critterai.nmgen.HeightfieldSpan structure, - are combined to form a - T:org.critterai.nmgen.Heightfield - representing obstructed space. - - - - - - -
      - -
      - - The Open Compact Heightfield - - - - - We don't only care about solid space. Many algorithms operate on the space above solid spans. - For navigation mesh generation this is the most important part of solid space, its upper surface. - Open spans represent this space. - - - - It is important to note that this is not a simple inversion of the solid space. If an - open heightfield column does not contain any solid spans, then it doesn't have any open spans. - Also, the area below the lowest solid span is ignored. An open span extends from the top of a solid - span to the bottom of the next higher solid span in the column. (Or to "infinity" if there - is no higher solid span.) - - - - - - - Though it may not be obvious at first glance, this example is the open space representation of the previous example. - Three open spans are fully visualized. - - - - - - - - - The open spans, represented by the T:org.critterai.nmgen.CompactSpan structure, - are combined to form a T:org.critterai.nmgen.CompactHeightfield representing open space. - - - - -
      - - - - T:org.critterai.nmgen.Heightfield - T:org.critterai.nmgen.CompactHeightfield - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/IncrementalBuilder.aml b/critterai/doc/cainav/nmgen/IncrementalBuilder.aml deleted file mode 100644 index a7158550..00000000 --- a/critterai/doc/cainav/nmgen/IncrementalBuilder.aml +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - - - The IncrementalBuilder implements a flexible build process that can be used at - design time to create PolyMesh and DetailMesh objects. INMGenProcessor's - are used to customize the process for almost any need. - - - - - - - This builder is not suitable for use at run-time since it is designed for flexibility - rather than high performance. - - - - There are a lot of configuration settings to deal with during the build process. See the NMGenParams - documentation for details, including recommendations. - - - - - - Only one builder is needed if the navigation mesh will contain only a single tile. Multi-tile meshes require - one builder for each tile. (Builders are single use.) - - - - - // Example: A simple NMGen build. - - // Where 'mesh' is a TriangleMesh object containing all of the input triangles - // and 'config' is a NMGenParams object containing the configuration. - - // Create an input geometry object. - byte[] areas = NMGen.CreateDefaultAreaBuffer(mesh.triCount); - InputGeometryBuilder gbuilder = InputGeometryBuilder.Create(mesh, areas, 45.5f); - gbuilder.BuildAll(); - InputGeometry geom = gbuilder.Result; - - // Create the incremental builder. - NMGenAssetFlag resultFlags = NMGenAssetFlag.PolyMesh | NMGenAssetFlag.DetailMesh; - IncrementalBuilder builder = IncrementalBuilder.Create(config - , resultFlags - , geom - , ProcessorSet.CreateStandard(ProcessorSet.StandardOptions)); - - // Perform the build and check the result. - builder.BuildAll(); - - switch (builder.State) - { - case NMGenState.Aborted: - - // Handle the error. - // Check builder messages for details. - - case NMGenState.Complete: - - NMGenAssets result = builder.Result; - - // Use the poly and detail mesh data. - - case NMGenState.NoResult: - - // No result was produced. - // Unexpected for single-tile builds. Not uncommon for multi-tile builds. - // Check builder messages for details. - } - - - - - -
      - - The Process - - - - - The incremental builder follows the process described by topic. - - - - - - -
      - -
      - - The Polygon Mesh - - - - - The IncrementalBuilder's main output is a PolyMesh object. - The polygon mesh is made up of convex polygons with between three and - F:org.critterai.nmgen.NMGen.MaxAllowedVertsPerPoly - vertices. Each polygon includes edge link, area, flag data. - - - - Polygons may overlap, based on the value of - P:org.critterai.nmgen.NMGenParams.WalkableHeight used during the build. - - - - At the end of the build process all polygons should have at least one flag set. Usually - F:org.critterai.nmbuild.NMBuild.DefaultFlag. - - - - All polygons will have a non-zero area id. (<= F:org.critterai.nmgen.NMGen.MaxArea) - - - - - - -
      - -
      - - The Detail Mesh - - - - An common optional output of the IncrementalBuilder is a DetailMesh object. - - - Pathfinding only uses the PolyMesh. For storage efficiency and speed the polygon mesh doesn't have a lot of height accuracy. - But some secondary navigation features require more accurate height data. The detail mesh provides the extra detail. - - - - The detail mesh consists of sub-meshes, one for each polygon in the polygon mesh. Each sub-mesh is a - triangle mesh that contains all the vertices of its associated polygon, plus additional vertices - that provide the extra height detail. - - - - -
      - -
      - - The NMGen Processors - - - - The NMGen processors provided by the ProcessorSet are what give the incremental builder its flexibility and power. - Without any processors, only a very simple polygon mesh can be created. - - Processors are called during the post-processor step of each stage, in ascending priority. A processor may perform processing - during a single stage or multiple stages. - - - - Any oject that implements INMGenProcessor can act as a processor. The - T:org.critterai.nmbuild.NMGenProcessor abstract class provides a good base to start from. - - - Two common uses for processors include polygon area and flag assignment. - -
      - - Area Assignment - - - - - Area assignment can happen via the InputGeometry object. But sometimes that isn't convenient or possible. Another choice - is to mark areas into the compact heightfield. You can use the T:org.critterai.nmbuild.AreaBoxMarker, - T:org.critterai.nmbuild.AreaCylinderMarker, and - T:org.critterai.nmbuild.AreaConvexMarker processors to do this. - - - - Because processors are prioritized, area markers can overwrite each other in useful ways. For example, lets say you have a swamp area with - a dry island contained within it. The swamp area needs to be assigned one area while the island needs to be a assigned a different area. - If you mark the swamp, the island will be included. This can't be helped since all markers are convex. But by marking the island with a higher - priority marker, it will be assigned the proper area. - - - - Another powerful use of area markers is applying F:org.critterai.nmgen.NMGen.NullArea. - Sometimes the build process will create polygons in areas you don't like. For example, there may be clutter on the ground that can technically - be walked across, but looks bad when it is. If you mark the area with F:org.critterai.nmgen.NMGen.NullArea, - then the area will be excluded from the final polygon mesh. - - - - -
      - -
      - - Polygon Flag Assignment - - - - - Polygon flags can be managed entirely in the Navmesh object. But sometimes the flags are best assigned to the PolyMesh - during the build process. For example, you may want to assign the 'swim' flag to all 'water' area polygons. - - - - The T:org.critterai.nmbuild.ApplyPolygonFlags processor can be used to add flags to all polygons. - - - - The T:org.critterai.nmbuild.AreaFlagMapper processor can be used to add flags to polygons based on - the area id of each polygon. - - - - -
      - -
      - -
      - - - - T:org.critterai.nmbuild.IncrementalBuilder - T:org.critterai.nmbuild.NMGenAssets - T:org.critterai.nmgen.NMGenParams - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/NMGen.aml b/critterai/doc/cainav/nmgen/NMGen.aml deleted file mode 100644 index 25f7c97c..00000000 --- a/critterai/doc/cainav/nmgen/NMGen.aml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - The purpose of NMGen is to generate navigation meshes from arbitrary source geometry. Features fall into two categories: - Core and 'standard build'. - - - - The core features are located in the N:org.critterai.nmgen namespace and involve creating - simplified polygon mesh data from detailed triangle-based source geometry. You can code your own build process from scratch using these features, but it will - require a significant amount of work and detailed knowlege of all aspects of the process. - - - - The standard build process implements a flexible, extendable build process suitable for use at design time. It takes care of many of the mundane - details for you. Its features are implemented in the following namespaces: - - - Common extentions: N:org.critterai.nmbuild - - Unity extensions: N:org.critterai.nmbuild.u3d.editor - - The standard build process has three main steps which will be covered in detail throughout the rest of this section. - - - - Compile the input. - The NMGen Build. (Produces the polygon meshes.) - Create the navigation mesh. - - - - - - - CAINav uses the OpenGL coordinate system. - - - - - -
      - - The Standard Build Process - - - - - - - -
      - - - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/nmgen/TiledMeshes.aml b/critterai/doc/cainav/nmgen/TiledMeshes.aml deleted file mode 100644 index 22982846..00000000 --- a/critterai/doc/cainav/nmgen/TiledMeshes.aml +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - A multi-tile navigation mesh consists of a group of square tiles layed out in a grid on the xz-plane. Each tile in the mesh consists of its - own polygon mesh, detail mesh, and off-mesh connection data. The tiles are linked together when added to the navigation mesh to form - the full navigation mesh. - - - This topic covers the extra steps necessary to create a multi-tile navigation mesh. - - - -
      - - The Multi-Tile Build Process - - - - - The process for building multi-tile navigation meshes is very similar to building a single-tile mesh. The main difference is that you need to - repeat the IncrementalBuilder and tile build steps for each tile, then combine the result into the final navigation mesh. You also have a new - input data class: TileSetDefinition. This class combines the InputGeometry and some configuration settings to define - the tile set. - - - - // Example: A simple multi-tile navigation mesh build. - - // Where 'geom' is an InputGeometry object and 'pset' is a ProcessorSet object. - - NMGenParams config = new NMGenParams(); - - // Load the various standard config settings based on your needs. - // E.g. cell size and agent settings. - - // ... - - // Then set the tile settings. - // The border size must be greater than zero, otherwise the tiles won't connect - // properly when added to the navigation mesh. You should almost always use - // the standard border size. - - config.TileSize = 512; - config.BorderSize = NMGenParams.DeriveBorderSize(config); // Standard border size. - - // Create the tile set definition. - TileSetDefinition tdef = - TileSetDefinition.Create(geom.BoundsMin, geom.BoundsMax, config, geom); - - NMGenAssetFlag resultFlags = NMGenAssetFlag.PolyMesh | NMGenAssetFlag.DetailMesh; - - List<TileBuildAssets> tiles = new List<TileBuildAssets>(); - int maxPolys = 0; // Need to keep track of maximum polys in a tile. - - // Interate over all tiles and build. - for (int tx = 0; tx < tdef.Width; tx++) - { - for (int tz = 0; tz < tdef.Depth; tz++) - { - IncrementalBuilder builder = - IncrementalBuilder.Create(tx, tz, resultFlags, tdef, pset); - - // Perform the build and check the result. - builder.BuildAll(); - - switch (builder.State) - { - case NMGenState.Aborted: - - // Handle the error. - // Check builder messages for details. - - case NMGenState.NoResult: - - // No result was produced. This is not uncommon for multi-tile builds. - // E.g. There may be no geometry at the location. - - continue; - } - - // Completed with a result. Build the tile data. - - NMGenAssets assets = builder.Result; - - // You can build the tile manually, but the tile build task will take - // care of standard error handling. - - TileBuildTask task = TileBuildTask.Create(tx, tz - , assets.PolyMesh.GetData(false), assets.DetailMesh.GetData(false) - , ConnectionSet.CreateEmpty() // Or use your connection set. - , false, 0); - - task.Run(); - - if (task.TaskState == BuildTaskState.Aborted) - { - // Perform error handling. - // Check task messages for details. - } - - TileBuildAssets tassets = task.Result; - - // Store for later. - tiles.Add(tassets); - - maxPolys = System.Math.Max(maxPolys, tassets.PolyCount); - } - - // Create an empty navigation mesh large enough to hold all tiles - // that produced a result. - - NavmeshParams nconfig = new NavmeshParams(tdef.BoundsMin - , tdef.Width, tdef.Depth - , tiles.Count, maxPolys); - - Navmesh navmesh; - - if ((Navmesh.Create(nconfig, out navmesh) & NavStatus.Sucess) == 0) - { - // Perform error handling. - } - - // Add the tiles to the navigation mesh. - foreach (TileBuildAssets tile in tiles) - { - // Note: Allowing the navigation mesh to assign the tile reference. - uint trash; - navmesh.AddTile(tile.Tile, Navmesh.NullTile, out trash); - } - - // The navigation mesh is ready to use. - // You will usually serialize it for later use. - } - - - - -
      - -
      - - Notes - - - - - The tile size should usually be between 500 and 1000. A tile size that is too small can result in extra, - unnecessary polygons and less than optimal pathfinding. A value that is too large can be result in memory and - performance issues during the build process. - In general, pick the largest size that also results in a good tile layout along the x and z axes. (You want to avoid creation - of thin tiles along the upper bounds of the navigation mesh.) - - - - You can use a single ConnectionSet for the entire build. The build process will add the appropriate - connections to each tile. - - - - Off-mesh connections can only be formed between a tile and its immediate neighbors. For example, an off-mesh connection - can't start in tile (5, 8) and end in (5, 10) since it would skip over tile (5, 9). So keep the length of off-mesh - connections less than (TileSize * XZCellSize). - - - - -
      - - - - T:org.critterai.nmbuild.IncrementalBuilder - T:org.critterai.nmgen.NMGenParams - T:org.critterai.nmgen.NMGenTileParams - T:org.critterai.nmbuild.TileSetDefinition - T:org.critterai.nmbuild.TileBuildTask - T:org.critterai.nmbuild.TileBuildAssets - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/u3d/AdvanceBuildType.aml b/critterai/doc/cainav/u3d/AdvanceBuildType.aml deleted file mode 100644 index 1cce1fd3..00000000 --- a/critterai/doc/cainav/u3d/AdvanceBuildType.aml +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - The T:NavmeshBuild asset's advanced build type serves three main purposes: - - - - Provides extra debug information to help you figure out problems, or better set the configuration. - Allows a partial rebuilds of multi-tiled navigation meshes. - Performs background processing for long builds. - - - - The advanced build uses the Navmesh Build Manager editor window that can be opened via the CritterAI menu. - - - - The main drawback of the advanced build is that things can get a bit complex. With lots of extra options you need to know what you are doing. - - - - The advanced build breaks the build down into four steps: - - - - Compile the input. - Set and accept the NMGen Configuration - Build and preview the result. - Bake the result to the target. - - - - While the standard build handles all these steps in one click, they are all separate steps in the advanced build. - - - - - - - The advanced build features are currently in an experimental state. The Unity editor can be finicky when it comes to running background processes. - Also, exception handling is not fully tested. - - - - Make sure you save your scenes frequency when using the advanced build features. - - - - - - -
      - - Limitations & Gotchas - - - - - Because the advanced build lets you go back and forth between the build and the scene while the build is in a partially complete state, there are some things you need to be - careful of. - - - - The input is compiled manually. If you make a change to the scene in the middle of a build, you will need to recompile the input before the build will - pick up the changes. - - - - Certain configuration settings are locked in once you reach the builder stage. If you want to change these settings after you've started the build you'll need to - re-initialize the builder, throwing away any unbaked results. - - - - If you chose to base a new build on the current target's navigation mesh then you will be automatically locked into certain configutration settings from the target. - This includes the target's origin. Any new scene geometry below the origin will not be included in the new build. - - - - The input data cannot survive a Unity Editor reset. A Unity Editor reset will occur, for example, when scripts are recompiled. If an editor reset occurs - during a build the build will enter a recovery state requiring manual intervention. - - - - Be careful when switching scenes while performing an advanced build. If you re-compile the input, it will gather the input from the currently open scene. - - - - The advanced builder stores intermediate build data in the T:NavmeshBuild asset. This data is not cleared when - you bake the mesh. You must exit the build using the Exit Build button. Otherwise, the next time you interact with - the build you'll start with the cached data. The primary reason for this behavior is to prevent the loss of build data in case of an accidental Unity Editor reset. - But it is also a useful behavior if you happen to want to return to a partially complete build at a later time. - - - - Don't forget to bake your build result. Baking to the target is never automatic. - - - - -
      - -
      - - Input Compile - - - - - The first step in the advanced build is the input compile. Once you run the compile you'll get useful debug information along with visualization options. - - - - - - - - You can come back and re-compile the input at any point in the build process. This is especially helpful if you are tweaking the scene and partially - rebuilding a multi-tile navigation mesh. - - - - -
      - -
      - - Configuration - - - - - During the configuration step you set the NMGen configuration that same as you would during a standard build. - - - - - - - - Once the configuration is set, you can start a new build from scratch using the From Scratch button. If the target contains a - supported multi-tile navigation mesh, then you can initialize the build from the target using the Based on Target button. This will - load the existing mesh's configuration and tile data into the builder so you can perform a partial rebuild. - - - - -
      - -
      - - The Builder - - - - - - - - There are two types of builders, one for single-tile and one for multi-tile meshes. This section covers the multi-tile version. - The single-tile version is simple, so it is not covered here. - - - - - - The builder allows you to build, tweak, and rebuild your navigation mesh as needed. Once satisfied you can bake the result to the build target. - Various debug visualizations are available to help you see what is going on with the build. Some visualizations are only available in zone mode. - - - - - - - - - - - Be careful. Some of the visualizations, especially the Input Geometry visualization, are framerate killers. - - - - - - It is possible to operate on only part of a navigation mesh by entering zone mode. You can do this by clicking a tile and adjusting - the Zone Size to get the coverage you desire. You can set the zone size to zero if you only want to select a single tile. - Exit zone mode by clicking on the selected tile. - - - - Builds are performed in the background with the progress shown in the tile grid. Be aware that the background builder is shared by - all build operations in a priority queued manner. It also limits the number of concurrent operations. So if you are building multiple - meshes at once, or perform an input compile in the middle of an in-progress build, don't be surprise when some operations have to wait for - others to complete. Input compiles have the highest priority, followed by zone builds. 'Build All' builds have the lowest priority. - - - - -
      - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/u3d/InputBuild.aml b/critterai/doc/cainav/u3d/InputBuild.aml deleted file mode 100644 index e81b68b4..00000000 --- a/critterai/doc/cainav/u3d/InputBuild.aml +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - The Unity NMGen build process is pretty much the same as the standard build process describe by - . The main difference is in the input - compile process. - - - - The input compile process is manged by an input builder that is modified by the scene query and input processors assigned to the - T:NavmeshBuild asset. - - - - -
      - - The Input Compile Process - - - - - The input compile process is managed by the input builder. The the only thing the builder does is manage - the input processors. At each step it makes sure all the necessary build assets are ready for use and calls the - processors in ascending priority. A processor can be active during one step or multiple steps. For example, - the T:MeshCompiler loads MeshFilter components from the scene during the - load step, then triangulates them during the compile step. - - - - - - -
      - - Load Components - - - - - The scene query asset is used to determine which components in the scene will be included in the input compile. Any ScritableObject that - implements the T:org.critterai.nmbuild.u3d.editor.ISceneQuery interface can be used. For example, - if you want the build to gather scene components based on tags, then you'll use the T:TagSceneQuery asset. - If no scene query is provided, then the the query will be global. (E.g. All MeshFitlers in the scene, all Terrains in the scene, etc.) - - - - During the load component step, each input processor uses the scene query to load the components that it cares about. For example, - the T:MeshCompiler will load all MeshFilters and the T:TerrainCompiler will - load the Terrain component. - - - - -
      - -
      - - Filter Components - - - - - During the filter component step the input processors have a chance to remove components from the input compile. The component loaders are generally dumb. - They load everything the scene query let's them load. In this step, other processors can refine the result. For example, a - T:MeshInputFilter can be used to remove MeshFilter's that reference all 'door' meshes. Or the - T:StaticFilter can be used to remove all components not marked as static. - - - - -
      - -
      - - Apply Area Modifiers - - - - - At this point all components that will be compiled have been gathered. During this step input processors can assign custom areas to each - component. The assignments will be used during the compile step. For example, the T:MeshAreaDef - can assign the area 21 to all MeshFilters that reference swamp and marsh meshes. During the compile step the - T:MeshCompiler will then assign 21 to all triangles generated from the meshes. - - - - - - - F:org.critterai.nmgen.NMGen.MaxArea will be assigned by default. You can use the - T:DefaultAreaDef asset to assign a different area as the default. - - - - - - -
      - -
      - - Compile Input - - - - - During the compile input step the input processors will compile everything needed to create the objects required by the rest of the NMGen build process. - (I.e. The InputGeometry, ProcessorSet, and ConnectionSet objects.) MeshFilter and Terrain components will - be triangulated, and off-mesh connections and NMGen processors created. - - - - -
      - -
      - - Post-Process - - - - - At this point all data needed to create the final input objects has been compiled. During the post-process step the input processors are - given the oportunity to make final adjustmwents to the data before it is locked down in the immutable InputGeometry, ProcessorSet, - and ConnectionSet objects. - - - - -
      - -
      - -
      - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/u3d/U3DGettingStarted.aml b/critterai/doc/cainav/u3d/U3DGettingStarted.aml deleted file mode 100644 index 92eb4341..00000000 --- a/critterai/doc/cainav/u3d/U3DGettingStarted.aml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - CAINav provides various extensions that make life easier in Unity. This section covers topcis - that will help you get going. - - - - The NMGen extensions provide designer friendly features that can be used by non-coders to create complex navigation meshes. - There are various extension points that allow coders to easily extend the build process even further. - - - - -
      - - Getting CAINav Up and Running - - - - - To get started you first need to get the CAINav package into your project: - - - - - - - Download - http://code.google.com/p/critterai/downloads/list - _blank - and extract the contents of the CAINav distribution. - - - - Locate the Unity Pro package: cai-nav-pro-x.x.x.unitypackage. (Where x.x.x is the version number.) - - - - Import the package into your project. (Assets->Import Package... from the menu bar.) - - - - - The package will add the following files to your project: - - - - The core plug-in libraries to the project's plugin - folder. - - The core libraries to the CAI folder. These give you script level - access to the core CAINav features. - - The Unity extension libraries to the CAI and - CAI/Editor folders. These provide all the Unity extensions. - - - - - The package also adds a CritterAI menu from which many of the features can be accessed. - - - - -
      - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/u3d/UnityBuildConfig.aml b/critterai/doc/cainav/u3d/UnityBuildConfig.aml deleted file mode 100644 index ff82116d..00000000 --- a/critterai/doc/cainav/u3d/UnityBuildConfig.aml +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - This topic covers some of the Unity specfic configuration settings found in the - T:NavmeshBuild asset. - - - - - - - See the NMGenParams documentation for information on the standard configuration settings. - - - - - - -
      - - Controls and Target Assignment - - - - - The upper portion of the inspector contains the main build controls and build target. - - - - - - - - The bake target is the asset that will get the result of the build. (The navigation mesh.) Any ScritableObject that - implements the T:org.critterai.nav.u3d.INavmeshData interface can be used. The normal - target will be a T:CAIBakedNavmesh asset. Note that this is a navigation asset, not an NMGen asset, - so it can be distributed as part of the project compile and be referenced by scene components. - - - - There are two types of builds. A standard build is performed directly from the inspector and will run a foreground build of the entire - navigation mesh. (Can't do anything else in the Unity editor until the build is complete.) The advanced build provides extra debug options, - background build capabilities, and the ability to partially rebuild multi-tile navigation meshes. The advanced build uses a special - editor window for the build. - - - - The Log Mesh State button will log the current state of the build target to the console. (Polygon count, bounds, etc.) - - - - The Build & Bake button will run a full build and bake of the navigation mesh in the foreground using the current scene as the input source. - (There will be a warning at the top of the inspector if the current scene is not the same as the last input scene.) - - - - If Trace is enabled, then detailed trace messages will be sent to the console. This is useful for debugging the build. - - - - -
      - -
      - - NMGen Configuration - - - - - - - - This section will not be avaiable if the build type is set to advanced. - - - - - - The configuration section contains the standard NMGen confiugration settings plus a some Unity specific options. - - - - - - - - The very first NMGen configuration settings you should take a look at are the Agent Settings. - Most other settings are derived, at least in part, from these. Unlike the NMGenParams core class, these agent settings are in world - units, not cell units. Set the values based on your agent maximums. (Maximum height, maximum radius, etc.) - - - - The next settings you'll want to take a look at are the Resolution and Tile Settings. You can derive these yourself with the help of - the NMGenParams documentation. But if you've already set up the scene you can use the Derive button to get a good starting point. - The values will be derived based on a combination of the agent settings and bounds of the input geometry. - - - - - - - A Tile Size of zero results in a single tile mesh. - - - - - - There are various toggle options in the Advanced configuration section. These will automatically add NMGen processors to the build as follows: - - - - Ledges Not Walkable -> T:org.critterai.nmbuild.FilterLedgeSpans - Low Height Not Walkable -> T:org.critterai.nmbuild.FilterLowHeightSpans - Low Obstacles Walkable -> T:org.critterai.nmbuild.LowObstaclesWalkable - Apply Poly Flag -> T:org.critterai.nmbuild.ApplyPolygonFlags (Flag: 0x01) - - - - If you don't need a lot of height detail in your navigation mesh you can uncheck the Include Detail Mesh option. This will - make the final navigation mesh more memory efficient. - - - - The Clean button can be used to round values to more reasonable values. (E.g. 0.2929384839 to 0.29) - - - - The Reset button will reset the NMGen configuration to its original default values. - - - - -
      - -
      - - Input Configuration - - - - - The input configuration contains the scene query and processor asset assignments. - - - - - - - - The assets assigned in this section can be created using menu items founds under CritterAI -> Create NMGen Assets. Note that some - assets are effectively singletons with no configuration. In such cases there is no need to create more than one per project; and the inspector won't let - you add them twice to the same build. - - - - It is perfectly fine to share scene query and input processors between multiple T:NavmeshBuild assets. - - - - The most common scene query is T:TagSceneQuery. The scene query is optional. If none is provided then - the search will be global. E.g. All MeshFilters in the scene, all terrains in the scene, etc. - - - - There must be at least one input processor for the build. For simple builds this is usually a compiler. The most commonly used compiler is - T:MeshCompiler. You can add as many processors as you wish. The processors will be run in - ascending priority. This is especially useful for area assignment since it allows higher priority areas to overwrite lower priority areas. - - - - The inspector won't let you add the the same input processor asset to a build twice. - - - - The Auto-Clean option is used to automatically clean up invalid triangles in the input geometry. Sometimes modeling programs can let invalid triangles slip in; - triangles that are no problem for the renderer but cause problems for NMGen. For example, triangles that contain the same vertex twice will be removed. - - - - -
      - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/doc/cainav/u3d/UnityNMGen.aml b/critterai/doc/cainav/u3d/UnityNMGen.aml deleted file mode 100644 index c21313aa..00000000 --- a/critterai/doc/cainav/u3d/UnityNMGen.aml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - The NMGen ease-of-use extensions for Unity provide GUI-level access to almost all of the NMGen features. You can build navigation meshes - with a single click. Or you can build, tweek, and rebuild selected zones of navigations meshes using advanced GUI features. - - - - All NMGen assets and support code are 'editor only'. So they have zero impact on scene size and are not included in the Unity project build. - (No data or code bloat.) The only impact on the scene will be if you need to create custom scene for things like off-mesh connections - and area markers. - - - - The Unity NMGen build process is pretty much the same as the standard build process describe by - . - The Unity extensions take care of gathering scene components and compiling them into input data, and provide ways to adjust the build via GUI - editors rather than requiring you to code things. - - - - -
      - - The Main NMGen Build Assets - - - - - As noted above, the NMGen build process and all associated assets are implemented as project assets, not scene components. The only time you will need - NMGen specific components in a scene is if you need to manually annotate something special that you want to include in the build. - (E.g. Off-mesh connections.) The below diagram shows the main assets and how they are related from an input/output perspective. - - - - - - - - The central asset is the T:NavmeshBuild asset. It defines the build configuration and holds all intermediate - build data created during the build. - - - - The build uses a scene query asset to determine which scene components will be included in the build. Any ScritableObject that - implements the T:org.critterai.nmbuild.u3d.editor.ISceneQuery interface can be used. For example, - if you want the build to gather scene components based on tags, then you'll use the T:TagSceneQuery asset. - - - - Input processors do the heavy lifting such as triangulating MeshFilter and Terrain components, adding INMGenProcessor objects to the build, etc. - Any ScriptableObject that implements the T:org.critterai.nmbuild.u3d.editor.IInputBuildProcessor interface can be used. - - - - The bake target is the asset that will get the result of the build. (The navigation mesh.) Any ScritableObject that - implements the T:org.critterai.nav.u3d.INavmeshData interface can be used. The normal - target will be a T:CAIBakedNavmesh asset. Note that this is a navigation asset, not an NMGen asset, - so it can be distributed as part of the project compile and be referenced by scene components. - - - - -
      - -
      - - The NavmeshBuild Asset - - - - - At the core of the Unity NMGen build process is the T:NavmeshBuild asset. It is created using one of the - CritterAI->Create NMGenAsset->Navmesh Build menu items, usually the Standard option. Once added to the project you'll be presented with - the following inspector. - - - - - - - - The upper section of the inspector contains the primary build controls and build target assignment. Since it is possible to reassign the target - you can use a single configuration to build any number of navigation meshes. Just reassign the target, open the target's input scene, and build. - - - - The center section contains the NMGen configuration. It is defaults to values suitable for generic human-sized agents. - - - - The lower section contains the input configuration. The scene query is optional. If none is provided then the search will be global. E.g. - All MeshFilters in the scene. There has to be at least one input processor for the build to produce anything. - - - - -
      - - - - - - - - - - -
      -
      \ No newline at end of file diff --git a/critterai/legacy/lib/README.txt b/critterai/legacy/lib/README.txt deleted file mode 100644 index a5290a3a..00000000 --- a/critterai/legacy/lib/README.txt +++ /dev/null @@ -1,10 +0,0 @@ -This directory contains shared project libraries. - -Compiled project libraries are not normally stored in -the repository. An exception is made when a library is -meant to be shared between projects. In such cases the -compiled library is placed here so that it is available for -dependant project builds and packaging. - -(The use of this directory is depreciated. New projects usually include -a direct reference to the shared library source.) diff --git a/critterai/legacy/lib/java/LICENSE.txt b/critterai/legacy/lib/java/LICENSE.txt deleted file mode 100644 index a7efd634..00000000 --- a/critterai/legacy/lib/java/LICENSE.txt +++ /dev/null @@ -1 +0,0 @@ -The files in this directory are governed by their own individual licenses. diff --git a/critterai/legacy/lib/java/cai-util-0.1.1.jar b/critterai/legacy/lib/java/cai-util-0.1.1.jar deleted file mode 100644 index 31d79d85..00000000 Binary files a/critterai/legacy/lib/java/cai-util-0.1.1.jar and /dev/null differ diff --git a/critterai/legacy/lib/java/junit-4.7.jar b/critterai/legacy/lib/java/junit-4.7.jar deleted file mode 100644 index 700ad695..00000000 Binary files a/critterai/legacy/lib/java/junit-4.7.jar and /dev/null differ diff --git a/critterai/legacy/nmgen-study/build.properties b/critterai/legacy/nmgen-study/build.properties deleted file mode 100644 index 478af374..00000000 --- a/critterai/legacy/nmgen-study/build.properties +++ /dev/null @@ -1,19 +0,0 @@ -version=snapshot -project.name=cai-nmgen -project.fullname=${project.name}-${version} - -lib.dir=../../lib/java -misc.resources.dir=../../misc - -src.dir=src - -local.misc.dir=misc -dist.scm.dir=${lib.dir} - -test.src.dir=test -test.classes.dir=${build.dir}/test - -build.dir=build -classes.dir=${build.dir}/classes -dist.dir=${build.dir}/dist -doc.dir=${build.dir}/docs \ No newline at end of file diff --git a/critterai/legacy/nmgen-study/build.xml b/critterai/legacy/nmgen-study/build.xml deleted file mode 100644 index 6a113d18..00000000 --- a/critterai/legacy/nmgen-study/build.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - - - Builds the CritterAI NMGen library. - Override the version property with -Dversion. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - - Project Home and - - Source Code - -

      -

      - Copyright 2010 Stephen Pratt. All rights reserved. - Use is subject to - - license terms. -

      -
      - - ]]> -
      -
      -
      - - - - - -
      \ No newline at end of file diff --git a/critterai/legacy/nmgen-study/misc/CHANGES.txt b/critterai/legacy/nmgen-study/misc/CHANGES.txt deleted file mode 100644 index 3d1da54e..00000000 --- a/critterai/legacy/nmgen-study/misc/CHANGES.txt +++ /dev/null @@ -1,36 +0,0 @@ ->>>>>> NMGen-0.2.0 <<<<<< - -Includes breaking API changes. - -Improved robustness when dealing with extreme configuration settings. -(Including bug fixes and changes to algorithms.) - -Improved robustness when dealing with outdoor/uneven terrain. -(Including bug fixes and changes to algorithms.) - -Resolved issue 4: Contour Generation Fails Due to Unexpected Internal Null -Region - -Resolved issue 5: Seams Form Between Triangles within a Region - -The smoothingThreshold parameter is now restricted to 0 <= value <= 4. - -The maxTraversableSlope parameter is now restricted to 0 <= value <= 85. - -Merged LogResults functionality into the IntermediateData class. - -New class: CleanNullRegionBorders - -Merged the functionality from the CleanNullRegionCorners class into the -cleanNullRegionBorders class. - -Retired the BaseHeightfield class. - -Retired the IHeightfieldIterator interface. - -General code reformatting: Cleaned white space, sorted class members, -reformatted all files to 80 character width. - ->>>>>> NMGen-0.1.2 <<<<<< - -Initial full release. \ No newline at end of file diff --git a/critterai/legacy/nmgen-study/misc/README.txt b/critterai/legacy/nmgen-study/misc/README.txt deleted file mode 100644 index ea91ce71..00000000 --- a/critterai/legacy/nmgen-study/misc/README.txt +++ /dev/null @@ -1,12 +0,0 @@ -This package contains a study version of NMGen. NMGen is an adaptation -in Java of Recast's static mesh functionality for purposes of study -and experimentation. NMGen takes an arbitrary triangle mesh as input -and generates data representing the traversable surface of the source mesh. - -Recast is a C++ navigation mesh construction toolset created by -Mikko Mononen and released under the MIT license. - -NMGen Home: http://code.google.com/p/critterai/ -Study Home: http://www.critterai.org/nmgen - -Recast Home: http://code.google.com/p/recastnavigation/ diff --git a/critterai/legacy/nmgen-study/misc/overview.html b/critterai/legacy/nmgen-study/misc/overview.html deleted file mode 100644 index 3eebf02f..00000000 --- a/critterai/legacy/nmgen-study/misc/overview.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - -CritterAI NMGen - - - - -

      NMGen is adaptation of Recast's static mesh functionality in the Java language for purposes of study and experimentation. It takes an arbitrary triangle mesh as input and outputs meshes representing the traversable surface of the original mesh.

      -

      Project Documentation
      -
      Project Source
      -License

      -

      -

      -

      Navigation Mesh Generation Process

      - -

      This process is an adaptation of portions of -Recast, a C++ navigation mesh generator -created and released by Mikko Mononen under the -MIT license.

      - -

      - The general process is as follows:

      -
        -
      1. - Voxelization - Create a solid heightfield from the source geometry.
      2. -
      3. - Generate Regions - Detect the top surface area of the solid heightfield and divide it up into contiguous regions.
      4. -
      5. - Generate Contours - Detect the contours of the regions and form them into simple polygons.
      6. -
      7. - Generate Polygon Mesh - Divide the contours into convex polygons.
      8. -
      9. Generate Detailed Mesh - Triangulate the polygon mesh and add height detail.
      10. -
      - -

      See The High Level Process -for more information.

      - -

      The class which implements this process is {@link org.critterai.nmgen.NavmeshGenerator}.

      - -

      Each stage of the process is implemented by data and builder classes. The output of one stage is required -as input for the next:

      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      StageBuilder ClassData Class (output)Builder Input
      Voxelization{@link org.critterai.nmgen.SolidHeightfieldBuilder}{@link org.critterai.nmgen.SolidHeightfield}Source Geometry
      Region Generation{@link org.critterai.nmgen.OpenHeightfieldBuilder}{@link org.critterai.nmgen.OpenHeightfield}{@link org.critterai.nmgen.SolidHeightfield}
      Contour Generation{@link org.critterai.nmgen.ContourSetBuilder}{@link org.critterai.nmgen.ContourSet}{@link org.critterai.nmgen.OpenHeightfield} (Fully built.)
      Polygon Mesh Generation{@link org.critterai.nmgen.PolyMeshField}{@link org.critterai.nmgen.PolyMeshField}{@link org.critterai.nmgen.ContourSet}
      Detail Mesh Generation{@link org.critterai.nmgen.DetailMeshBuilder}{@link org.critterai.nmgen.TriangleMesh}{@link org.critterai.nmgen.PolyMeshField}
      - - - diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/BoundedField.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/BoundedField.java deleted file mode 100644 index d94cff5d..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/BoundedField.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Defines an axis aligned bounding box containing a grid based field. - *

      There are no enforced usage models for this class. But within this - * package the following standards apply:

      - *
        - *
      • The base (width/depth) of the field is defined by a grid of cells - * with a size of {@link #cellSize()}.
      • - *
      • Width of the field is associated with the x-axis and depth with - * the z-axis. So the width and depth of the field lies on the xz-plane.

        - *
      • The position of a cell is defined by an aggregate width/depth index - * obtained from {@link #gridIndex(int, int) gridIndex()}.
      • - *
      • The grid indices originate at the minimum bounds of the field.
      • - *
      • The height increment within each grid location is defined by the - * value of {@link #cellHeight()} - * and also originates at the field's minimum bounds.
      • - *
      • Sizing of the bounds and the values of cell size/height will be - * such that the bounds will not contain partial cells.
      • - *
      - *

      Warning: Behavior is undefined if the minimum bounds is set to be - * greater than the maximum bounds.

      - * @see Introduction to Height Fields - */ -public class BoundedField -{ - - /* - * Design notes: - * - * In most cases, performance trumps object safety. For example, the - * bounds getters return a reference to the internal bounds arrays in - * order to save on object creation costs. - * - * Setters are protected rather than public in order to allow implementing - * classes to control mutability. - * - * Recast Reference: None - */ - - private int mWidth; - private int mDepth; - private final float[] mBoundsMin = new float[3]; - private final float[] mBoundsMax = new float[3]; - private float mCellSize; - private float mCellHeight; - - /** - * Constructor - Default - *

      The bounds of the field will default to min(0, 0, 0) and - * max(1, 1, 1).

      - *

      The cell size and height will default to 0.1.

      - */ - public BoundedField() - { - resetBounds(); - resetCellInfo(); // Must call this after the bounds call. - } - - /** - * Constructor - Partial - *

      The bounds of the field will default to min(0, 0, 0) and - * max(1, 1, 1).

      - *

      The cell size and height values are auto-clamped to - * {@link Float#MIN_VALUE}.

      - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - */ - public BoundedField(float cellSize, float cellHeight) - { - mCellSize = Math.max(cellSize, Float.MIN_VALUE); - mCellHeight = Math.max(cellHeight, Float.MIN_VALUE); - calculateWidthDepth(); - } - - /** - * Constructor - Full - *

      The cell size and height values are auto-clamped to - * {@link Float#MIN_VALUE}.

      - *

      Warning: Behavior is undefined if the minimum bounds is set to - * be greater than the maximum bounds.

      - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - * @throws IllegalArgumentException If the bounds are null or the - * wrong size. - */ - public BoundedField(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize - , float cellHeight) - throws IllegalArgumentException - { - if (gridBoundsMax == null - || gridBoundsMin == null - || gridBoundsMax.length != 3 - || gridBoundsMin.length != 3) - throw new IllegalArgumentException( - "One or both bounds are invalid."); - - System.arraycopy(gridBoundsMin, 0, mBoundsMin, 0, 3); - System.arraycopy(gridBoundsMax, 0, mBoundsMax, 0, 3); - - mCellSize = Math.max(cellSize, Float.MIN_VALUE); - mCellHeight = Math.max(cellHeight, Float.MIN_VALUE); - - calculateWidthDepth(); - } - - /** - * The maximum bounds of the field in world units. - *

      Warning: A reference to the internal array is being returned, - * not a new array.

      - *

      Form: (maxX, maxY, maxZ)

      - */ - public final float[] boundsMax() { return mBoundsMax; } - - /** - * The minimum bounds of the field in world units. - *

      Warning: A reference to the internal array is being returned, - * not a new array.

      - *

      Form: (minX, minY, minZ)

      - *

      Considered the origin of the field.

      - */ - public final float[] boundsMin() { return mBoundsMin; } - - /** - * The height increment of the field. - */ - public final float cellHeight() { return mCellHeight; } - - /** - * The size of the cells. (The grid that forms the base of the field.) - */ - public final float cellSize() { return mCellSize; } - - /** - * Depth of the field in voxels. - *

      The maximum depth index for the field is equal to(depth - 1). - */ - public final int depth() { return mDepth; } - - /** - * Indicates whether or not the provided index values represent a - * valid cell location within - * the field. - * @param widthIndex The width index. - * @param depthIndex The depth index. - * @return TRUE if the width and depth indices are valid for the field. - * Otherwise FALSE. - */ - public final boolean isInBounds(int widthIndex, int depthIndex) - { - return (widthIndex >= 0 - && depthIndex >= 0 - && widthIndex < mWidth - && depthIndex < mDepth); - } - - /** - * Indicates whether or not the provided bounds overlaps the bounds of - * the current field. - *

      All tests are inclusive. So if there is an edge match, then the - * bounds overlap.

      - * @param boundsMin The minimum bounds of the field to test in the - * form (minX, minY, minZ). - * @param boundsMax The maximum bounds of the field to test in the - * form (maxX, maxY, maxZ). - * @return TRUE if the provided bounds overlaps the bounds of the - * current field. Otherwise FALSE. - */ - public final boolean overlaps(float[] boundsMin, float[] boundsMax) - { - boolean overlaps = true; - if (boundsMin == null - || boundsMax == null - || boundsMin.length != 3 - || boundsMax.length != 3) - return false; - // Keep the value of TRUE unless a non-overlap condition is found. - overlaps = (mBoundsMin[0] > boundsMax[0] - || mBoundsMax[0] < boundsMin[0]) ? false : overlaps; - overlaps = (mBoundsMin[1] > boundsMax[1] - || mBoundsMax[1] < boundsMin[1]) ? false : overlaps; - overlaps = (mBoundsMin[2] > boundsMax[2] - || mBoundsMax[2] < boundsMin[2]) ? false : overlaps; - return overlaps; - } - - /** - * Width of the field in voxels. - *

      The maximum width index for the field is equal to (width - 1).

      - */ - public final int width() { return mWidth; } - - - /** - * Generates a standardized grid index suitable for use in flattened - * storage arrays. - *

      Results in depth adjacent storage. (Cells at depth 0, Cells at - * depth 1, etc.)

      - * @param widthIndex The width index. - * @param depthIndex The depth index. - * @return A standardized grid index for the cell identified by the - * width and depth - * indices. If the width and depth combination is invalid for the - * field, a value of -1 will be returned. - */ - protected final int gridIndex(int widthIndex, int depthIndex) - { - /* - * Design notes: - * - * It is not uncommon during iteration processes, especially - * processes which are iterating on the edge of the bounds, that the - * width and depth indices may go out of range. While there would be - * a slight performance gain by leaving out the below argument - * validation, and require that callers be responsible for passing - * good values, experience indicates that this causes hard to find - * bugs. So instead, the validation is being performed here for - * all calls. - * - * Compare this algorithm to flattened vertex storage. - * This only involves different naming conventions. - * vertPointer = vertIndex * 3 + offset. - * Where: 3 is the number of values per vertex (the dimension) - * and 0 <= offset < vertex dimensions. - */ - if (widthIndex < 0 - || depthIndex < 0 - || widthIndex >= mWidth - || depthIndex >= mDepth) - return -1; - return widthIndex * mDepth + depthIndex ; - } - - /** - * Resets the bounds to min(0, 0, 0) and max(1, 1, 1). - */ - protected final void resetBounds() - { - mBoundsMin[0] = 0; - mBoundsMin[1] = 0; - mBoundsMin[2] = 0; - mBoundsMax[0] = 1; - mBoundsMax[1] = 1; - mBoundsMax[2] = 1; - calculateWidthDepth(); - } - - /** - * Reset the cell size and height values to 0.1. - */ - protected final void resetCellInfo() - { - mCellSize = 0.1f; - mCellHeight = 0.1f; - calculateWidthDepth(); - } - - /** - * Sets the bounds of the field. - *

      Warning: Behavior is undefined if the minimum bounds is greater - * than the maximum bounds.

      - * @param xmin The x-value for the minimum bounds. - * @param ymin The y-value for the minimum bounds. - * @param zmin The z-value for the minimum bounds. - * @param xmax The x-value for the maximum bounds. - * @param ymax The y-value for the maximum bounds. - * @param zmax The z-value for the maximum bounds. - */ - protected final void setBounds(float xmin, float ymin, float zmin - , float xmax, float ymax, float zmax) - { - mBoundsMin[0] = xmin; - mBoundsMin[1] = ymin; - mBoundsMin[2] = zmin; - mBoundsMax[0] = xmax; - mBoundsMax[1] = ymax; - mBoundsMax[2] = zmax; - calculateWidthDepth(); - } - - /** - * Sets the bounds of the field. - *

      Null values and arrays of length other than 3 are ignored.

      - *

      Warning: Behavior is undefined if the minimum bounds is greater - * than the maximum bounds.

      - * @param min The minimum bounds in the form (minX, minY, minZ). - * @param max The maximum bounds in the form (maxX, maxY, maxZ). - */ - protected final void setBounds(float[] min, float[] max) - { - if (min == null || max == null || min.length != 3 || max.length != 3) - return; - System.arraycopy(min, 0, mBoundsMin, 0, 3); - System.arraycopy(max, 0, mBoundsMax, 0, 3); - calculateWidthDepth(); - } - - /** - * Set the maximum bounds of the field. - *

      Null values and arrays of length other than 3 are ignored.

      - *

      Warning: Behavior is undefined if the new maximum bounds is less - * than the current minimum bounds.

      - * @param value The maximum bounds in the form (maxX, maxY, maxZ). - */ - protected final void setBoundsMax(float[] value) - { - if (value == null || value.length != 3) - return; - System.arraycopy(value, 0, mBoundsMax, 0, 3);; - calculateWidthDepth(); - } - - /** - * Set the minimum bounds of the field. - *

      Null values and arrays of length other than 3 are ignored.

      - *

      Warning: Behavior is undefined if the new minimum bounds is - * greater than the current maximum bounds.

      - * @param value The minimum bounds in the form (minX, minY, minZ). - */ - protected final void setBoundsMin(float[] value) - { - if (value == null || value.length != 3) - return; - System.arraycopy(value, 0, mBoundsMin, 0, 3); - calculateWidthDepth(); - } - - /** - * Set the cell height. - *

      The cell height value is clamped to {@link Float#MIN_VALUE}.

      - * @param value The new cell height. - */ - protected final void setCellHeight(float value) - { - mCellHeight = Math.max(value, Float.MIN_VALUE); - } - - /** - * Set the cell size. - *

      The cell size value is clamped to {@link Float#MIN_VALUE}.

      - * @param value The new cell size. - */ - protected final void setCellSize(float value) - { - mCellSize = Math.max(value, Float.MIN_VALUE); - calculateWidthDepth(); - } - - /** - * Sets the width and depth fields based on the current - * bounds and cell size. - */ - private void calculateWidthDepth() - { - mWidth = (int)((mBoundsMax[0] - mBoundsMin[0]) / mCellSize + 0.5f); - mDepth = (int)((mBoundsMax[2] - mBoundsMin[2]) / mCellSize + 0.5f); - } - - /** - * When used in conjunction with {@link #getDirOffsetWidth(int)}, gets a - * standard axis-neighbor direction offset that can be used for - * searching adjacent grid locations. - *

      The combined offset will be in the clockwise direction for - * direction 0 to 3, starting at (-1, 0).

      - *

      For example, if a direction value of 3 is passed to both this - * operation and {@link #getDirOffsetWidth(int)}, - * then the combined width/depth offset will be (0, -1).

      - * @param dir A value representing the direction to get the offset for. - * The value will be automatically constrained to a valid value between - * 0 and 3 inclusive using wrapping. E.g. A value of 4 will be - * automatically wrapped to 0, a value of 9 will be automatically - * wrapped to 1, etc. - * @return The standard offset for the provided direction. - * @see Neighbor Searches - */ - public static int getDirOffsetDepth(int dir) - { - final int offset[] = { 0, 1, 0, -1 }; - return offset[dir&0x03]; - } - - /** - * When used in conjunction with {@link #getDirOffsetDepth(int)}, gets a - * standard axis-neighbor direction offset that can be used for - * searching adjacent grid locations within the field. - *

      The combined offset will be in the clockwise direction for - * direction 0 to 3, starting at (-1, 0).

      - *

      For example, if a direction value of 3 is passed to both this - * operation and {@link #getDirOffsetDepth(int)}, then the combined - * width/depth offset will be (0, -1).

      - * @param dir A value representing the direction to get the offset for. - * The value will be automatically constrained to a valid value between - * 0 and 3 inclusive, using wrapping. E.g. A value of 4 will be - * automatically wrapped to 0, a value of 9 will be automatically wrapped - * to 1, etc. - * @return The standard offset for the provided direction. - * @see Neighbor Searches - */ - public static int getDirOffsetWidth(int dir) - { - final int offset[] = { -1, 0, 1, 0 }; - // All bits above 3 are discarded, constraining argument to 0 - 3; - return offset[dir&0x03]; - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/CleanNullRegionBorders.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/CleanNullRegionBorders.java deleted file mode 100644 index bf4a935e..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/CleanNullRegionBorders.java +++ /dev/null @@ -1,754 +0,0 @@ -package org.critterai.nmgen; - -import java.util.ArrayDeque; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Implements three algorithms that clean up issues that can - * develop around null region boarders. - * - *

      Detect and fix encompassed null regions:

      - *

      If a null region is found that is fully encompassed by a single - * region, then the region will be split into two regions at the - * null region border.

      - * - *

      Detect and fix "short wrapping" of null regions:

      - *

      Regions can sometimes wrap slightly around the corner of a null region - * in a manner that eventually results in the formation of self-intersecting - * polygons.

      - *

      Example: Before the algorithm is applied:

      - *

      - * - *

      - *

      Example: After the algorithm is applied:

      - *

      - * - *

      - * - *

      Detect and fix incomplete null region connections:

      - *

      If a region touches null region only diagonally, then contour detection - * algorithms may not properly detect the null region connection. This can - * adversely effect other algorithms in the pipeline.

      - *

      Example: Before algorithm is applied:

      - *

      - *     b b a a a a
      - *     b b a a a a
      - *     a a x x x x
      - *     a a x x x x
      - * 

      - *

      Example: After algorithm is applied:

      - *

      - *     b b a a a a
      - *     b b b a a a <-- Span transferred to region B.
      - *     a a x x x x
      - *     a a x x x x
      - * 

      - * - * @see Region Generation - */ -public class CleanNullRegionBorders - implements IOpenHeightFieldAlgorithm -{ - - /* - * Design Notes: - * - * Three algorithms have been aggregated into this single class - * for performance reasons. Otherwise we would be stuck - * performing three full contour searches rather than one. - * - * The optimization method used in the search can result in missed - * null region contours. Consider the following pattern: - * - * x x x x x x - * x a a a a x x - null region WITHOUT SPANS - * x a v v a x a - region A - * x a v v a x v - null region WITHOUT SPANS - * x a a a a x - * x x x x x x - * - * If an all span search is performed, the outer null region (x) will - * be detected, but during the process all a-region spans will be marked as - * viewed. This will leave no spans available to detect the inner null - * region (v). - * - * I've not fixing this until it proves to be a problem or I figure out - * a way of resolving the design issue without killing performance. - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private final boolean mUseOnlyNullSpans; - - // Working variables. Content is meaningless outside of - // method they are used. - private final ArrayDeque mwOpenSpans - = new ArrayDeque(1024); - private final ArrayDeque mwBorderDistance - = new ArrayDeque(1024); - private final int[] mwNeighborRegions = new int[8]; - - /** - * Constructor. - *

      Choosing a contour detection type:

      - *

      This algorithm has to detect and walk null region contours. (Where - * null regions border non-null regions.) There are two options for - * detection: Search every single span looking for null region - * neighbors. Or search only null region spans looking for - * non-null region neighbors. Since null region spans are only a tiny - * fraction of total spans, the second option has better performance.

      - *

      If a heightfield is constructed such that all null regions have - * at least one null region span in each contour, then set - * useOnlyNullRegionSpans to TRUE.

      - * @param useOnlyNullRegionSpans If TRUE, then only null region spans - * will be used to initially detect null region borders. This - * improves performance. If FALSE, all spans are searched to detect - * borders. - */ - public CleanNullRegionBorders(boolean useOnlyNullRegionSpans) - { - mUseOnlyNullSpans = useOnlyNullRegionSpans; - } - - /** - * {@inheritDoc} - *

      This operation utilizes {@link OpenHeightSpan#flags}. It - * expects the value to be zero on entry, and re-zero's the value - * on exit.

      - *

      Expects a heightfield with fully built regions.

      - */ - @Override - public void apply(OpenHeightfield field) - { - - int nextRegionID = field.regionCount(); - final OpenHeightFieldIterator iter = field.dataIterator(); - - // Iterate over the spans, trying to find null region borders. - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - - if (span.flags != 0) - // Span was processed in a previous iteration. - // Ignore it. - continue; - - span.flags = 1; - - OpenHeightSpan workingSpan = null; - int edgeDirection = -1; - - if (span.regionID() == NULL_REGION) - { - // This is a null region span. See if it - // connects to a span in a non-null region. - edgeDirection = getNonNullBorderDrection(span); - if (edgeDirection == -1) - // This span is not a border span. Ignore it. - continue; - - // This is a border span. Step into the non-null - // region and swing the direction around 180 degrees. - workingSpan = span.getNeighbor(edgeDirection); - edgeDirection = (edgeDirection+2) & 0x3; - } - else if (!mUseOnlyNullSpans) - { - // This is a non-null region span and I'm allowed - // to look at it. See if it connects to a null region. - edgeDirection = getNullBorderDrection(span); - if (edgeDirection == -1) - // This span is not a null region border span. Ignore it. - continue; - workingSpan = span; - } - else - // Not interested in this span. - continue; - - // Process the null region contour. Detect and fix - // local issues. Determine if the region is - // fully encompassed by a single non-null region. - boolean isEncompassedNullRegion = processNullRegion( - workingSpan - , edgeDirection); - - if (isEncompassedNullRegion) - { - // This span is part of a group of null region spans - // that is encompassed within a single non-null region. - // This is not permitted. Need to fix it. - partialFloodRegion(workingSpan - , edgeDirection - , nextRegionID); - nextRegionID++; - } - } - - field.setRegionCount(nextRegionID); - - // Clear all flags. - iter.reset(); - while (iter.hasNext()) - { - iter.next().flags = 0; - } - } - - /** - * Partially flood a region away from the specified direction. - *

      {@link OpenHeightSpan#distanceToRegionCore()} - * is set to zero for all flooded spans.

      - * @param startSpan The span to start the flood from. - * @param borderDirection The hard border for flooding. No - * spans in this direction from the startSpan will be flooded. - * @param newRegionID The region id to assign the flooded - * spans to. - */ - private void partialFloodRegion(OpenHeightSpan startSpan - , int borderDirection - , int newRegionID) - { - // Gather some information. - final int antiBorderDirection = (borderDirection+2) & 0x3; - final int regionID = startSpan.regionID(); - - // Re-assign the start span and queue it for the neighbor search. - startSpan.setRegionID(newRegionID); - startSpan.setDistanceToRegionCore(0); // This information is lost. - mwOpenSpans.add(startSpan); - mwBorderDistance.add(0); - - // Search for new spans that can be assigned the new region. - while(!mwOpenSpans.isEmpty()) - { - // Get the next span off the stack. - final OpenHeightSpan span = mwOpenSpans.pollLast(); - final int distance = mwBorderDistance.pollLast(); - - // Search in all directions for neighbors. - for (int i = 0; i < 4; i++) - { - final OpenHeightSpan nSpan = span.getNeighbor(i); - if (nSpan == null - || nSpan.regionID() != regionID) - // No span in this direction, or the span - // is not in the region being processed. - // Note: It may have already been transferred. - continue; - int nDistance = distance; - if (i == borderDirection) - { - // This neighbor is back toward the border. - if (distance == 0) - // The span is at the border. Can't go - // further in this direction. Ignore - // this neighbor. - continue; - nDistance--; - } - else if (i == antiBorderDirection) - // This neighbor is further away from the border. - nDistance++; - - // Transfer the neighbor to the new region. - nSpan.setRegionID(newRegionID); - nSpan.setDistanceToRegionCore(0); // This information is lost. - - // Add the span to the stack to be processed. - mwOpenSpans.add(nSpan); - mwBorderDistance.add(nDistance); - - } - - } - - } - - /** - * Detects and fixes bad span configurations in the vicinity of a - * null region contour. (See class description for details.) - * @param startSpan A span in a non-null region that borders a null - * region. - * @param startDirection The direction of the null region border. - * @return TRUE if the start span's region completely encompasses - * the null region. - */ - private boolean processNullRegion(OpenHeightSpan startSpan - , int startDirection) - { - - /* - * This algorithm traverses the contour. As it does so, it detects - * and fixes various known dangerous span configurations. - * - * Traversing the contour: A good way to visualize it is to think - * of a robot sitting on the floor facing a known wall. It then - * does the following to skirt the wall: - * 1. If there is a wall in front of it, turn clockwise in 90 degrees - * increments until it finds the wall is gone. - * 2. Move forward one step. - * 3. Turn counter-clockwise by 90 degrees. - * 4. Repeat from step 1 until it finds itself at its original - * location facing its original direction. - * - * See also: http://www.critterai.org/nmgen_contourgen#robotwalk - * - * As the traversal occurs, the number of acute (90 degree) and - * obtuse (270 degree) corners are monitored. If a complete contour is - * detected and (obtuse corners > acute corners), then the null - * region is inside the contour. Otherwise the null region is - * outside the contour, which we don't care about. - */ - - int borderRegionID = startSpan.regionID(); - - // Prepare for loop. - OpenHeightSpan span = startSpan; - OpenHeightSpan nSpan = null; - int dir = startDirection; - - // Initialize monitoring variables. - int loopCount = 0; - int acuteCornerCount = 0; - int obtuseCornerCount = 0; - int stepsWithoutBorder = 0; - boolean borderSeenLastLoop = false; - boolean isBorder = true; // Initial value doesn't matter. - - // Assume a single region is connected to the null region - // until proven otherwise. - boolean hasSingleConnection = true; - - /* - * The loop limit exists for the sole reason of preventing - * an infinite loop in case of bad input data. - * It is set to a very high value because there is no way of - * definitively determining a safe smaller value. Setting - * the value too low can result in rescanning a contour - * multiple times, killing performance. - */ - while (++loopCount < Integer.MAX_VALUE) - { - // Get the span across the border. - nSpan = span.getNeighbor(dir); - - // Detect which type of edge this direction points across. - if (nSpan == null) - { - // It points across a null region border edge. - isBorder = true; - } - else - { - // We never need to perform contour detection - // on this span again. So mark it as processed. - nSpan.flags = 1; - if (nSpan.regionID() == NULL_REGION) - { - // It points across a null region border edge. - isBorder = true; - } - else - { - // This isn't a null region border. - isBorder = false; - if (nSpan.regionID() != borderRegionID) - // It points across a border to a non-null region. - // This means the current contour can't - // represent a fully encompassed null region. - hasSingleConnection = false; - } - } - - // Process the border. - if (isBorder) - { - // It is a border edge. - if (borderSeenLastLoop) - { - /* - * A border was detected during the last loop as well. - * Two detections in a row indicates we passed an acute - * (inner) corner. - * - * a x - * x x - */ - acuteCornerCount++; - } - else if (stepsWithoutBorder > 1) - { - /* - * We have moved at least two spans before detecting - * a border. This indicates we passed an obtuse - * (outer) corner. - * - * a a - * a x - */ - obtuseCornerCount++; - stepsWithoutBorder = 0; - // Detect and fix span configuraiton issue around this - // corner. - if (processOuterCorner(span, dir)) - // A change was made and it resulted in the - // corner area having multiple region connections. - hasSingleConnection = false; - } - dir = (dir+1) & 0x3; // Rotate in clockwise direction. - borderSeenLastLoop = true; - stepsWithoutBorder = 0; - } - else - { - /* - * Not a null region border. - * Move to the neighbor and swing the search direction back - * one increment (counterclockwise). By moving the direction - * back one increment we guarantee we don't miss any edges. - */ - span = nSpan; - dir = (dir+3) & 0x3; // Rotate counterclockwise direction. - borderSeenLastLoop = false; - stepsWithoutBorder++; - } - - if (startSpan == span && startDirection == dir) - // Have returned to the original span and direction. - // The search is complete. - // Is the null region inside the contour? - return (hasSingleConnection - && obtuseCornerCount > acuteCornerCount); - } - - // If got here then the null region boarder is too large to be fully - // explored. So it can't be encompassed. - return false; - } - - /** - * Detects and fixes span configuration issues in the vicinity - * of obtuse (outer) null region corners. - * @param referenceSpan The span in a non-null region that is - * just past the outer corner. - * @param borderDirection The direciton of the null region border. - * @return TRUE if more than one region connects to the null region - * in the vicinity of the corner. (This may or may not be due to - * a change made by this operation.) - */ - private boolean processOuterCorner(OpenHeightSpan referenceSpan - , int borderDirection) - { - - boolean hasMultiRegions = false; - - // Get the previous two spans along the border. - OpenHeightSpan backOne = - referenceSpan.getNeighbor((borderDirection+3) & 0x3); - OpenHeightSpan backTwo = backOne.getNeighbor(borderDirection); - OpenHeightSpan testSpan; - - if (backOne.regionID() != referenceSpan.regionID() - && backTwo.regionID() == referenceSpan.regionID()) - { - /* - * Dangerous corner configuration. - * - * a x - * b a - * - * Need to change to one of the following configurations: - * - * b x a x - * b a b b - * - * Reason: During contour detection this type of configuration can - * result in the region connection being detected as a - * region-region portal, when it is not. The region connection - * is actually interrupted by the null region. - * - * This configuration has been demonstrated to result in - * two regions being improperly merged to encompass an - * internal null region. - * - * Example: - * - * a a x x x a - * a a x x a a - * b b a a a a - * b b a a a a - * - * During contour and connection detection for region b, at no - * point will the null region be detected. It will appear - * as if a clean a-b portal exists. - * - * An investigation into fixing this issue via updates to the - * watershed or contour detection algorithms did not turn - * up a better way of resolving this issue. - */ - hasMultiRegions = true; - // Determine how many connections backTwo has to backOne's region. - testSpan = backOne.getNeighbor((borderDirection+3) & 0x3); - int backTwoConnections = 0; - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - { - backTwoConnections++; - testSpan = testSpan.getNeighbor(borderDirection); - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - backTwoConnections++; - } - // Determine how many connections the reference span has - // to backOne's region. - int referenceConnections = 0; - testSpan = backOne.getNeighbor((borderDirection+2) & 0x3); - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - { - referenceConnections++; - testSpan = testSpan.getNeighbor((borderDirection+2) & 0x3); - if (testSpan != null - && testSpan.regionID() == backOne.regionID()) - backTwoConnections++; - } - // Change the region of the span that has the most connections - // to the target region. - if (referenceConnections > backTwoConnections) - referenceSpan.setRegionID(backOne.regionID()); - else - backTwo.setRegionID(backOne.regionID()); - } - else if (backOne.regionID() == referenceSpan.regionID() - && backTwo.regionID() == referenceSpan.regionID()) - { - /* - * Potential dangerous short wrap. - * - * a x - * a a - * - * Example of actual problem configuration: - * - * b b x x - * b a x x <- Short wrap. - * b a a a - * - * In the above case, the short wrap around the corner of the - * null region has been demonstrated to cause self-intersecting - * polygons during polygon formation. - * - * This algorithm detects whether or not one (and only one) - * of the axis neighbors of the corner should be re-assigned to - * a more appropriate region. - * - * In the above example, the following configuration is more - * appropriate: - * - * b b x x - * b b x x <- Change to this row. - * b a a a - */ - // Check to see if backTwo should be in a different region. - int selectedRegion = selectedRegionID(backTwo - , (borderDirection+1) & 0x3 - , (borderDirection+2) & 0x3); - if (selectedRegion == backTwo.regionID()) - { - // backTwo should not be re-assigned. How about - // the reference span? - selectedRegion = selectedRegionID(referenceSpan - , borderDirection - , (borderDirection+3) & 0x3); - if (selectedRegion != referenceSpan.regionID()) - { - // The reference span should be reassigned - // to a new region. - referenceSpan.setRegionID(selectedRegion); - hasMultiRegions = true; - } - } - else - { - // backTwo should be re-assigned to a new region. - backTwo.setRegionID(selectedRegion); - hasMultiRegions = true; - } - } - else - /* - * No dangerous configurations detected. But definitely - * has a change in regions at the corner. (We know this - * because one of the previous checks looked for a single - * region for all wrap spans.) - */ - hasMultiRegions = true; - - return hasMultiRegions; - } - - /** - * Checks the span to see if it should be reassigned to a new region. - * @param referenceSpan A span on one side of an null region contour's - * outer corner. It is expected that the all spans that wrap the - * corner are in the same region. - * @param borderDirection The direction of the null region border. - * @param cornerDirection The direction of the outer corner from the - * reference span. - * @return The region the span should be a member of. May be the - * region the span is currently a member of. - */ - private int selectedRegionID(OpenHeightSpan referenceSpan - , int borderDirection - , int cornerDirection) - { - - // Get the regions of all neighbors. - referenceSpan.getDetailedRegionMap(mwNeighborRegions, 0); - - /* - * Initial example state: - * - * a - Known region. - * x - Null region. - * u - Unknown, not checked yet. - * - * u u u - * u a x - * u a a - */ - - // The only possible alternate region id is from - // the span that is opposite the border. So check it first. - int regionID = mwNeighborRegions[(borderDirection+2) & 0x3]; - if (regionID == referenceSpan.regionID() - || regionID == NULL_REGION) - /* - * The region away from the border is either a null region - * or the same region. So we keep the current region. - * - * u u u u u u - * a a x or x a x <-- Potentially bad, but stuck with it. - * u a a u a a - */ - return referenceSpan.regionID(); - - // Candidate region for re-assignment. - int potentialRegion = regionID; - - // Next we check the region opposite from the corner direction. - // If it is the current region, then we definitely can't - // change the region id without risk of splitting the region. - regionID = mwNeighborRegions[(cornerDirection+2) & 0x3]; - if (regionID == referenceSpan.regionID() || regionID == NULL_REGION) - /* - * The region opposite from the corner direction is - * either a null region or the same region. So we - * keep the current region. - * - * u a u u x u - * b a x or b a x - * u a a u a a - */ - return referenceSpan.regionID(); - - /* - * We have checked the early exit special cases. Now a generalized - * brute count is performed. - * - * Priority is given to the potential region. Here is why: - * (Highly unlikely worst case scenario.) - * - * c c c c c c - * b a x -> b b x Select b even though b count == a count. - * b a a b a a - */ - - // Neighbors in potential region. - // We know this will have a minimum value of 1. - int potentialCount = 0; - - // Neighbors in the span's current region. - // We know this will have a minimum value of 2. - int currentCount = 0; - - /* - * Maximum edge case: - * - * b b b - * b a x - * b a a - * - * The maximum edge case for region A can't exist. It - * is filtered out during one of the earlier special cases - * handlers. - * - * Other cases may exist if more regions are involved. - * Such cases will tend to favor the current region. - */ - - for (int i = 0; i < 8; i++) - { - if (mwNeighborRegions[i] == referenceSpan.regionID()) - currentCount++; - else if (mwNeighborRegions[i] == potentialRegion) - potentialCount++; - } - - return (potentialCount < currentCount - ? referenceSpan.regionID() : potentialRegion); - } - - /** - * Returns the direction of the first neighbor in a non-null region. - * @param span The span to check. - * @return The direction of the first neighbor in a non-null region, or - * -1 if all neighbors are in the null region. - */ - private static int getNonNullBorderDrection(OpenHeightSpan span) - { - // Search axis-neighbors. - for (int dir = 0; dir < 4; ++dir) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null && nSpan.regionID() != NULL_REGION) - // The neighbor is a non-null region. - return dir; - } - // All neighbors are in the null region. - return -1; - } - - /** - * Returns the direction of the first neighbor in the null region. - * @param span The span to check. - * @return The direction of the first neighbor that is in the null - * region, or -1 if there are no null region neighbors. - */ - private static int getNullBorderDrection(OpenHeightSpan span) - { - // Search axis-neighbors. - for (int dir = 0; dir < 4; ++dir) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null || nSpan.regionID() == NULL_REGION) - // The neighbor is a null region. - return dir; - } - // All neighbors are in a non-null region. - return -1; - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Contour.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Contour.java deleted file mode 100644 index f94182ac..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Contour.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Represents the detailed and simplified versions of a contour. - * A contour is expected to always represent a simple polygon. - * (Convex or concave.) - *

      - * - * - *

      - * @see ContourSetBuilder - */ -public final class Contour -{ - /* - * Recast Reference: rcContour in Recast.h - */ - - /** - * The region associated with the contour. - */ - public final int regionID; - - /** - * The vertices which represent the raw (or detailed) contour. - *

      Vertices are clockwise wrapped in the form (x, y, z, regionID), - * where regionID is the external region the vertex is considered to be - * connected to.

      - */ - public final int[] rawVerts; - - /** - * The raw vertex count. (A convenience value.) - */ - public final int rawVertCount; - - /** - * The vertices which represent the simplified contour. - *

      Vertices are clockwise wrapped in the form (x, y, z, regionID), - * where regionID is the external region the vertex is considered to be - * connected to.

      - */ - public final int[] verts; - - /** - * The detail vertex count. (A convenience value.) - */ - public final int vertCount; - - /** - * Constructor - *

      All vertex lists are expected to be clockwise wrapped in - * the form (x, y, z, regionID), where regionID is the external - * region the vertex is considered to be connected to.

      - * @param regionID The region associated with the contour. - * @param rawList The vertices which represent the raw (or detailed) - * contour. - * @param vertList The vertices which represent the detailed contour. - * @throws IllegalArgumentException If either vertex list is null. - * The size of the vertex lists is not checked. - */ - public Contour(int regionID - , ArrayList rawList - , ArrayList vertList) - throws IllegalArgumentException - { - if (rawList == null || vertList == null) - throw new IllegalArgumentException( - "One or both vertex lists are null."); - - this.regionID = regionID; - - rawVerts = new int[rawList.size()]; - for (int i = 0; i < rawVerts.length; i++) - rawVerts[i] = rawList.get(i); - - rawVertCount = rawVerts.length / 4; - - verts = new int[vertList.size()]; - for (int i = 0; i < verts.length; i++) - verts[i] = vertList.get(i); - - vertCount = verts.length / 4; - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/ContourSet.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/ContourSet.java deleted file mode 100644 index 24b7c959..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/ContourSet.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Represents a set of related contours (simple polygons) - * within a bounded field. - *

      The contours may be connected (share edges), but are expected - * to not intersect.

      - * @see Contour - */ -public final class ContourSet - extends BoundedField -{ - - /* - * Design notes: - * - * Not adding the ability to remove contours until it is needed. - * - * Recast Reference: rcContourSet in Recast.h - */ - - private final ArrayList mContours; - - /** - * Constructor - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - * @param initialSize The initial size of the set. Effects performance - * and memory consumption. The actual size will dynamically resize - * as needed. - */ - ContourSet(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize - , float cellHeight - , int initialSize) - { - super(gridBoundsMin, gridBoundsMax, cellSize, cellHeight); - mContours = new ArrayList(initialSize); - } - - /** - * Add a contour to the set. - *

      Behavior is undefined if the contour argument is null.

      - * @param contour The contour to add to the set. - */ - public void add(Contour contour) { mContours.add(contour);} - - /** - * Gets the contour specified by the index. - * @param index The index of the contour to retrieve. - * @return The contour for the specified index, or null if the index - * is invalid. - */ - public Contour get(int index) - { - if (index < 0 || index >= mContours.size()) - return null; - return mContours.get(index); - } - - /** - * The number of contours in the set. - * @return The number of contours in the set. - */ - public int size() { return mContours.size(); } - -} \ No newline at end of file diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/ContourSetBuilder.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/ContourSetBuilder.java deleted file mode 100644 index 31186206..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/ContourSetBuilder.java +++ /dev/null @@ -1,989 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; -import java.util.logging.Logger; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Builds a set of contours from the region information contained by an - * {@link OpenHeightfield}. It does this by locating and "walking" the edges - *

      - *

      - * @see Contour Generation - * @see Contour - * @see ContourSet - */ -public final class ContourSetBuilder -{ - - /* - * Design notes: - * - * Not adding configuration getters until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - * - * Recast Reference: rcBuildContours() in RecastContour.cpp - */ - - private static final Logger logger = - Logger.getLogger(ContourSetBuilder.class.getName()); - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * The post-processing algorithms to apply to the contours. - */ - private final ArrayList mAlgorithms = - new ArrayList(); - - /** - * Contructor - * @param algorithms The post-processing algorithms to apply to - * the contours. - */ - public ContourSetBuilder(ArrayList algorithms) - { - if (algorithms == null) - return; - this.mAlgorithms.addAll(algorithms); - } - - /** - * Generates a contour set from the provided {@link OpenHeightfield} - *

      The provided field is expected to contain region information. - * Behavior is undefined if the provided field is malformed or incomplete. - *

      - *

      This operation overwrites the flag fields for all spans in the - * provided field. So the flags must be saved and restored if they are - * important.

      - * @param sourceField A fully generated field. - * @return The contours generated from the field. - */ - public ContourSet build(OpenHeightfield sourceField) - { - if (sourceField == null || sourceField.regionCount() == 0) - return null; - - // Initialize the contour set. - final ContourSet result = new ContourSet(sourceField.boundsMin() - , sourceField.boundsMax() - , sourceField.cellSize() - , sourceField.cellHeight() - , sourceField.regionCount()); - - int discardedContours = 0; - - /* - * Set the flags on all spans in non-null regions to indicate which - * edges are connected to external regions. - * - * Reference: Neighbor search and nomenclature. - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - * - * If a span has no connections to external regions or is - * completely surrounded by other regions (a single span island), - * its flag will be zero. - * - * If a span is connected to one or more external regions then the - * flag will be a 4 bit value where connections are recorded as - * follows: - * bit1 = neighbor0 - * bit2 = neighbor1 - * bit3 = neighbor2 - * bit4 = neighbor3 - * With the meaning of the bits as follows: - * 0 = neighbor in same region. - * 1 = neighbor not in same region. (Neighbor may be the null - * region or a real region.) - */ - final OpenHeightFieldIterator iter = - sourceField.dataIterator(); - while(iter.hasNext()) - { - // Note: This algorithm first sets the flag bits such that - // 1 = "neighbor is in the same region". At the end it inverts - // the bits so flags are as expected. - final OpenHeightSpan span = iter.next(); - // Default to "not connected to any external region". - span.flags = 0; - if (span.regionID() == NULL_REGION) - // Don't care about spans in the null region. - continue; - // Loop through all directions. - for (int dir = 0; dir < 4; dir++) - { - // Default to show neighbor is in null region. - int nRegionID = NULL_REGION; - final OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null) - // There is a neighbor in the current direction. - // Get its region ID. - nRegionID = nSpan.regionID(); - if (span.regionID() == nRegionID) - // Neighbor is in same region as this span. Set the bit - // for this neighbor to 1. (Will be inverted later.) - span.flags |= (1 << dir); - } - // Invert the bits so a bit value of 1 indicates neighbor NOT in - // same region. - span.flags ^= 0xf; - if (span.flags == 0xf) - { - // This is an island span. (All neighbors are other regions.) - // Get rid of flags. - span.flags = 0; - discardedContours++; - logger.warning("Discarded contour: Island span. Can't form " + - "a contour. Region: " + span.regionID()); - } - } - - /* - * These are working lists whose content changes with each iteration - * of the up coming loop. They represent the detailed and simple - * contour vertices. - * Initial sizing is arbitrary. - */ - final ArrayList workingRawVerts = new ArrayList(256); - final ArrayList workingSimplifiedVerts = - new ArrayList(64); - - /* - * Loop through all spans looking for spans on the edge of a region. - * - * At this point, only spans with flags != 0 are edge spans that - * are part of a region contour. - * - * The process of building a contour will clear the flags on all spans - * that make up the contour. This ensures that the spans that make - * up a contour are only processed once. - */ - iter.reset(); - while(iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - if (span.regionID() == NULL_REGION || span.flags == 0) - // Span is either: Part of the null region, does not - // represent an edge span, or was already processed during - // an earlier iteration. - continue; - workingRawVerts.clear(); - workingSimplifiedVerts.clear(); - // The span is part of an unprocessed region's contour. - // Locate a direction of the span's edge which points toward - // another region. (We know there is at least one.) - int startDir = 0; - while ((span.flags & (1 << startDir)) == 0) - // This is not an edge direction. Try the next one. - startDir++; - // We now have a span that is part of a contour and a direction - // that points to a different region (null or real). - // Build the contour. - buildRawContours(span - , iter.widthIndex() - , iter.depthIndex() - , startDir - , workingRawVerts); - // Perform post processing on the contour in order to - // create the final, simplified contour. - generateSimplifiedContour(span.regionID() - , workingRawVerts - , workingSimplifiedVerts); - /* - * This next test is needed because some extreme cases contours - * just can't be successfully generated. - * We can't just copy the raw contour to the simplified contour - * because the reason the build failed may be because it - * can't be triangulated. (E.g. Has too many vertical segments.) - */ - if (workingSimplifiedVerts.size() < 12) - { - logger.warning("Discarded contour: Can't form enough valid" + - "edges from the vertices." + - " Region: " + span.regionID()); - discardedContours++; - } - else - { - result.add(new Contour(span.regionID() - , workingRawVerts - , workingSimplifiedVerts)); - } - - } - - if (discardedContours > 0) - { - logger.warning("Contours not generated for " + discardedContours - + " regions."); - } - - if (result.size() + discardedContours != - sourceField.regionCount() - 1) - { - /* - * The only valid state is one contour per region. - * - * The only time this should occur is if an invalid contour - * was formed or if a region resulted in multiple - * contours (bad region data). - * - * IMPORTANT: While a mismatch may not be a fatal error, - * it should be addressed since it can result in odd, - * hard to spot anomalies later in the pipeline. - * - * A known cause is if a region fully encompasses another - * region. In such a case, two contours will be formed. - * The normal outer contour and an inner contour. - * The CleanNullRegionBorders algorithm protects - * against internal encompassed null regions. - */ - - // Detect and report anomalies. - // Not reporting missing contours since those are sometimes - // expected and already reported. - - for (int regionID = 1 - ; regionID < sourceField.regionCount() - ; regionID++) - { - int regionMatches = 0; - for (int iContour = 0; iContour < result.size(); iContour++) - { - if (result.get(iContour).regionID == regionID) - regionMatches++; - } - if (regionMatches > 1) - { - logger.severe("More than one contour generated for a" + - "region: Region: " + regionID + ", Contours:" + - regionMatches); - } - } - - for (int iContour = 0; iContour < result.size(); iContour++) - { - Contour contour = result.get(iContour); - if (contour.regionID <= 0) - { - // Indicates a problem with this class. - logger.severe("A contour was generated for the null" - + "region."); - } - else if (contour.regionID >= sourceField.regionCount()) - { - // Indicates a problem with region generation. - logger.severe("A contour was generated for a region" - + " not in the source field's range: " - + contour.regionID); - } - } - - logger.severe("Contour generation failed: Detected contours does" - + " not match the number of regions. Regions: " - + (sourceField.regionCount() - 1) - + ", Detected contours: " - + (result.size() + discardedContours) - + " (Actual: " + result.size() - + ", Discarded: " + discardedContours + ")"); - return null; - } - - return result; - - } - - /** - * Walk around the edge of this span's region gathering vertices that - * represent the corners of each span on the sides that are external facing. - *

      There will be two or three vertices for each edge span: - * Two for spans that don't represent a change in edge direction. Three - * for spans that represent a change in edge direction.

      - *

      The output array will contain vertices ordered as follows: - * (x, y, z, regionID) where regionID is the region (null or real) that - * this vertex is considered to be connected to.

      - *

      WARNING: Only run this operation on spans that are already known - * to be on a region edge. The direction must also be pointing to a - * valid edge. Otherwise behavior will be undefined.

      - * @param startSpan A span that is known to be on the edge of a region. - * (Part of a region contour.) - * @param startWidthIndex The width index of the starting span. - * @param startDepthIndex The depth index of the starting span. - * @param startDirection The direction of the edge of the span that is - * known to point - * across the region edge. - * @param outContourVerts The list of vertices that represent the edge - * of the region. (Plus region information.) - */ - private void buildRawContours(OpenHeightSpan startSpan - , int startWidthIndex - , int startDepthIndex - , int startDirection - , ArrayList outContourVerts) - { - - /* - * Flaw in Algorithm: - * - * This method of contour generation can result in an inappropriate - * impassable seam between two adjacent regions in the following case: - * - * 1. One region connects to another region on two sides in an - * uninterrupted manner. (Visualize one region wrapping in an L - * shape around the corner of another.) - * 2. At the corner shared by the two regions, a change in height - * occurs. - * - * In this case, the two regions should share a corner vertex. - * (An obtuse corner vertex for one region and an acute corner - * vertex for the other region.) - * - * In reality, though this algorithm will select the same (x, z) - * coordinates for each region's corner vertex, the vertex heights - * may differ, eventually resulting in an impassable seam. - * - */ - - /* - * It is a bit hard to describe the stepping portion of this algorithm. - * One way to visualize it is to think of a robot sitting on the - * floor facing a known wall. It then does the following to skirt - * the wall: - * 1. If there is a wall in front of it, turn clockwise in 90 degrees - * increments until it finds the wall is gone. - * 2. Move forward one step. - * 3. Turn counter-clockwise by 90 degrees. - * 4. Repeat from step 1 until it finds itself at its original - * location facing its original direction. - * - * See also: http://www.critterai.org/nmgen_contourgen#robotwalk - */ - - // Initialize to current span pointing to the edge. - OpenHeightSpan span = startSpan; - int dir = startDirection; - int spanX = startWidthIndex; - int spanZ = startDepthIndex; - - int loopCount = 0; - /* - * The loop limit is arbitrary. It exists only to guarantee that - * bad input data doesn't result in an infinite loop. - * The only down side of this loop limit is that it limits the - * number of detectable edge vertices. (The longer the region edge - * and the higher the number of "turns" in a region's edge, the less - * edge vertices can be detected for that region.) - */ - while (++loopCount < 65535) - { - - // Note: The design of this loop is such that the span variable - // will always reference an edge span from the same region as - // the start span. - - if ((span.flags & (1 << dir)) != 0) - { - - // The current direction is pointing toward an edge. - // Get this edge's vertex. - int px = spanX; - final int py = getCornerHeight(span, dir); - int pz = spanZ; - /* - * Update the px and pz values based on current direction. - * The update is such that the corner being represented is - * clockwise from the edge the direction is currently pointing - * toward. - */ - switch(dir) - { - case 0: pz++; break; - case 1: px++; pz++; break; - case 2: px++; break; - } - // Default in case no neighbor. - int regionThisDirection = NULL_REGION; - final OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null) - // There is a neighbor in this direction. - // Get its region ID. - regionThisDirection = nSpan.regionID(); - // Add the vertex to the contour. - outContourVerts.add(px); - outContourVerts.add(py); - outContourVerts.add(pz); - outContourVerts.add(regionThisDirection); - - // Remove the flag for this edge. We never need to consider - // it again since we have a vertex for this edge. - span.flags &= ~(1 << dir); - dir = (dir+1) & 0x3; // Rotate in clockwise direction. - } - else - { - /* - * The current direction does not point to an edge. So it - * must point to a neighbor span in the same region as the - * current span. Move to the neighbor and swing the search - * direction back one increment (counterclockwise). - * By moving the direction back one increment we guarantee we - * don't miss any edges. - */ - span = span.getNeighbor(dir); - // Update the span index based on the direction traveled to - // get to this neighbor. - switch(dir) - { - case 0: spanX--; break; - case 1: spanZ++; break; - case 2: spanX++; break; - case 3: spanZ--; break; - } - dir = (dir+3) & 0x3; // Rotate counterclockwise. - } - - if (span == startSpan && dir == startDirection) - // We have returned to the starting point. Time to stop the - // walk. The contour is complete. - break; - - } - - } - - /** - * Takes a group of vertices that represent a region contour and changes - * it in the following manner: - *
        - *
      • For any edges that connect to non-null regions, remove all - * vertices except the start and end vertices for that edge. (This - * smoothes the edges between non-null regions into a straight line.)
      • - *
      • Runs all algorithm's in {@link #mAlgorithms} against the contour.
      • - *
      - * @param regionID The region the contour was derived from. - * @param sourceVerts The source vertices that represent the complex - * contour in the form (x, y, z, regionID) - * @param outVerts The simplified contour vertices in the form: - * (x, y, z, regionID) - */ - private void generateSimplifiedContour(int regionID - , ArrayList sourceVerts - , ArrayList outVerts) - { - /* - * NOTE: In the output list, the forth field in each vertex contains - * the index of its corresponding source vertex. Only at the very end - * is the region information copied from the source to the output list. - */ - - boolean noConnections = true; - // Determine if this contour has any connections to non-null regions. - for (int pVert = 0; pVert < sourceVerts.size(); pVert += 4) - { - if (sourceVerts.get(pVert+3) != NULL_REGION) - { - // Found a non-null region connection. - noConnections = false; - break; - } - } - - // Seed the simplified contour with the mandatory edges. - // (At least one edge.) - if (noConnections) - { - /* - * This contour represents an island region surrounded only by the - * null region. Seed the simplified contour with the source's - * lower left (ll) and upper right (ur) vertices. - */ - int llx = sourceVerts.get(0); - int lly = sourceVerts.get(1); - int llz = sourceVerts.get(2); - int lli = 0; // Will be index of source vertex, not region. - int urx = sourceVerts.get(0); - int ury = sourceVerts.get(1); - int urz = sourceVerts.get(2); - int uri = 0; // Will be index of source vertex, not region. - // Loop through the source contour vertices and find the ur and - // ll vertices. - for (int pVert = 0; pVert < sourceVerts.size(); pVert += 4) - { - int x = sourceVerts.get(pVert); - int y = sourceVerts.get(pVert+1); - int z = sourceVerts.get(pVert+2); - if (x < llx || (x == llx && z < llz)) - { - // This the new lower left vertex. - llx = x; - lly = y; - llz = z; - lli = pVert / 4; - } - if (x >= urx || (x == urx && z > urz)) - { - // This is the new upper right vertex. - urx = x; - ury = y; - urz = z; - uri = pVert / 4; - } - } - // Seed the simplified contour with this edge. - outVerts.add(llx); - outVerts.add(lly); - outVerts.add(llz); - outVerts.add(lli); - - outVerts.add(urx); - outVerts.add(ury); - outVerts.add(urz); - outVerts.add(uri); - } - else - { - /* - * The contour shares edges with other non-null regions. - * Seed the simplified contour with a new vertex for every - * location where the region connection changes. These are - * vertices that are important because they represent portals - * to other regions. - */ - for (int iVert = 0, vCount = sourceVerts.size() / 4 - ; iVert < vCount - ; iVert++) - { - if (!sourceVerts.get(iVert*4+3) - .equals(sourceVerts.get(((iVert+1)%vCount)*4+3)) - ) - { - // The current vertex has a different region than the - // next vertex. So there is a change in vertex region. - outVerts.add(sourceVerts.get(iVert*4)); - outVerts.add(sourceVerts.get(iVert*4+1)); - outVerts.add(sourceVerts.get(iVert*4+2)); - outVerts.add(iVert); - } - } - } - - /* - * There are two situations where the out vert list may contain - * only two vertices. (An invalid polygon.) - * 1. The region is fully encompassed by the null region. - * 2. The region is encompassed by exactly two regions. - * This must be kept in mind since at least one vertex must be added - * back at some point. - * - * Though a region encompassed by two regions is technically a - * candidate for merging into one of the other regions, this is - * not done. It is the responsibility of region building to - * decide on such things. - */ - - // Run all post processing algorithms. These will build the final - // simplified contour from the seeded edges. - for (IContourAlgorithm algorithm : mAlgorithms) - { - algorithm.apply(sourceVerts, outVerts); - } - - if (outVerts.size() < 12) - { - /* - * Less than 3 vertices. - * - * This can occur in only one known case: The contour started - * with only two seed vertices and none of the algorithms added - * a vertex. - * - * This case is not completely unexpected. At this time, - * the contour algorithms only add vertices back if a null region - * edge is involved. So if a region is only surrounded by two - * non-null regions, it can end up in this situation. - * - * Find the vertex farthest from the current line segment - * and add it back to the contour. - * - * Design notes: - * - * This shouldn't happen very often. So I'm not optimizing it. - */ - int sourceVertCount = sourceVerts.size() / 4; - int iSelected = -1; - float maxDistance = 0; - int ax = outVerts.get(0); - int az = outVerts.get(2); - int bx = outVerts.get(4); - int bz = outVerts.get(6); - for (int iVert = 0; iVert < sourceVertCount; iVert++) - { - float dist = Geometry.getPointSegmentDistanceSq( - sourceVerts.get(iVert*4+0), - sourceVerts.get(iVert*4+2), - ax, - az, - bx, - bz); - if (dist > maxDistance) - { - maxDistance = dist; - iSelected = iVert; - } - } - // As selected vertex such that the contour stays - // wrapped clockwise. - if (iSelected < outVerts.get(3)) - { - // Insert selected vertex before other vertices. - outVerts.add(bx); - outVerts.add(outVerts.get(5)); - outVerts.add(bz); - outVerts.add(outVerts.get(7)); - outVerts.set(4, ax); - outVerts.set(5, outVerts.get(1)); - outVerts.set(6, az); - outVerts.set(7, outVerts.get(3)); - outVerts.set(0, sourceVerts.get(iSelected*4+0)); - outVerts.set(1, sourceVerts.get(iSelected*4+1)); - outVerts.set(2, sourceVerts.get(iSelected*4+2)); - outVerts.set(3, sourceVerts.get(iSelected)); - } - else if (iSelected < outVerts.get(7)) - { - // Insert selected vertex between other vertices. - outVerts.add(bx); - outVerts.add(outVerts.get(5)); - outVerts.add(bz); - outVerts.add(outVerts.get(7)); - outVerts.set(4, sourceVerts.get(iSelected*4+0)); - outVerts.set(5, sourceVerts.get(iSelected*4+1)); - outVerts.set(6, sourceVerts.get(iSelected*4+2)); - outVerts.set(7, sourceVerts.get(iSelected)); - } - else - { - // Insert selected vertex at end. - outVerts.add(sourceVerts.get(iSelected*4+0)); - outVerts.add(sourceVerts.get(iSelected*4+1)); - outVerts.add(sourceVerts.get(iSelected*4+2)); - outVerts.add(sourceVerts.get(iSelected)); - } - } - - // Replace the index pointers in the output list with region IDs. - final int sourceVertCount = sourceVerts.size() / 4; - final int simplifiedVertCount = outVerts.size() / 4; - for (int iVert = 0; iVert < simplifiedVertCount; ++iVert) - { - // The connected region id is taken from the next source point. - final int sourceVertIndex = - (outVerts.get(iVert * 4 + 3) + 1) % sourceVertCount; - outVerts.set(iVert * 4 + 3 - , sourceVerts.get(sourceVertIndex * 4 + 3)); - } - - /* - * Remove segments that will cause problems for the triangulation. - * - * There is a possibility that this will drop the vertices back below - * three. If this happens, nothing we can do about it. The contour - * will be lost. - */ - removeVerticalSegments(regionID, outVerts); - removeIntersectingSegments(regionID, outVerts); - } - - /** - * Removes segments that intersect with region portal segments. - * This can occur along the height axis in certain region configurations - * when detail is added back to a simplified contour. - *

      This is required to prevent triangluation failures later in - * the pipeline.

      - * @param regionID The region the contour was derived from. - * @param verts Contour vertices in the following form: (x, y, z, regionID) - */ - static void removeIntersectingSegments(int regionID - , ArrayList verts) - { - - /* Dev Notes: - * - * This is meant to be a temporary fix since it might remove - * important details. A more appropriate fix will require redesigning - * contour building into multiple stages so that detail can be - * added to portals such that both sides of the portal get the same - * detail. - * - * I'm a little worried about side effects from unanticipated - * contour configurations. - */ - - int startSize = verts.size(); - int vCount = startSize / 4; - for (int iVert = 0 - ; iVert < vCount - ; iVert++) - { - int iVertNext = (iVert+1)%vCount; - if (verts.get(iVertNext*4+3) != NULL_REGION) - { - // Segment iVert->iVertNext is a non-null region edge. - // Check for intersections. - iVert += removeIntersectingSegments(iVert - , iVertNext - , verts); // Offset will always be negative. - vCount = verts.size() / 4; - } - } - if (startSize != verts.size()) - { - logger.warning("Contour detail lost: Found and removed null" - + " region segments which were intersecting a portal." - + " Region: " + regionID + ", Segments removed: " - + (startSize - verts.size()) / 4); - } - } - - /** - * Merges segments such that no vertical segments exist. - * A vertical segment is a segment comprised of end points with - * duplicate (x, z) coordinates. - *

      This is required to prevent triangluation failures later in - * the pipeline.

      - * @param regionID The region the contour was derived from. - * @param verts Contour vertices in the following form: (x, y, z, regionID) - */ - static void removeVerticalSegments(int regionID, ArrayList verts) - { - /* - * Design Notes: - * - * Access level is set to internal to permit direct testing. - */ - - /* - * Remove vertical segments. - * - * Design notes: - * - * Protecting triangulation is more important than keeping region - * portals intact. So this algorithm will remove - * seed vertices if necessary. - * - * A potential enhancement is to have the algorithm try to detect - * the best vertex to remove from the pair. - * - * Another potential consideration: If otherwise there is no priority, - * Remove the vertex with the lowest y-value. This fits the general - * rule that the navigation mesh should be above the source geometry. - */ - - // Loop through all vertices starting with the last vertex. - for (int pVert = 0 ; pVert < verts.size();) - { - int pNextVert = (pVert+4)%verts.size(); - if (verts.get(pVert).equals(verts.get(pNextVert)) && - verts.get(pVert+2).equals(verts.get(pNextVert+2))) - { - // This segment represents a vertical line. - verts.remove(pNextVert); - verts.remove(pNextVert); // +1 - verts.remove(pNextVert); // +2 - verts.remove(pNextVert); // +3 - logger.warning("Contour detail lost: Removed a vertical" - + " segment from contour. Region: " + regionID); - } - else - pVert += 4; - } - - } - - /** - * Finds the correct height to use for a particular span vertex. - * (The vertex to the the right (clockwise) of the specified direction.) - * @param span A span on a region edge. - * @param direction A direction that points to a neighbor in a different - * region. (I.e. Crosses the border to a new region.) - * @return The height (y-value) to use for the vertex for this edge. - */ - static private int getCornerHeight(OpenHeightSpan span, int direction) - { - - /* - * This algorithm, while it uses similar processes as Recast, - * has been significantly adjusted. - * - * Examples: - * - Only 3 vertices are surveyed instead of the 4 - * the recast uses. - * - This algorithm searches more thoroughly for the diagonal neighbor. - * - * Reference: Neighbor search and nomenclature. - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - * - * See also: http://www.critterai.org/nmgen_contourgen#yselection - */ - - // Default height to the current floor. - int maxFloor = span.floor(); - - // The diagonal neighbor span to this corner. - OpenHeightSpan dSpan = null; - - // Rotate clockwise from original direction. - int directionOffset = (direction + 1) & 0x3; - - // Check axis neighbor in current direction. - OpenHeightSpan nSpan = span.getNeighbor(direction); - if (nSpan != null) - { - // Select for maximum floor using this neighbor. - maxFloor = Math.max(maxFloor, nSpan.floor()); - // Get diagonal neighbor. (By looking clockwise from this - // neighbor.) - dSpan = nSpan.getNeighbor(directionOffset); - } - // Check original span's axis-neighbor in clockwise direction. - nSpan = span.getNeighbor(directionOffset); - if (nSpan != null) - { - // Select for maximum floor using this neighbor. - maxFloor = Math.max(maxFloor, nSpan.floor()); - if (dSpan == null) - // Haven't found the diagonal neighbor yet. - // Try to get it by looking counter-clockwise - // from this neighbor. - dSpan = nSpan.getNeighbor(direction); - } - - if (dSpan != null) - // The diagonal neighbor was found. - // Select for maximum floor using this neighbor. - maxFloor = Math.max(maxFloor, dSpan.floor()); - - return maxFloor; - } - - /** - * Removes any null region segments that intersect with the - * specified edge. - *

      Concerning the return value:

      - *

      The start and end vertices are expected to be in the - * correct contour order. So the only time the start index will be - * greater than the end index in value is if the end index is zero.

      - *

      So the return value can be used to offset the the end index as - * well as the start index unless the end index is zero.

      - * @param startVertIndex The index of the edge's start index. - * @param endVertIndex The index of the edge's end index. - * @param verts Contour vertices in the following format: - * (x, y, z, regionID) - * @return If vertices were removed in such a way as to - * change the location of the start vertex, then this - * is the offset to apply to the startIndex. The value will always - * be <= 0. - */ - private static int removeIntersectingSegments(int startVertIndex - , int endVertIndex - , ArrayList verts) - { - - if (verts.size() < 16) - // Must have at least four vertices to have an intersection. - // This check is mandatory. An infinite loop will occur if - // there are less than four. - return 0; - - int offset = 0; - int startX = verts.get(startVertIndex*4+0); - int startZ = verts.get(startVertIndex*4+2); - int endX = verts.get(endVertIndex*4+0); - int endZ = verts.get(endVertIndex*4+2); - - int vCount = verts.size() / 4; - // Start at the line segment after the segment being - // checked and loop to the beginning of the segment being - // checked. - for (int iVert = (endVertIndex+2)%vCount - , iVertMinus = (endVertIndex+1)%vCount - ; iVert != startVertIndex - ;) - { - /* - * Only remove a vertex if it meets both of the following: - * - Both edges it belongs to connect to the null region. - * (null region segment - vertex - null region segment) - * - Belongs to a segment that intersects the segment being - * tested against. - */ - if (verts.get(iVert*4+3) == NULL_REGION - && verts.get(((iVert+1)%vCount)*4+3) == NULL_REGION - && Geometry.segmentsIntersect(startX - , startZ - , endX - , endZ - , verts.get(iVertMinus*4+0) - , verts.get(iVertMinus*4+2) - , verts.get(iVert*4+0) - , verts.get(iVert*4+2))) - { - // Remove the null region segment. - verts.remove(iVert*4); - verts.remove(iVert*4); // +1 - verts.remove(iVert*4); // +2 - verts.remove(iVert*4); // +3 - if (iVert < startVertIndex || iVert < endVertIndex) - { - // The removed vertex was stored before the line - // segment being tested. So the removal resulted - // in the segment indices shifting. - startVertIndex--; - endVertIndex--; - offset--; - } - // Segment has changed. Need to check the new segment. - // Adjust the indices as needed. - if (iVert < iVertMinus) - iVertMinus--; - vCount = verts.size() / 4; - iVert = iVert%vCount; - } - else - { - // Move to the next segment. - iVertMinus = iVert; - iVert = (iVert+1)%vCount; - } - } - return offset; - } -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/DetailMeshBuilder.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/DetailMeshBuilder.java deleted file mode 100644 index fcc097d2..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/DetailMeshBuilder.java +++ /dev/null @@ -1,2560 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.logging.Logger; - -/** - * Builds an triangle mesh from {@link OpenHeightfield } and - * {@link PolyMeshField} data. The polygon mesh field is triangulated and - * detail added as needed to match the surface of the mesh to the surface - * defined in the open heightfield. - *

      - * - * - *

      - * @see Detail Mesh Generation - * @see TriangleMesh - */ -public final class DetailMeshBuilder -{ - - /* - * Design notes: - * - * Recast Reference: rcBuildPolyMeshDetail in RecastMeshDetail.cpp - * - * Not adding configuration getters until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - */ - - /* - * TODO: EVAL: Need to review the process of loading and getting values - * from the height patch. - * - * Current design assumes that there are natural special cases that - * result in vertices improperly showing as outside of the patch. But - * it may be a design issue that needs fixing rather than true special - * cases such as floating point errors. See getHeightWithinField() for - * descriptions of the special cases currently being taken into account. - */ - - /** - * Represents height information for a portion (or patch) of a larger - * heightfield. - *

      Various fields indicate which portion of the source heightfield is - * represented.

      - *

      Unlike normal heightfields, this class cannot represent overlaps. - * Each grid location can only hold a single data point.

      - *

      Data is filled using a flood method. I.e. Start at a particular - * span in the source height field, and flood outward to the patch's - * boundaries.

      - *

      Since the value {@link #UNSET} is used to indicate the lack of - * data at a particular location, the effective maximum height value - * is {@link Integer#MAX_VALUE} - 1.

      - *

      WARNING: It is critical that public fields be set correctly. - * Otherwise operation exceptions may be thrown.

      - */ - private class HeightPatch - { - /** - * Indicates that data at a particular grid location has not been set. - * (Has no value.) After data has been loaded, this means - * that there is no valid height information for the particular grid - * location. - */ - public static final int UNSET = Integer.MAX_VALUE; - - /** - * The width index for the origin of this patch. - * (Should be a valid width index within the larger height field.) - */ - int minWidthIndex; - - /** - * The depth index for the origin of this patch. - * (Should be a valid depth index within the larger height field.) - */ - int minDepthIndex; - - /** - * The width of this patch as measured from the patch's origin. - */ - int width; - - /** - * The depth of this patch as measured from the patch's origin. - */ - int depth; - - /** - * Height data for this patch. - *

      Should normally use the {@link #setData(int, int, int) setData} - * and {@link #getData(int, int) getData} operations to access data - * in this array.

      - *

      Storage: [(Depth Data) (Depth Data) ... (Depth Data)] - * So the location of a particular data point is - * widthIndex * {@link #depth} + depthIndex

      - *

      Array should be sized such that it can hold at least - * {@link #width} x {@link #depth} worth of data.

      - */ - int[] data; - - /** - * Gets the height data for the patch location. - *

      The indices are auto-clamped.

      - * @param globalWidthIndex The width index of the grid location - * from the source height field. - * @param globalDepthIndex The depth index of the grid location - * from the source height field. - * @return The data stored a the grid location. - */ - public int getData(int globalWidthIndex, int globalDepthIndex) - { - // Do not remove auto-clamping. It is an important feature. - // See special case comments in getHeightWithinField() for - // details on why. - int idx = Math.min(Math.max( - globalWidthIndex - minWidthIndex, 0) - , width - 1) * depth - + Math.min(Math.max( - globalDepthIndex - minDepthIndex, 0) - , depth - 1); - return data[idx]; - } - - /** - * Indicates whether or not a global index (width, height) is - * within the bounds of the patch. - * @param globalWidthIndex The width index from the patch's - * source heightfield. - * @param globalDepthIndex The depth index from the patch's - * source heightfield. - * @return If the global index (width, height) is within the - * bounds of the patch. - */ - public boolean isInPatch(int globalWidthIndex, int globalDepthIndex) - { - return (globalWidthIndex >= minWidthIndex - && globalDepthIndex >= minDepthIndex - && globalWidthIndex < minWidthIndex + width - && globalDepthIndex < minDepthIndex + depth); - } - - /** - * Sets all values in the data array to {@link #UNSET}. - */ - public void resetData() - { - if (data == null) - return; - for (int i = 0; i < data.length; i++) - data[i] = UNSET; - } - - /** - * Sets the height data for the patch location. - *

      WARNING: No argument validation is performed. Calling code - * should perform all needed validations prior to calling this - * operation.

      - * @param globalWidthIndex The width index of the grid location - * from the source height field. - * @param globalDepthIndex The depth index of the grid location - * from the source height field. - * @param value The data to store at the grid location. - */ - public void setData(int globalWidthIndex - , int globalDepthIndex - , int value) - { - data[(globalWidthIndex - minWidthIndex)*depth - +globalDepthIndex-minDepthIndex] = value; - } - - } - - private static final Logger logger = - Logger.getLogger(DetailMeshBuilder.class.getName()); - - /** - * Information is undefined. (Not yet set.) - */ - private static final int UNDEFINED = -1; - - /** - * This side of the edge is external to the main polygon. (It is part - * of the polygon's hull.) - *

      Edges internal to the polygon (i.e. those created during - * triangulation) should never have this value.

      - */ - private static final int HULL = -2; - - /** - * The maximum number of vertices allowed for a triangulated polygon mesh. - *

      This value is arbitrary.

      - */ - private static final int MAX_VERTS = 256; - - /** - * The maximum number of edges that a single edge can be broken into - * during edge sampling. - *

      This value is arbitrary.

      - */ - private static final int MAX_EDGES = 64; - - /** - * Contour matching sample resolution. - *

      Impacts how well the final mesh conforms to surface data in the - * {@link OpenHeightfield} Higher values, closer conforming, higher - * final triangle count.

      - */ - private final float mContourSampleDistance; - - /** - * Contour matching maximum deviation. - *

      Impacts how well the final mesh conforms to the original meshes - * surface contour. Lower values, closer conforming, higher final - * triangle count.

      - */ - private final float mContourMaxDeviation; - - /** - * - * @param contourSampleDistance Sets the sampling distance to use when - * matching the final mesh to the surface defined by the - * {@link OpenHeightfield}. - *

      Impacts how well the final mesh conforms to surface data in the - * {@link OpenHeightfield} Higher values, closer conforming, higher - * final triangle count.

      - *

      Setting this argument to zero will disable this functionality.

      - *

      Constraints: >= 0

      - * - * @param contourMaxDeviation The maximum distance the surface of the - * navmesh may deviate from the surface data in the {@link OpenHeightfield}. - *

      The accuracy of the algorithm which uses this value is impacted by - * the value of the contour sample distance argument.

      - *

      The value of this argument has no meaning if the contour sample - * distance argument is set to zero.

      - *

      Setting the value to zero is not recommended since it can result - * in a large increase in the number of triangles in the final navmesh - * at a high processing cost.

      - *

      Constraints: >= 0

      - */ - public DetailMeshBuilder(float contourSampleDistance - , float contourMaxDeviation) - { - mContourSampleDistance = Math.max(0, contourSampleDistance); - mContourMaxDeviation = Math.max(0, contourMaxDeviation); - } - - /** - * Build a triangle mesh with detailed height information from the - * provided polygon mesh. - *

      Concerning sampling: Sampling functionality will only work - * correctly if the y-values in the source mesh are accurate to within - * {@link OpenHeightfield#cellHeight()} of an associated span within the - * provided height field. Otherwise the algorithms used by - * this operation may not be able to find accurate height information - * from the {@link OpenHeightfield}. - * @param sourceMesh The source polygon mesh to build the triangle - * mesh from. - * @param heightField The heightfield from which the {@link PolyMeshField} - * was derived. - * @return The generated triangle mesh. Or null if there were errors - * which prevented triangulation. - */ - public TriangleMesh build(PolyMeshField sourceMesh - , OpenHeightfield heightField) - { - if (sourceMesh == null - || sourceMesh.vertCount() == 0 - || sourceMesh.polyCount() == 0) - return null; - - // Create result object. - final TriangleMesh mesh = new TriangleMesh(); - - // Saves on divisions within loops. - final int sourcePolyCount = sourceMesh.polyCount(); - - // Convenience variables. - final float cellSize = sourceMesh.cellSize(); - final float cellHeight = sourceMesh.cellHeight(); - final float[] minBounds = sourceMesh.boundsMin(); - final int maxVertsPerPoly = sourceMesh.maxVertsPerPoly(); - final int[] sourceVerts = sourceMesh.verts; - final int[] sourcePolys = sourceMesh.polys; - - /* - * Contains the xz-plane bounds of each polygon. - * Entry format: (xmin, xmax, zmin, zmax) - * Uses the same index as sourcePolys. - */ - final int[] polyXZBounds = new int[sourcePolyCount * 4]; - - // The total number of polygon vertices. - // Needs to be calculated since the vertex count of the source - // polygons vary. - int totalPolyVertCount = 0; - - // The maximum width and depth found for the source polygons. - int maxPolyWidth = 0; - int maxPolyDepth = 0; - - /* - * Gather data. - * Loop through each polygon and find its xz bounds, the number of - * vertices, and the overall maximum polygon width and depth. - */ - for (int iPoly = 0; iPoly < sourcePolyCount; iPoly++) - { - final int pPoly = iPoly * maxVertsPerPoly * 2; - // These next variables are pointers to this poly's bound fields - // in polyXZBounds. - final int pxmin = iPoly*4; - final int pxmax = iPoly*4+1; - final int pzmin = iPoly*4+2; - final int pzmax = iPoly*4+3; - // Initialize the bounds fields to their extremes. - polyXZBounds[pxmin] = heightField.width(); - polyXZBounds[pxmax] = 0; - polyXZBounds[pzmin] = heightField.depth(); - polyXZBounds[pzmax] = 0; - // Loop through each vertex in the polygon, searching for - // minimum/maximum vertex values. - for (int vertOffset = 0; vertOffset < maxVertsPerPoly; vertOffset++) - { - if(sourcePolys[pPoly+vertOffset] == PolyMeshField.NULL_INDEX) - // Reached the end of this polygon's vertices. - break; - final int pVert = sourcePolys[pPoly+vertOffset]*3; - // Adjust the values of the bounds if this vertex - // represents a new min/max. - polyXZBounds[pxmin] = Math.min(polyXZBounds[pxmin] - , sourceVerts[pVert]); - polyXZBounds[pxmax] = Math.max(polyXZBounds[pxmax] - , sourceVerts[pVert]); - polyXZBounds[pzmin] = Math.min(polyXZBounds[pzmin] - , sourceVerts[pVert+2]); - polyXZBounds[pzmax] = Math.max(polyXZBounds[pzmax] - , sourceVerts[pVert+2]); - // Increment the total vertex count. - totalPolyVertCount++; - } - /* - * Clamp the values to one less than the minimum and one more - * than the maximum while staying within the valid field bounds. - * This ensures that when a height patch is created later, it is - * guaranteed to encompass the entire polygon. - */ - polyXZBounds[pxmin] = Math.max(0,polyXZBounds[pxmin] - 1); - polyXZBounds[pxmax] = Math.min(heightField.width() - ,polyXZBounds[pxmax] + 1); - polyXZBounds[pzmin] = Math.max(0,polyXZBounds[pzmin] - 1); - polyXZBounds[pzmax] = Math.min(heightField.depth() - ,polyXZBounds[pzmax] + 1); - if (polyXZBounds[pxmin] >= polyXZBounds[pxmax] - || polyXZBounds[pzmin] >= polyXZBounds[pzmax]) - // NO chance of this polygon being the max width/depth polygon. - continue; - // Record whether this polygon has the largest width of depth - // found so far. - maxPolyWidth = Math.max(maxPolyWidth - , polyXZBounds[pxmax] - polyXZBounds[pxmin]); - maxPolyDepth = Math.max(maxPolyDepth - , polyXZBounds[pzmax] - polyXZBounds[pzmin]); - } - - // Holds the vertices of the current polygon to be triangulated. - final float[] poly = new float[maxVertsPerPoly*3]; - int polyVertCount = 0; - - /* - * Holds the triangle indices generated for the current polygon. - * Form: (vertAIndex, vertBIndex, vertCIndex) - * Initialized to allow for an increase in vertices during sampling. - */ - ArrayList polyTriangles - = new ArrayList(maxVertsPerPoly * 2 * 3); - - /* - * Hold the vertex information for the triangles. - * If sampling occurs, there will be more vertices in this array - * than in the polygon array. Otherwise the content will be the same. - */ - final float[] polyTriangleVerts = new float[MAX_VERTS*3]; - int polyTriangleVertCount = 0; - - final HeightPatch hfPatch = new HeightPatch(); - if (mContourSampleDistance > 0) - /* - * The height patch is only used in the polygon detail - * operation if the sample distance is > 0. - * Set the bounds of the patch to be searched. - * Sized to hold the largest possible polygon. - */ - hfPatch.data = new int[maxPolyWidth * maxPolyDepth]; - - /* - * Values within working variables are irrelevant outside the - * operations in which they are used. Their only purpose is to - * save on object creation cost during loop iterations. - * Most initialization sizes are arbitrary. - */ - final ArrayDeque workingStack = - new ArrayDeque(256); - final ArrayDeque workingSpanStack = - new ArrayDeque(128); - final ArrayList workingEdges = - new ArrayList(MAX_EDGES * 4); - final ArrayList workingSamples = new ArrayList(512); - - /* - * A working array used while building the height path. - * Its data is not used within this operation. - */ - final int[] workingWidthDepth = new int[2]; - - /* - * Holds the aggregate vertices for the entire mesh. - * Form: (x, y, z) - */ - final ArrayList globalVerts = - new ArrayList(totalPolyVertCount * 2 * 3); - - /* - * Holds the aggregate triangles for the entire mesh. - * Format (vertAIndex, vertBIndex, vertCIndex, regionID) - * where vertices are wrapped clockwise and regionID is the region - * id of the source polygon the triangles were generated from. - */ - final ArrayList globalTriangles = - new ArrayList(totalPolyVertCount * 2 * 4); - - // Triangluate all polygons. - for (int iPoly = 0; iPoly < sourcePolyCount; iPoly++) - { - final int pPoly = iPoly*maxVertsPerPoly*2; - - // Loop through all vertices in the current polygon and - // load the working polygon array. - polyVertCount = 0; - for (int vertOffset = 0; vertOffset < maxVertsPerPoly; vertOffset++) - { - if(sourcePolys[pPoly+vertOffset] == PolyMeshField.NULL_INDEX) - // Reached the end of the polygon's verts. - break; - - final int pVert = sourcePolys[pPoly+vertOffset]*3; - - // Load the vertex information for the current polygon - // into the working poly array. - poly[vertOffset*3+0] = sourceVerts[pVert] * cellSize; - poly[vertOffset*3+1] = sourceVerts[pVert+1] * cellHeight; - poly[vertOffset*3+2] = sourceVerts[pVert+2] * cellSize; - - polyVertCount++; - - } - - if (mContourSampleDistance > 0) - { - // The height patch is only used if the sample - // distance is > 0. - - // Load height patch data for this polygon. - - // Set the bounds to the min/max for current polygon. - hfPatch.minWidthIndex = polyXZBounds[iPoly*4]; - hfPatch.minDepthIndex = polyXZBounds[iPoly*4+2]; - hfPatch.width = - polyXZBounds[iPoly*4+1] - polyXZBounds[iPoly*4+0]; - hfPatch.depth = - polyXZBounds[iPoly*4+3] - polyXZBounds[iPoly*4+2]; - - // Load the height data. - loadHeightPatch(pPoly - , polyVertCount - , sourcePolys - , sourceVerts - , heightField - , hfPatch - , workingStack - , workingSpanStack - , workingWidthDepth); - } - - // Triangulate this polygon. - polyTriangleVertCount = buildPolyDetail(poly - , polyVertCount - , heightField - , hfPatch - , polyTriangleVerts - , polyTriangles - , workingEdges - , workingSamples); - - if (polyTriangleVertCount < 3) - { - logger.severe("Generation of detail polygon failed:" - + " Polygon lost. Region: " - + sourceMesh.getPolyRegion(iPoly) - + ", Polygon index: " + iPoly); - continue; - } - - // Make sure the global lists are able to handle the new data. - globalVerts.ensureCapacity( - globalVerts.size() + polyTriangleVertCount * 3); - globalTriangles.ensureCapacity( - globalTriangles.size() + polyTriangles.size() * 4 / 3); - - // Represents the next available vertex index. - final int indexOffset = globalVerts.size() / 3; - - // Add all new vertices to the global vertices list. - for (int iVert = 0; iVert < polyTriangleVertCount; iVert++) - { - // Note: Converting from height field to world coordinates. - globalVerts.add(polyTriangleVerts[iVert*3] + minBounds[0]); - globalVerts.add(polyTriangleVerts[iVert*3+1] + minBounds[1]); - globalVerts.add(polyTriangleVerts[iVert*3+2] + minBounds[2]); - } - - // Add all new triangles to the global triangles list. - for (int pTriangle = 0 - ; pTriangle < polyTriangles.size() - ; pTriangle += 3) - { - // Offset the original vertex index to match the index in - // the global vertex list. - globalTriangles.add( - polyTriangles.get(pTriangle) + indexOffset); - globalTriangles.add( - polyTriangles.get(pTriangle+1) + indexOffset); - globalTriangles.add( - polyTriangles.get(pTriangle+2) + indexOffset); - // Record the region. - globalTriangles.add(sourceMesh.getPolyRegion(iPoly)); - } - } - - // Transfer the final results to the mesh object. - - // Load mesh object with vertex data. - mesh.vertices = new float[globalVerts.size()]; - for (int i = 0; i < globalVerts.size(); i++) - mesh.vertices[i] = globalVerts.get(i); - - // Load mesh object with the triangle indices and region information. - mesh.indices = new int[globalTriangles.size() * 3 / 4]; - final int tcount = globalTriangles.size() / 4; - mesh.triangleRegions = new int[tcount]; - for (int i = 0; i < tcount; i++) - { - // The index and region information is split and set to two - // different locations in the mesh object. - final int sourcePointer = i*4; - final int destinationPointer = i*3; - mesh.indices[destinationPointer] = - globalTriangles.get(sourcePointer); - mesh.indices[destinationPointer+1] = - globalTriangles.get(sourcePointer+1); - mesh.indices[destinationPointer+2] = - globalTriangles.get(sourcePointer+2); - mesh.triangleRegions[i] = globalTriangles.get(sourcePointer+3); - } - - return mesh; - - } - - /** - * Performs sampling and triangulation of the polygon. - *

      Sampling increases the detail of the polygon so that the height of - * the final triangle mesh better follows the height of its section of - * the heightfield.

      - *

      If the sample distance is > 0, sampling will occur. Otherwise - * sampling will not occur and the number of vertices in the final mesh - * will equal the number of vertices in the source polygon.

      - * @param sourcePoly Represents a list of vertices in the format - * (x, y, z) that represent a clockwise wrapped convex polygon. - * @param sourceVertCount The number of vertices in the source polygon. - * @param heightField The height field from which the polygon was derived. - * @param patch The loaded height patch to use for sample vertex - * height data. - *

      This parameter can be null if the the sample distance is <= 0.

      - * @param outVerts The vertices for the triangle mesh generated from - * the polygon. - *

      The array must be sized to be able to fit the maximum number of - * vertices that can be generated.

      - *

      The output may contain trash information. Only vertex locations - * which have an associated index in the output triangles list represent - * real vertices. - * @param outTriangles The indices of the triangle mesh generated from - * the polygon. Its content is cleared before use. - * @param workingEdges A working list used by this operation. Its - * content is undefined outside of this operation. Its content is - * cleared prior to use. - * @param workingSamples A working list used by this operation. Its - * content is undefined outside of this operation. Its content is - * cleared prior to use. - * @return The number of vertices in the outVerts array. - *

      For successful completion: Will equal the source vertex - * count if not new vertices were added. Otherwise be greater - * than the source vertex count by the number of vertices added.

      - *

      For a failure: The value will be zero. The polygon should be - * discarded.

      - */ - private int buildPolyDetail(float[] sourcePoly - , int sourceVertCount - , OpenHeightfield heightField - , HeightPatch patch - , float[] outVerts - , ArrayList outTriangles - , ArrayList workingEdges - , ArrayList workingSamples) - { - - // There is no early exit for a source vertex count of 3 - // (a triangle) since sampling may increase the vertex count. - - // TODO: EVAL: There is a lot of array object creation going on here. - // Investigate optimization. - - // TODO: EVAL: Should the height field reference be removed in favor - // of integer parameters for cell size and such? Parameter count is - // getting a bit unruly. Then again, this is a private operation. - - // Holds potential vertices for an edge that may be broken up into - // smaller edges. - final float[] workingVerts = new float[(MAX_EDGES+1)*3]; - - // Holds the indices to the actual smoothed edge definition. - // The indices reference vertices in the working vertices array. - final int[] workingIndices = new int[MAX_EDGES]; - int workingIndicesCount = 0; - - /* Contains indices of vertices that represent the hull of the - * polygon which the triangulation cannot alter. The content can be - * considered as "seed" edges for the triangulation and is not - * used unless the sample distance is > zero. - * Points to vertices in the output vertex array. - */ - final int[] hullIndices = new int[MAX_VERTS]; - int hullIndicesCount = 0; - - // Convenience variable and a variable to reduce number of divisions. - final float cellSize = heightField.cellSize(); - final float inverseCellSize = 1.0f/heightField.cellSize(); - - // Seed the output vertices array with the source vertices. - System.arraycopy(sourcePoly, 0, outVerts, 0, sourceVertCount*3); - - // The number of vertices in the final detail polygon. Will equal - // the source vertex count if no new vertices are added. This is - // the return value. - int outVertCount = sourceVertCount; - - // Any value sample vertex height value equal to or greater than - // this value means a height could not be found in the patch. - final float heightPathLimit = - HeightPatch.UNSET * heightField.cellHeight(); - - if (mContourSampleDistance > 0) - { - - /* - * Create the mandatory hull edges. - * - * The purpose of this algorithm is to better match the height - * of the polygon edges to the height of the source field. - * Vertices are added to edges so that the polygon's edges - * better fit the contour of the height field. - * - * This is the first of two sampling passes. In this pass only - * the edges are sampled. In the second pass, the inside of the - * polygon is sampled. - * - * See: http://www.critterai.org/nmgen_detailgen#edgedetail - */ - - // Loop through all source polygon edges. - for (int iSourceVertB = 0, iSourceVertA = sourceVertCount - 1 - ; iSourceVertB < sourceVertCount - ; iSourceVertA = iSourceVertB++) - { - int pSourceVertA = iSourceVertA*3; - int pSourceVertB = iSourceVertB*3; - boolean swapped = false; - /* - * Next section applies a consistent sort to the vertices so - * that segments are always processed in the same order. - * - * I.e. If VertexA and VertexB represent an edge shared - * between two polygons, then when this operation is called - * for each polygon, the edge vertices are processed in the - * same order no matter the order they are defined within - * each polygon. - * - * This prevents seams from forming between polygons due to - * floating point errors. - */ - if (Math.abs(sourcePoly[pSourceVertA] - - sourcePoly[pSourceVertB]) < Float.MIN_VALUE) - { - if (sourcePoly[pSourceVertA+2] > sourcePoly[pSourceVertB+2]) - { - pSourceVertA = iSourceVertB*3; - pSourceVertB = iSourceVertA*3; - swapped = true; - } - } - else if (sourcePoly[pSourceVertA] > sourcePoly[pSourceVertB]) - { - pSourceVertA = iSourceVertB*3; - pSourceVertB = iSourceVertA*3; - swapped = true; - } - - // Note: The ordering of the subtraction in these deltas - // is important. Later code depends on this ordering. - final float deltaX = - sourcePoly[pSourceVertB] - sourcePoly[pSourceVertA]; - final float deltaZ = - sourcePoly[pSourceVertB+2] - sourcePoly[pSourceVertA+2]; - final float edgeXZLength = - (float)Math.sqrt(deltaX * deltaX + deltaZ * deltaZ); - - // Get the maximum edge index. (This is purposely not an - // edge count.) This value is based on how many edge's this - // edge is allowed to be broken into. - int iMaxEdge = - 1 + (int)Math.floor(edgeXZLength/mContourSampleDistance); - // Clamp to max allowed edges. - iMaxEdge = Math.min(iMaxEdge, MAX_EDGES); - if (iMaxEdge + outVertCount >= MAX_VERTS) - // The addition of these new edges would result in - // too many vertices in the polygon. Adjust edge count - // so we don't exceed maximum allowed verts. - iMaxEdge = MAX_VERTS - 1 - outVertCount; - - /* - * Split the source edge into equally sized segments based - * on the maximum number of new edges allowed. - * - * The edge is being build from vertex A toward vertex B. - */ - for (int iEdgeVert = 0; iEdgeVert <= iMaxEdge; iEdgeVert++) - { - // This section of code depends on the delta's being A->B. - final float percentOffset = (float)iEdgeVert/iMaxEdge; - final int pEdge = iEdgeVert * 3; - workingVerts[pEdge] = - sourcePoly[pSourceVertA] + (deltaX * percentOffset); - workingVerts[pEdge+2] = - sourcePoly[pSourceVertA+2] + (deltaZ * percentOffset); - // Snap the y-value to a valid height in the height field. - workingVerts[pEdge+1] - = getHeightWithinField(workingVerts[pEdge] - , workingVerts[pEdge+2] - , cellSize - , inverseCellSize, patch) - * heightField.cellHeight(); - } - - /* - * The edges array now has a list of vertices that would - * represent the new edges if the source edge was to be - * broken up into the maximum number of edges allowed. - */ - - // Seed with the first and last vertices. - // The source edge's vertex A. - workingIndices[0] = 0; - // The sample vertex just before vertex B. - workingIndices[1] = iMaxEdge; - workingIndicesCount = 2; - - /* - * This loop incrementally inserts vertices into the - * working indices array when one is found to exceed the - * maximum allowed distance from the edge. Since the - * initialization of the working vertices array ensures - * that x and z-values will not deviate from the edge, this - * process only acts based on the y-value. - * - * Note that the increment for this loop happens internal - * to the loop. - */ - for (int iWorkingIndex = 0 - ; iWorkingIndex < workingIndicesCount - 1 - ; ) - { - // Define the end points of the current working segment. - final int iWorkingVertA = workingIndices[iWorkingIndex]; - final int iWorkingVertB = workingIndices[iWorkingIndex+1]; - final int pWorkingVertA = iWorkingVertA*3; - final int pWorkingVertB = iWorkingVertB*3; - // Search the vertices that are between these end points. - // Find the vertex that is farthest from the segment. - // (Has the maximum deviation from the segment.) - float maxDistanceSq = 0; - int iMaxDistanceVert = -1; - for (int iTestVert = iWorkingVertA + 1 - ; iTestVert < iWorkingVertB - ; iTestVert++) - { - if (workingVerts[iTestVert*3+1] >= heightPathLimit) - { - /* - * This vertex cannot be used. - * - * Special case: No valid height could be derived - * for the point. This is not necessarily an error, - * though it does indicate a potential problem - * with the configuration used for generation - * of the navigation mesh. - * - * Several potential causes: - * - The line segment crosses through a true null - * region (a region with no spans). E.g. - * polygon mesh doesn't have enough detail - * at null region border. - * - Error in input data. - * - Error in height patch build process. - */ - logger.warning("Potential loss of polygon height" - + "detail on polygon edge: Could not" - + "determine height for sample vertex at (" - + workingVerts[iTestVert*3+0] + ", " - + workingVerts[iTestVert*3+2] + ")." - + " Heightpatch data not availalable."); - continue; - } - float distanceSq = Geometry.getPointSegmentDistanceSq( - workingVerts[iTestVert*3] - , workingVerts[iTestVert*3+1] - , workingVerts[iTestVert*3+2] - , workingVerts[pWorkingVertA] - , workingVerts[pWorkingVertA+1] - , workingVerts[pWorkingVertA+2] - , workingVerts[pWorkingVertB] - , workingVerts[pWorkingVertB+1] - , workingVerts[pWorkingVertB+2]); - if (distanceSq > maxDistanceSq) - { - // Found a new maximum. - maxDistanceSq = distanceSq; - iMaxDistanceVert = iTestVert; - } - } - if (iMaxDistanceVert != -1 - && maxDistanceSq - > mContourMaxDeviation * mContourMaxDeviation) - { - // A vertex was found which exceeded the maximum - // allowed deviation from the current segment. - // Insert the vertex. - for (int i = workingIndicesCount - ; i > iWorkingIndex - ; i--) - workingIndices[i] = workingIndices[i-1]; - workingIndices[iWorkingIndex+1] = iMaxDistanceVert; - workingIndicesCount++; - } - else - iWorkingIndex++; - } - - // The working indices array now contains a list of vertex - // indices for an edge smoothed based on height. - - /* - * Add new vertices to the polygon. - * Build the hull. - * - * Notes: - * - * Remember that the output vertices array has already been - * seeded with the source indices in the same order as the - * source indices array. So the indices match between - * the source and output arrays for all original vertices. - * - * The new vertices are not added to the output vertex array - * in any particular order. That is why the hull array is - * required to determine proper ordering for the polygon. - */ - - // First add the start vertex for this new group of edges. - hullIndices[hullIndicesCount++] = iSourceVertA; - if (swapped) - { - // The original vertices for this edge had to be - // reversed for the previous calculations. So they need - // to be added to the hull array in reverse order. - for (int iWorkingIndex = workingIndicesCount - 2 - ; iWorkingIndex > 0 - ; iWorkingIndex--) - { - outVerts[outVertCount*3] = - workingVerts[workingIndices[iWorkingIndex]*3]; - outVerts[outVertCount*3+1] = - workingVerts[workingIndices[iWorkingIndex]*3+1]; - outVerts[outVertCount*3+2] = - workingVerts[workingIndices[iWorkingIndex]*3+2]; - hullIndices[hullIndicesCount++] = outVertCount; - outVertCount++; - } - } - else - { - for (int iWorkingIndex = 1 - ; iWorkingIndex < workingIndicesCount-1 - ; iWorkingIndex++) - { - outVerts[outVertCount*3] = - workingVerts[workingIndices[iWorkingIndex]*3]; - outVerts[outVertCount*3+1] = - workingVerts[workingIndices[iWorkingIndex]*3+1]; - outVerts[outVertCount*3+2] = - workingVerts[workingIndices[iWorkingIndex]*3+2]; - hullIndices[hullIndicesCount++] = outVertCount; - outVertCount++; - } - } - } - } - else - { - // There will be no adjustment to the edges of the polygon. - // Just use the order of the output vertices array since it - // contains a duplicate of the source polygon. - for (int i = 0; i < outVertCount ; i++) - hullIndices[i] = i; - hullIndicesCount = outVertCount; - } - - if (outVertCount > 3) - { - /* - * Perform the triangulation. - * Note: The only output expected is outTriangles. - * The rest of the variables with the prefix "out" are only inputs - * to this operation. - */ - performDelaunayTriangulation(outVerts - , outVertCount - , hullIndices - , hullIndicesCount - , workingEdges, outTriangles); - } - else if (outVertCount == 3) - { - // The output vertices form a triangle. - // Just copy it over. - outTriangles.clear(); - outTriangles.add(0); - outTriangles.add(1); - outTriangles.add(2); - } - else - { - // Invalid output polygon due to bad input data. - // Logging is handled by the caller. - outTriangles.clear(); - return 0; - } - - // Check validity of indices. - int badIndicesCount = - getInvalidIndicesCount(outTriangles, outVertCount); - if (badIndicesCount > 0) - { - logger.severe("Delaunay triangulation failure: Invalid indices" - + " detected edge detail step. Bad indices" - + " detected: " + badIndicesCount); - outTriangles.clear(); - return 0; - } - - if (mContourSampleDistance > 0) - { - - /* - * The purpose of this second pass is to sample the inside of - * the polygon and add internal triangles where the height field - * deviates too far from the mesh. - * - * This process has to be performed after the initial - * triangulation in order to get accurate mesh distance values. - */ - - // TODO: EVAL: Can time be saved by using the patch bounds instead - // of running these bounds calculations? - - // Get the bounds of the polygon in polygon space. - float minX = sourcePoly[0]; - float minZ = sourcePoly[2]; - float maxX = minX; - float maxZ = minZ; - for (int iVert = 1; iVert < sourceVertCount; iVert++) - { - int pVert = iVert*3; - minX = Math.min(minX, sourcePoly[pVert]); - minZ = Math.min(minZ, sourcePoly[pVert+2]); - maxX = Math.max(maxX, sourcePoly[pVert]); - maxZ = Math.max(maxZ, sourcePoly[pVert+2]); - } - - /* - * Build the sample grid. - * The next looping process builds a grid of points (x, y, z). - * The x and z-values are snapped to a grid that encompasses - * the entire source polygon and is incremented by the sample - * distance. - * The y-value is snapped to the closest height found in the - * height patch at the grid's (x, z) location. - */ - - // Convert the polygon bounds to sample grid space bounds. - final int x0 = (int)Math.floor(minX/mContourSampleDistance); - final int z0 = (int)Math.floor(minZ/mContourSampleDistance); - final int x1 = (int)Math.ceil(maxX/mContourSampleDistance); - final int z1 = (int)Math.ceil(maxZ/mContourSampleDistance); - - workingSamples.clear(); - - // Loop through all locations within the sample grid space - // and create a vertex for each location that is inside the - // source polygon. - for (int z = z0; z < z1; z++) - { - for (int x = x0; x < x1; x++) - { - // Need to figure out whether this grid location is - // outside or very close to the edge of the actual polygon. - // Converts back to polygon space. - final float vx = x * mContourSampleDistance; - // Converts back to polygon space. - final float vz = z * mContourSampleDistance; - - if (getSignedDistanceToPolygonSq(vx - , vz, sourcePoly - , sourceVertCount) - > -mContourSampleDistance/2) - // This location is either outside the polygon or - // very close to the the internal edge. Skip it. - continue; - - // Add the sample vertex to the grid. - workingSamples.add(x); - workingSamples.add(getHeightWithinField(vx - , vz - , cellSize - , inverseCellSize - , patch)); - workingSamples.add(z); - } - } - - final int sampleCount = workingSamples.size() / 3; - - // The only purpose of this outer loop is to provide a certain - // number of iterations. The inner loop does not depend in any way - // on the iteration count of the outer loop. - for (int iterationCount = 0 - ; iterationCount < sampleCount - ; iterationCount++) - { - - float selectedX = 0; - float selectedY = 0; - float selectedZ = 0; - float maxDistance = 0; - - // Loop through all sample vertices. - for (int iSampleVert = 0 - ; iSampleVert < sampleCount - ; iSampleVert++) - { - /* - * Design note: - * - * There is a potential that the y-value for a sample - * vertex will be > Integer.MAX_VALUE because a height - * value for the vertex could not be found in the height - * patch. - * - * Unlike for the edge vertices earlier, there is no known - * valid reason for this to occur, so it is not being - * checked and handled here. - * - * If it does occur, the symptom will be the insertion of - * a vertex with a very high y-value that will disrupt - * the mesh at its location. - */ - // Get the position of the sample in polygon space and - // its distance from the current mesh. - final float sampleX = - workingSamples.get(iSampleVert*3) - * mContourSampleDistance; - final float sampleY = - workingSamples.get(iSampleVert*3+1) - * heightField.cellHeight(); - final float sampleZ = - workingSamples.get(iSampleVert*3+2) - * mContourSampleDistance; - final float sampleDistance = getInternalDistanceToMesh( - sampleX - , sampleY - , sampleZ - , outVerts - , outTriangles); - - if (sampleDistance == UNDEFINED) - // This sample vertex is outside of the triangle mesh. - continue; - - if (sampleDistance > maxDistance) - { - // This sample vertex is farther from the mesh than - // any other found so far. - maxDistance = sampleDistance; - selectedX = sampleX; - selectedY = sampleY; - selectedZ = sampleZ; - } - } - - if (maxDistance <= mContourMaxDeviation) - // No sample vertex was found to be too far from the mesh. - // Can stop iterating early. - break; - - // Add this vertex to the output vertices. - // Note that since this is an internal vertex it is not part of - // a mandatory edge. (Not part of the hull.) - outVerts[outVertCount*3] = selectedX; - outVerts[outVertCount*3+1] = selectedY; - outVerts[outVertCount*3+2] = selectedZ; - outVertCount++; - - // Re-perform the triangulation with the new vertex. - // TODO: EVAL: A good candidate for optimizing. - // E.g. Insert rather than full rebuild. - performDelaunayTriangulation(outVerts - , outVertCount - , hullIndices - , hullIndicesCount - , workingEdges - , outTriangles); - - // Check validity of indices. - badIndicesCount = - getInvalidIndicesCount(outTriangles, outVertCount); - if (badIndicesCount > 0) - { - logger.severe("Delaunay triangulation failure: Invalid " - + "indices detected during internal detail" - + " iteration. Iteration: " + iterationCount - + ", Bad indices detected: "+ badIndicesCount); - outTriangles.clear(); - return 0; - } - - } - } - - return outVertCount; - } - - /** - * Generates data which represents the circumcircle of the triangle - * formed by the three points (A, B, C). - * @param triangleAreaX2 2x the area of the triangle formed by the - * points. The only reason for this parameter is for optimization. - * The only operation that calls this operation has already performed - * the area calculation, so why repeat it? - * @param outCircle The definition of the circumcircle in the form - * (x, y, r) where (x, y) is the center point and r is the radius. - * The value of (x, y) will be (0, 0) and r will be {@link #UNDEFINED} if - * this operation returns FALSE. - * @return TRUE if the circumcircle was successfully created. - * Otherwise FALSE. - */ - private static boolean buildCircumcircle(float ax - , float ay - , float bx - , float by - , float cx - , float cy - , float triangleAreaX2 - , float[] outCircle) - { - - /* - * References: - * http://en.wikipedia.org/wiki/Circumcenter#Coordinates_of_circumcenter - * http://mathworld.wolfram.com/Circumcircle.html - */ - - final float epsilon = 1e-6f; - - if (Math.abs(triangleAreaX2) > epsilon) - { - // Triangle has an area. Calculate center point of circle. - final float aLenSq = ax * ax + ay * ay; - final float bLenSq = bx * bx + by * by; - final float cLenSq = cx * cx + cy * cy; - outCircle[0] = (aLenSq * (by - cy) + bLenSq - * (cy - ay) + cLenSq * (ay - by)) / (2* triangleAreaX2); - outCircle[1] = (aLenSq * (cx - bx) + bLenSq - * (ax - cx) + cLenSq * (bx - ax)) / (2* triangleAreaX2); - // Calculate the radius of the circle. (Distance from center to - // one of the supplied points.) - outCircle[2] = (float)Math.sqrt( - getDistanceSq(outCircle[0], outCircle[1], ax, ay)); - return true; - } - - // Invalid triangle. - outCircle[0] = 0; - outCircle[1] = 0; - outCircle[2] = UNDEFINED; - return false; - } - - /** - * Attempts to form a new triangle on an UNDEFINED side of the specified - * edge. - *

      Will only attempt to form a new triangle for the first UNDEFINED - * side that is found.

      - *

      If a new triangle cannot be formed for the selected UNDEFINED side, - * then that side will be set to the value HULL.

      - *

      If a new triangle is formed, it is guaranteed to be complete. - * (I.e. All necessary data to form the triangle will exist in the - * edges list.)

      - * @param iEdge The index of the edge to perform the operation on. - * @param verts The available vertices in the format: (x, y, z) - * @param vertCount The number of vertices in the vertices array. - * @param currentTriangleCount The current number of triangles in the - * edges list. - * @param edges The edges list in the form: - * (vertA, vertB, valueA, valueB) where valueA is the side to the left - * of line segment vertA->vertB and valueB is the side to the left of - * line segment vertB->vertA. - * @return The new triangle count. If the return value is the same as - * currentTriangleCount then no new triangle could be formed. - */ - private static int completeTriangle(int iEdge - , float[] verts - , int vertCount - , int currentTriangleCount - , ArrayList edges) - { - - int iVertA; - int iVertB; - - if (edges.get(iEdge*4+2) == UNDEFINED) - { - // The side to the left of segment A->B is undefined. - iVertA = edges.get(iEdge*4); - iVertB = edges.get(iEdge*4+1); - } - else if (edges.get(iEdge*4+3) == UNDEFINED) - { - // The side to the left of segment B-A is undefined. - iVertA = edges.get(iEdge*4+1); - iVertB = edges.get(iEdge*4); - } - else - // Edge is already completed. No new faces. - return currentTriangleCount; - - final int pVertA = iVertA * 3; - final int pVertB = iVertB * 3; - - // The index of the best vertex on the left side of the edge. - int iSelectedVert = UNDEFINED; - - /* - * The definition of the selected circle in the format (x, z, r) - * where (x, z) is the center point and r is the radius. - * TODO: EVAL: Object creation. Convert to a working parameter? - */ - final float[] selectedCircle = { 0, 0, -1 }; - - // Values used to take into account floating point errors. - final float tolerance = 0.001f; - final float epsilon = 1e-5f; - - /* - * Loop through all the vertices. Find the vertex that is to the - * left of the edge (vertA->vertB) and forms the triangle with the - * smallest circumcircle. - * - * This process is difficult to optimize due to floating point - * errors. Especially when the source polygon is small in area. - * So the optimizations were abandoned. - */ - for (int iPotentialVert = 0 - ; iPotentialVert < vertCount - ; iPotentialVert++) - { - if (iPotentialVert == iVertA || iPotentialVert == iVertB) - // This vertex is one of the edge's vertices. Skip it. - continue; - - final int pPotentialVert = iPotentialVert * 3; - - final float area - = getSignedAreaX2(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pPotentialVert] - , verts[pPotentialVert+2]); - - if (area > epsilon) - { - // The three vertices form a triangle of adequate size AND the - // current vertex is to the left of the line segment - // vertA->vertB. - - if (selectedCircle[2] < 0) - { - // This is the first potentially valid vertex combination - // found so far. - if (overlapsExistingEdge(iVertA - , iPotentialVert - , verts - , edges) - || overlapsExistingEdge(iVertB - , iPotentialVert - , verts - , edges)) - // An overlap was found. Can't use this vertex. - continue; - // Vertex combination is valid. Try to use it. - if (buildCircumcircle(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pPotentialVert] - , verts[pPotentialVert+2] - , area - , selectedCircle)) - // Successfully created a circumcircle. - // Select this vertex. - iSelectedVert = iPotentialVert; - continue; - } - - // This is not the first valid combination found. - // Is it better than the existing? - - // Get the distance from the origin of the current - // circumcircle to this vertex. - final float distanceToOrigin = - (float)Math.sqrt(getDistanceSq(selectedCircle[0] - , selectedCircle[1] - , verts[pPotentialVert] - , verts[pPotentialVert+2])); - if (distanceToOrigin > selectedCircle[2] * (1 + tolerance)) - { - // This vertex is outside the current circumcircle and - // can be ignored. - continue; - } - else - { - /* - * The vertex is within, on, or almost on, the current - * circumcircle. - * - * If it were not for floating point errors, we could - * automatically accept all vertices that showed as - * within the current circumcircle. But floating point - * errors for small polygons prevent such a shortcut. - * - * Need to check if new edges formed by the use of this - * vertex will conflict with other edges already created. - */ - if (overlapsExistingEdge(iVertA - , iPotentialVert - , verts - , edges) - || overlapsExistingEdge(iVertB - , iPotentialVert - , verts - , edges)) - // An overlap was found. Can't use this vertex. - continue; - // Using this vertex is valid. - if (buildCircumcircle(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pPotentialVert] - , verts[pPotentialVert+2] - , area - , selectedCircle)) - // Successfully created a circumcircle. - // Select this vertex. - iSelectedVert = iPotentialVert; - } - } - } - - if (iSelectedVert != UNDEFINED) - { - // A new triangle can be formed. - - // Update triangle information of edge being completed. - updateLeftFace(iEdge, iVertA, currentTriangleCount, edges); - - // Add a new edge (selectedVert->vertA) or update face info - // of existing edge. - int iSelectedEdge = getEdgeIndex(edges, iSelectedVert, iVertA); - if (iSelectedEdge == UNDEFINED) - { - // This is a new edge. - edges.add(iSelectedVert); - edges.add(iVertA); - edges.add(currentTriangleCount); - edges.add(UNDEFINED); - } - else - // Update the existing edge. - updateLeftFace(iSelectedEdge - , iSelectedVert - , currentTriangleCount - , edges); - - // Add a new edge (vertB->selectedVert) or update face info - // of existing edge. - iSelectedEdge = getEdgeIndex(edges, iVertB, iSelectedVert); - if (iSelectedEdge == UNDEFINED) - { - // This is a new edge. - edges.add(iVertB); - edges.add(iSelectedVert); - edges.add(currentTriangleCount); - edges.add(UNDEFINED); - } - else - // Update the existing edge. - updateLeftFace(iSelectedEdge - , iVertB - , currentTriangleCount - , edges); - - // Indicate a new face was created. - currentTriangleCount++; - } - else - { - // A new face cannot be formed. Set the indicate the side of - // the edge is a hull. - updateLeftFace(iEdge, iVertA, HULL, edges); - } - - return currentTriangleCount; - } - - /** - * Attempts to find a span in the heightfield associated with the - * provided vertex. - *

      Spans that are within {@link OpenHeightfield#cellHeight()} of - * the vertices y-value take precedence in the search. Otherwise the - * span closest in height is returned.

      - * @param vertX The x-value of the vertex (x, y, z). - * @param vertY The y-value of the vertex (x, y, z). - * @param vertZ The z-value of the vertex (x, y, z). - * @param heightField The heightfield to search. - * @param outWidthDepth The actual width and depth index of the selected - * span in the form: (widthIndex, depthIndex). The array must be - * at least 2 in size. Content is undefined if the return value - * of the operation is null. - * @return The span in the feightfield that is best associated with - * the provided vertex. - */ - private static OpenHeightSpan getBestSpan(int vertX - , int vertY - , int vertZ - , OpenHeightfield heightField - , int[] outWidthDepth) - { - /* - * There are special cases which can result in the wrong span being - * returned by a simple column search. These special cases are what - * result in this a more complex search algorithm. - * - * In the best case search: Search up the height field column - * corresponding to the vertices x and z-values and return the - * span whose floor is within the correct tolerance of the y-value. - * - * While, technically, the best case search should always be - * successful, floating point errors and other special cases can - * result in a search failure. In such cases the search is expanded - * to the 8-neighbor cells, resulting in a slower search. - * - * If a search if forced to include neighbors, the search will - * always be a full 8-neighbor search. (No early exists.) - * - * Known special case when this occurs: - * - * The vertex lies on the outer edge of a border span. (The span - * edge across which there is no other span, at any height.) - * - * The vertex lies on the outer edge of a span without a connected - * neighbor. (The cell across the span edge contains spans, but - * none are connected as a neighbor to the span.) - * - * The scope of these special cases may not be fully known since - * a search failure can be hidden. E.g. When building a height - * patch, as long as one vertex in a polygon gets a good result, - * the flood fill algoritm can still succeed. The search failures - * will never be visible. There may be other special cases - * which are hidden in a similar manner. - * - * The known special cases are much less likely to exhibit when - * the source height field contains null (zero) region borders. - * This is because a border forces all vertices in from the region - * edges, which is where problems occur. - */ - - /* - * Search order starts with zero offset. - */ - final int[] targetOffset = - { 0,0, -1,0, 0,-1, -1,-1, 1,-1, -1,1, 1,0, 1,1, 0,1 }; - - OpenHeightSpan resultSpan = null; - int minDistance = Integer.MAX_VALUE; - // Loop through the offsets trying to find the best span match. - // Priority and potential early exit is given to spans at zero offset. - for (int p = 0; p < 17; p += 2) - { - int widthIndex = vertX + targetOffset[p]; - int depthIndex = vertZ + targetOffset[p+1]; - if (!heightField.isInBounds(widthIndex, depthIndex)) - // This neighbor is outside of the height field. - continue; - // Get the base span for this vertex from the height field. - OpenHeightSpan span = heightField.getData(widthIndex, depthIndex); - // Find the best span in the column. (Closest height match.) - span = getBestSpan(span, vertY); - if (span == null) - // No spans at the target location. - continue; - else - { - // Found a span. - int distance = Math.abs(vertY - span.floor()); - if (p == 0 && (distance <= heightField.cellHeight())) - { - // Found a span at a good height at the zero offset - // grid location. Don't search further. (Early exit.) - outWidthDepth[0] = widthIndex; - outWidthDepth[1] = depthIndex; - return span; - } - else if (distance < minDistance) - { - /* - * Could not find the "perfect" match. So dropping back - * to the best possible match. - * This span's floor is the closest to the vertex found - * so far. - */ - resultSpan = span; - outWidthDepth[0] = widthIndex; - outWidthDepth[1] = depthIndex; - minDistance = distance; - } - } - } - return resultSpan; - } - - /** - * Returns the span within the column whose floor is closest to the - * provided height. - * @param baseSpan Where to start the search. - * @param targetHeight The height to find the closest match for. - * @return The span whose floor is closest to the target height, or null - * if no base span was provided. - */ - private static OpenHeightSpan getBestSpan(OpenHeightSpan baseSpan - , int targetHeight) - { - int minDistance = Integer.MAX_VALUE; - OpenHeightSpan result = null; - // Loop up the column, starting at the base span. - for (OpenHeightSpan span = baseSpan; span != null; span = span.next()) - { - final int distance = Math.abs(targetHeight - span.floor()); - if (distance < minDistance) - { - // This span's floor is the closest to the vertex found so far. - result = span; - minDistance = distance; - } - } - return result; - } - - /** - * Returns the square of the distance between two points. - * @param ax The x-value of point (ax, ay). - * @param ay The y-value of point (ax, ay). - * @param bx The x-value of point (bx, by). - * @param by The y-value of point (bx, by). - * @return The square of the distance between two points. - */ - private static float getDistanceSq(float ax, float ay, float bx, float by) - { - final float deltaX = (ax - bx); - final float deltaY = (ay - by); - return deltaX * deltaX + deltaY * deltaY; - } - - /** - * Gets the index of the edge defined by two indices. - * @param edges The edge list where each edge is in the form: - * (vertIndex, vertIndex, value, value) - * @param vertAIndex The index of one of the edge's vertices. - * @param vertBIndex The index of the other of the edge's vertices. - * @return The index of the edge in the edges list which matches the - * provided vertices. Or {@link #UNDEFINED} if there is no corresponding - * edge. - */ - private static int getEdgeIndex(ArrayList edges - , int vertAIndex - , int vertBIndex) - { - final int edgeCount = edges.size() / 4; - for (int i = 0; i < edgeCount; i++) - { - final int u = edges.get(i*4); - final int v = edges.get(i*4+1); - if ((u == vertAIndex && v == vertBIndex) - || (u == vertBIndex && v == vertAIndex)) - return i; - } - return UNDEFINED; - } - - /** - * Get the height of the point within the height patch. - * @param x The world x position. - * @param z The world y position. - * @param minBounds The minimum bounds of the source field. - * @param cellSize The cell size of the source field. - * @param inverseCellSize The inverse of the cell size of the source - * field. (Included only to improve performance by avoiding a division - * within this operation.) - * @param patch The height patch to search. - * @return The height of the location within the patch. Or - * {@link Float#MAX_VALUE} if the - * search for a height fails. - */ - private static int getHeightWithinField(float x - , float z - , float cellSize - , float inverseCellSize - , HeightPatch patch) - { - /* - * There are two special cases when getting the height value: - * - * The x value is on the upper width edge of the source height field. - * The z value is on the upper depth edge of the source height field. - * - * In these cases this algorithm will create invalid indices for - * the height patch. (Out of bounds high.) Since the height patch - * is a private class (under strict control) it is being left up to - * the height patch class to clamp the index values so no exceptions - * are thrown. - * - * Note that these special cases refer to the source height field - * edges, not the height patch edges. This is because the height - * patch creation process always creates the patch to be slightly - * larger than the polygon being processed. The problem is that - * this slight expansion cannot occur when the height patch is up - * against the edges of source height field. - * - * The impact of these special cases is as follows: - * - * If x is on the upper width edge, then the same height value - * will be returned as is returned for (x - cellSize). - * - * If z is on the upper height edge, then the same value will be - * returned as is returned for (z - cellSize). - * - * This is not a significant issue. - */ - - // Convert world coordinates to height field indices. - final int widthIndex = (int)Math.floor(x * inverseCellSize + 0.01f); - final int depthIndex = (int)Math.floor(z * inverseCellSize + 0.01f); - // Get the height. - int height = patch.getData(widthIndex, depthIndex); - if (height == HeightPatch.UNSET) - { - /* - * One of the following special cases exist: - * - Data is bad. - * - Floating point calculation errors. - * - The vertex is in a true null region. (A region without - * any spans.) This can happen since sloppiness is permitted - * around null regions. - * Find nearest neighbor which has valid height. - * This is an 8 neighbor search. - */ - final int[] neighborOffset = - { -1,0, -1,-1, 0,-1, 1,-1, 1,0, 1,1, 0,1, -1,1}; - float minNeighborDistanceSq = Float.MAX_VALUE; - for (int p = 0; p < 16; p += 2) - { - int nWidthIndex = widthIndex + neighborOffset[p]; - int nDepthIndex = depthIndex + neighborOffset[p+1]; - if (!patch.isInPatch(nWidthIndex, nDepthIndex)) - // This neighbor is outside of the height patch. - continue; - int nNeighborHeight = patch.getData(nWidthIndex, nDepthIndex); - if (nNeighborHeight == HeightPatch.UNSET) - // This neighbor doesn't have a value either. - continue; - // Get distance from this neighbor to the target location. - float deltaWidth = (nWidthIndex + 0.5f) * cellSize - x; - float deltaDepth = (nDepthIndex + 0.5f) * cellSize - z; - float neighborDistanceSq = - deltaWidth*deltaWidth + deltaDepth*deltaDepth; - if (neighborDistanceSq < minNeighborDistanceSq) - { - // This is the closest neighbor found so far. - height = nNeighborHeight; - minNeighborDistanceSq = neighborDistanceSq; - } - } - } - return height; - } - - /** - * Returns the approximate y-axis distance of a point from the triangle - * mesh. - *

      If the point is not within the (x, z) plane projection of the - * mesh then {@link #UNDEFINED} will be returned.

      - * @param px The x-value of the point to be tested. (px, py, pz) - * @param py The y-value of the point to be tested. (px, py, pz) - * @param pz The z-value of the point to be tested. (px, py, pz) - * @param verts The vertices of the mesh to test against. - * @param indices The indices for the mesh to test against. - * @return The approximate y-axis distance of a point from the - * triangle mesh. - */ - private static float getInternalDistanceToMesh(float px - , float py - , float pz - , float[] verts - , ArrayList indices) - { - - float minDistance = Float.MAX_VALUE; - - final int triangleCount = indices.size() / 3; - // Loop through all triangles in the mesh and get the point's y-distance - // from any triangles the point lies within. The goal is to find - // the minimum (closest to the mesh) y-distance. - for (int iTriangle = 0; iTriangle < triangleCount; iTriangle++) - { - final int pVertA = indices.get(iTriangle*3)*3; - final int pVertB = indices.get(iTriangle*3+1)*3; - final int pVertC = indices.get(iTriangle*3+2)*3; - - float distance = Float.MAX_VALUE; - - final float deltaACx = verts[pVertC] - verts[pVertA]; - final float deltaACy = verts[pVertC+1] - verts[pVertA+1]; - final float deltaACz = verts[pVertC+2] - verts[pVertA+2]; - - final float deltaABx = verts[pVertB] - verts[pVertA]; - final float deltaABy = verts[pVertB+1] - verts[pVertA+1]; - final float deltaABz = verts[pVertB+2] - verts[pVertA+2]; - - final float deltaAPx = px - verts[pVertA]; - final float deltaAPz = pz - verts[pVertA+2]; - - final float dotACAC = deltaACx * deltaACx + deltaACz * deltaACz; - final float dotACAB = deltaACx * deltaABx + deltaACz * deltaABz; - final float dotACAP = deltaACx * deltaAPx + deltaACz * deltaAPz; - final float dotABAB = deltaABx * deltaABx + deltaABz * deltaABz; - final float dotABAP = deltaABx * deltaAPx + deltaABz * deltaAPz; - - // Compute barycentric coordinates - final float inverseDenominator = 1.0f - / (dotACAC * dotABAB - dotACAB * dotACAB); - final float u = (dotABAB * dotACAP - dotACAB * dotABAP) - * inverseDenominator; - final float v = (dotACAC * dotABAP - dotACAB * dotACAP) - * inverseDenominator; - - final float tolerance = 1e-4f; - if (u >= -tolerance && v >= -tolerance && (u + v) <= 1 + tolerance) - { - // The point lies inside the (x, z) plane projection of - // the triangle. Interpolate the y value. - final float y = verts[pVertA+1] + deltaACy * u + deltaABy * v; - distance = Math.abs(y - py); - } - - if (distance < minDistance) - minDistance = distance; - } - if (minDistance == Float.MAX_VALUE) - // The point does not lie within the (x, z) plane projection - // of the mesh. So it is invalid. - return UNDEFINED; - - return minDistance; - } - - /** - * Detects whether an indices list contains any obviously invalid - * values. - *

      An invalid index: index < 0 or index >= vertCount. - *

      - * This check exists because the triangulation can be a bit dodgy when - * dealing with very small triangles. It helps detect these issues so - * crashes can be avoided. - *

      - * @param indices The detailed polygon indices in the form: - * (vertA, vertB, vertC) - * @param vertCount The number of vertices in the vertices array - * which the indices refer to. - * @return The number of invalid indices detected. - */ - private static int getInvalidIndicesCount(ArrayList indices - , int vertCount) - { - int badIndicesCount = 0; - for (int i = 0; i < indices.size(); i++) - { - int index = indices.get(i); - if (index < 0 || index >= vertCount) - badIndicesCount++; - } - return badIndicesCount; - } - - /** - * Returns the distance squared from the point to the line segment. - * @param px The x-value of point (px, py). - * @param py The y-value of point (px, py) - * @param ax The x-value of the line segment's vertex A. - * @param ay The y-value of the line segment's vertex A. - * @param bx The x-value of the line segment's vertex B. - * @param by The y-value of the line segment's vertex B. - * @return The distance squared from the point (px, py) to line segment AB. - */ - private static float getPointSegmentDistanceSq(float px - , float py - , float ax - , float ay - , float bx - , float by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line segment - * AB that is closest to P and then calculate the distance between - * P and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = deltaABx * deltaABx - + deltaABy * deltaABy; - - if (segmentABLengthSq == 0) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = (deltaAPx * deltaABx + deltaAPy * deltaABy) - / segmentABLengthSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and - // closer to A. So return distanceSq from P to A. - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) + (py - by)*(py - by); - - // Closest point on lineAB is inside segment AB. So find the exact - // point on AB and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on - // the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle defined by points (A, B, C). - *

      A positive value indicates:

      - *
        - *
      • Counterclockwise wrapping of the points.
      • - *
      • Point B lies to the right of line AC, looking from A to C.
      • - *
      - *

      A negative value indicates:

      - *
        - *
      • Clockwise wrapping of the points.
      • - *
      • Point B lies to the left of line AC, looking from A to C.
      • - *
      - *

      A value of zero indicates that all points are collinear or - * represent the same point. - *

      Each call to this operation results in 2 multiplications and 5 - * subtractions.

      - * @param ax The x-value for point (ax, ay) for vertex A of the triangle. - * @param ay The y-value for point (ax, ay) for vertex A of the triangle. - * @param bx The x-value for point (bx, by) for vertex B of the triangle. - * @param by The y-value for point (bx, by) for vertex B of the triangle. - * @param cx The x-value for point (cx, cy) for vertex C of the triangle. - * @param cy The y-value for point (cx, cy) for vertex C of the triangle. - * @return The signed value of two times the area of the triangle defined - * by the points (A, B, C). - */ - private static float getSignedAreaX2(float ax - , float ay - , float bx - , float by - , float cx - , float cy) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm - // #Modern%20Triangles - // http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - - /** - * Returns the distance squared from the point to the closest polygon - * segment on the (x, z) plane. - * If the return value is positive, the point is outside the polygon. - * @param x The x-value of the test point (x, z). - * @param z The y-value of the test point (x, z). - * @param verts The polygon vertices in the form - * (ax, ay, az, bx, by, bz, ..., nx, ny, nz, trash) - * @param vertCount The number of vertices in the polygon. - * @return The distanceSq from the point to the closest polygon - * segment on the (x, z) plane. - */ - private static float getSignedDistanceToPolygonSq(float x - , float z - , float[] verts - , int vertCount) - { - float minDistance = Float.MAX_VALUE; - int iVertB; - int iVertA; - boolean isInside = false; - // Loop through all edges of the polygon and determine the distance - // from (x, y) to the edge. - for (iVertB = 0, iVertA = vertCount-1 - ; iVertB < vertCount - ; iVertA = iVertB++) - { - final int pVertB = iVertB*3; - final int pVertA = iVertA*3; - if (((verts[pVertB+2] > z) != (verts[pVertA+2] > z)) - && (x < (verts[pVertA]-verts[pVertB]) * (z-verts[pVertB+2]) - / (verts[pVertA+2]-verts[pVertB+2]) - + verts[pVertB]) ) - // The point is inside the polygons (x,z) plane's column. - isInside = true; - // Get the distance from the point to this edge and compare it - // to the current minimum distance. - minDistance = Math.min(minDistance - , getPointSegmentDistanceSq(x - , z - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2])); - } - return isInside ? -minDistance : minDistance; - } - - /** - * Fills the data array of a height patch with height data. Height - * data is chosen from the heightfield based on the provided polygon's - * vertices. - *

      The closest floor for each vertex is recorded, then this - * operation floods fills outward to all neighbors, recording neighbor - * floor heights, out to the edges of the height patch. - * @param polyPointer A pointer to the polygon whose vertices will be - * used as seed information when building the height data. - * @param vertCount The number of vertices in the polygon. - * @param indices Polygon indices data. - * @param verts Vertex data. - * @param inoutPatch The section of the height field to find height - * data for. Expects that the bounds data has been set. - * Expects data array to be pre-sized such that it can fit the maximum - * possible data. The data array values will be initialized to UNSET - * before being filled. - * @param gridIndexStack A working stack. Its data will be discarded - * prior to use. Content after the operation completes is undefined. - * @param spanStack A working stack. Its data will be discarded prior - * to use. Content after the operation completes is undefined. - * @param widthDepth A working array. Expected to be of size 2. - * Its content is undefined after operation completes. - */ - private static void loadHeightPatch(int polyPointer - , int vertCount - , int[] indices - , int[] verts - , OpenHeightfield heightField - , HeightPatch inoutPatch - , ArrayDeque gridIndexStack - , ArrayDeque spanStack - , int[] widthDepth) - { - // Initialization - inoutPatch.resetData(); - gridIndexStack.clear(); - spanStack.clear(); - - /* - * For each vertex, locate the span in the height field that is - * closest to it. Push the spans onto the stack. - * Only searching spans at the grid location of the vertex. - * (E.g. In the height column of the vertex.) - */ - - for (int vertOffset = 0; vertOffset < vertCount; vertOffset++) - { - // The width within the height field. - final int vertX = verts[indices[polyPointer+vertOffset]*3]; - // The height within the height field. - final int vertY = verts[indices[polyPointer+vertOffset]*3+1]; - // The depth within the height field. - final int vertZ = verts[indices[polyPointer+vertOffset]*3+2]; - - // Search for the best span in the height field for this vertex. - // Best span is the span whose floor area is closest to the - // vertex location. - final OpenHeightSpan selectedSpan = - getBestSpan(vertX, vertY, vertZ, heightField, widthDepth); - - if (selectedSpan != null) - { - // Found a span for this vertex. Push in onto the stack. - gridIndexStack.push(widthDepth[0]); - gridIndexStack.push(widthDepth[1]); - spanStack.push(selectedSpan); - } - } - - // NOTE: If the polygon mesh was properly built, the stack should - // always have a size greater than zero. - - /* - * Using the spans that have been seeded into the stacks, flood - * outward, recording the heights found for each grid location - * within the bounds of the patch. - */ - while(spanStack.size() > 0) - { - final int depthIndex = gridIndexStack.pop(); - final int widthIndex = gridIndexStack.pop(); - OpenHeightSpan span = spanStack.pop(); - - if (inoutPatch.getData(widthIndex, depthIndex) != HeightPatch.UNSET) - // This grid location was processed in an earlier iteration. - continue; - - if (inoutPatch.isInPatch(widthIndex, depthIndex)) - { - /* - * This span is in the height patch. Record the span's height. - * - * Note: It is a valid situation for the span to NOT be in - * the height patch. This can occur in the special cases - * described in detail in getHeightWithinField(). When this - * occurs, the algorithm depends on the neighbor search - * below to ensure the necessary flooding succeeds. - * E.g. One of the neighbors should end up within the - * bounds of the patch and continue the flooding. - */ - inoutPatch.setData(widthIndex, depthIndex, span.floor()); - } - - // "Flood" to the neighbors of this span. If a neighbor is within - // the patch's grid, then put it in the stacks for processing. - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null) - // No neighbor in this direction. - continue; - - final int nWidthIndex = - widthIndex + BoundedField.getDirOffsetWidth(dir); - final int nDepthIndex = - depthIndex + BoundedField.getDirOffsetDepth(dir); - - if (!inoutPatch.isInPatch(nWidthIndex, nDepthIndex)) - // This neighbor is outside the bounds of the patch. - // So skip it. - continue; - - if (inoutPatch.getData(nWidthIndex, nDepthIndex) != - HeightPatch.UNSET) - // This grid location was processed in an earlier iteration. - continue; - - // Need to process this neighbor. - gridIndexStack.push(nWidthIndex); - gridIndexStack.push(nDepthIndex); - spanStack.push(nSpan); - - } - } - } - - /** - * Checks whether or not a potential new edge intersects with any - * existing edge. Same and connected edges are ignored. - * @param iVertA The first vertex index of the potential new edge. - * @param iVertB The second vertex index of the potential new edge. - * @param verts The available vertices in the form (x, y, z) - * @param edges The edge definitions in the form - * (vertAIndex, vertBIndex, valueA, valueB) - * (valueA and valueB are not used by this operation.) - * @return TRUE if the potential new edge inappropriately intersects - * with an existing edge. - * Otherwise FALSE. - */ - private static boolean overlapsExistingEdge(int iVertA - , int iVertB - , float verts[] - , ArrayList edges) - { - // Loop through all edges. - for (int pEdge = 0; pEdge < edges.size(); pEdge += 4) - { - final int iEdgeVertA = edges.get(pEdge); - final int iEdgeVertB = edges.get(pEdge+1); - if (iEdgeVertA == iVertA - || iEdgeVertA == iVertB - || iEdgeVertB == iVertA - || iEdgeVertB == iVertB) - // Is same or connected edge. Ignore this edge. - continue; - if (segmentsOverlap(verts[iEdgeVertA*3] - , verts[iEdgeVertA*3+2] - , verts[iEdgeVertB*3] - , verts[iEdgeVertB*3+2] - , verts[iVertA*3] - , verts[iVertA*3+2] - , verts[iVertB*3] - , verts[iVertB*3+2])) - // The new edge overlaps this edge. - return true; - } - // No intersections detected. - return false; - } - - /** - * Attempts to perform a Delaunay triangulation on a group of vertices, - * potentially restricted by the content of the hull argument. - * @param verts The vertices to triangulate in the form (x, y, z). - * @param vertCount The number of vertices in the vertices array. - * @param immutableHull The indices that make up the required hull - * edges. These edges are guaranteed to be in the final triangulation. - *

      The indices in the hull array are expected to define a clockwise - * wrapped convex polygon. Behavior of the operation is undefined if - * this is not the case.

      - * @param hullEdgeCount The number of indices in the hull array. - * If zero, then there will be no guaranteed edges. - * @param workingEdges A working list used for internal purposes. Its - * only purpose as an argument is to save on object creation time. - * Its content is cleared before use. - * @param outTriangles The indices of the output triangle mesh in the - * form (vertAIndex, vertBIndex, vertCIndex). The indices refer to - * vertices in the vertices array. - *

      The list is cleared prior to use by this operation.

      - */ - private static void performDelaunayTriangulation(float[] verts - , int vertCount - , int[] immutableHull - , int hullEdgeCount - , ArrayList workingEdges - , ArrayList outTriangles) - { - - int triangleCount = 0; - workingEdges.clear(); - - /* - * General reference: - * http://en.wikipedia.org/wiki/Delaunay_triangulation - * More references at: - * http://digestingduck.blogspot.com/2009/10/ - * delaunay-triangulations.html - */ - - /* - * Entries in the working edges list is as follows: - * (vertA, vertB, valueA, valueB) - * where valueA is the side to the left of line segment vertA->vertB - * and valueB is the side to the left of line segment vertB->vertA - */ - - // Create an working edge entry for each hull edge. - for (int iHullVertB = 0, iHullVertA = hullEdgeCount-1 - ; iHullVertB < hullEdgeCount - ; iHullVertA = iHullVertB++) - { - workingEdges.add(immutableHull[iHullVertA]); - workingEdges.add(immutableHull[iHullVertB]); - // Since hull is expected to be clockwise wrapped, mark the - // left side of the edge as a hull. - workingEdges.add(HULL); - // Don't know what is on the right side of the edge yet. - // So default to undefined. - workingEdges.add(UNDEFINED); - } - - /* - * Loop through edges until all UNDEFINED sides have been defined. - * Notes: - * - The looping is expected to continue for longer than the original - * edge count since new edges will be created by the triangle - * completion operation. - * - No edge will ever be added to the edge list without at least - * one side already defined. So each edge will, at most, need a - * single triangle built for it. - */ - int iCurrentEdge = 0; - while (iCurrentEdge * 4 < workingEdges.size()) - { - if (workingEdges.get(iCurrentEdge*4+2) == UNDEFINED - || workingEdges.get(iCurrentEdge*4+3) == UNDEFINED) - // Need to create a triangle for one of the sides. - triangleCount = completeTriangle(iCurrentEdge - , verts - , vertCount - , triangleCount - , workingEdges); - iCurrentEdge++; - } - - /* - * Unless there is a logic error, at this point no side value in the - * edges array should have a value of UNDEFINED. They should all - * either be set to a triangle index or HULL. - * The strict HULL equality tests below, rather than just testing - * for >= 0, are meant to force logic errors to the surface. - */ - - // Fill the triangle list with the UNDEFINED value for each - // expected entry. - outTriangles.clear(); - outTriangles.ensureCapacity(triangleCount*3); - for (int i = 0; i < triangleCount * 3; i++) - outTriangles.add(UNDEFINED); - - // Loop through all edges. - for (int pEdge = 0; pEdge < workingEdges.size(); pEdge += 4) - { - - /* - * This algorithm is based on the following assumptions: - * - * Two of the three triangle vertices are known as soon as a - * triangle is first detected. Only the third vertex needs to - * be found. - * - * The edge building process guarantees that no partial - * triangles exist in the data. - */ - - // This strict test is meant to force logic errors to the surface. - // E.g. If an UNDEFINED value creeps into the working edges list. - if (workingEdges.get(pEdge+3) != HULL) - { - /* - * The right side of edge A->B has a associated triangle. - * This will always be the case for hull edges. - * Also indicates that A->B is the clockwise wrapping direction. - */ - - // Get a pointer to the triangle. - final int pTriangle = workingEdges.get(pEdge+3)*3; - - if (outTriangles.get(pTriangle) == UNDEFINED) - { - - /* - * This is the first time this triangle has been seen. - * - * Initialize this triangle by adding the edge's vertices - * to the triangle definition. - * - * Wrap A->B for clockwise. - */ - outTriangles.set(pTriangle, workingEdges.get(pEdge)); - outTriangles.set(pTriangle+1, workingEdges.get(pEdge+1)); - } - else if (outTriangles.get(pTriangle+2) == UNDEFINED) - { - // This triangle's first two vertices have already been - // set. Need to figure out which vertex in this edge - // is the final vertex. - if (workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle)) - || workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle+1))) - // The first vertex of this edge is already in the - // triangle. Add the second vertex of this edge to - // the triangle. - outTriangles.set(pTriangle+2 - , workingEdges.get(pEdge+1)); - else - /* - * The first vertex of this edge is NOT already in - * the triangle, so the 2nd vertex must already be - * in it. Add the first vertex of this edge to the - * triangle. - */ - outTriangles.set(pTriangle+2, workingEdges.get(pEdge)); - } - } - if (workingEdges.get(pEdge+2) != HULL) - { - /* - * The left side of edge A->B has an associated triangle. - * - * Indicates that B->A is the clockwise wrapping direction. - * - * This will never be the case for an original edge since - * original edges always have their left sides set to HULL. - */ - - final int pTriangle = workingEdges.get(pEdge+2)*3; - - if (outTriangles.get(pTriangle) == UNDEFINED) - { - - /* - * This is the first time this triangle has been seen. - * - * Trivia: Will only get here for internal triangles that - * don't have a hull edge. - * - * Initialize this triangle by adding the edge's vertices - * to the triangle definition. - * - * Wrap B->A for clockwise. - */ - outTriangles.set(pTriangle, workingEdges.get(pEdge+1)); - outTriangles.set(pTriangle+1, workingEdges.get(pEdge)); - } - else if (outTriangles.get(pTriangle+2) == UNDEFINED) - { - // This triangle's first two vertices have already been - // set. Need to figure out which vertex in this edge - // is the final vertex. - if (workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle)) - || workingEdges.get(pEdge).equals( - outTriangles.get(pTriangle+1))) - // The first vertex of this edge is already in the - // triangle. Add the second vertex of this edge to - // the triangle. - outTriangles.set(pTriangle+2 - , workingEdges.get(pEdge+1)); - else - /* - * The first vertex of this edge is NOT already in - * the triangle, so the 2nd vertex must already be - * in it. Add the first vertex of this edge to - * the triangle. - */ - outTriangles.set(pTriangle+2, workingEdges.get(pEdge)); - } - } - } - - } - - /** - * Returns TRUE if the line segments AB and CD intersect at one or - * more points. Otherwise FALSE. - * @param ax The x-value of point (ax, ay) for the line segment AB - * @param ay The y-value of point (ax, ay) for the line segment AB - * @param bx The x-value of point (bx, by) for the line segment AB - * @param by The y-value of point (bx, by) for the line segment AB - * @param cx The x-value of point (cx, cy) for the line segment CD - * @param cy The y-value of point (cx, cy) for the line segment CD - * @param dx The x-value of point (dx, dy) for the line segment CD - * @param dy The y-value of point (dx, dy) for the line segment CD - * @return TRUE if the line segments AB and CD intersect at one or - * more points. Otherwise FALSE. - */ - private static boolean segmentsOverlap(float ax - , float ay - , float bx - , float by - , float cx - , float cy - , float dx - , float dy) - { - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - - final float deltaCDx = dx - cx; - final float deltaCDy = dy - cy; - - final float deltaCAx = ax - cx; - final float deltaCAy = ay - cy; - - final float numerator = (deltaCAy * deltaCDx) - (deltaCAx * deltaCDy); - final float denominator = (deltaABx * deltaCDy) - (deltaABy * deltaCDx); - - final float tolerance = 0.001f; - - if (denominator == 0) - { - if (numerator != 0) - // Parallel and not colinear - return false; - /* - * Lines are colinear. But do the segments overlap? - * - * Note: This design takes into account that it is a - * logic error to call this operation for segments that share - * end points. - * - * Note: Since we know they are colinear, we only need to - * check one axis for overlap. - */ - if (Math.abs(cx - dx) < tolerance) - { - // Line is horizontal. Use y-axis. - if (Math.max(cy, dy) < Math.min(ay, by) - || Math.max(ay, by) < Math.min(cy, dy)) - // The end points of the segments don't overlap. - // No intersection. - return false; - else - // The end points of the segments overlap. Intersection. - return true; - } - else - { - if (Math.max(cx, dx) < Math.min(ax, bx) - || Math.max(ax, bx) < Math.min(cx, dx)) - // The end points of the segments don't overlap. - // No intersection. - return false; - else - // The end points of the segments overlap. Intersection. - return true; - } - } - - // Lines definitely intersect at a single point. - - float factorAB = numerator / denominator; - float factorCD = ((deltaCAy * deltaABx) - (deltaCAx * deltaABy)) - / denominator; - - // Determine the type of intersection - if ((factorAB >= 0.0f) - && (factorAB <= 1.0f) - && (factorCD >= 0.0f) - && (factorCD <= 1.0f)) - // Segments intersect. - return true; - - // Intersection is outside of one or both segments. - return false; - - } - - /** - * Sets the left face value of the specified edge to the specified value - * if the value is not already set. - *

      Note that this means that once the value has been set to a value - * other than UNDEFINED, this operation will not change the value.

      - * @param iEdge The index of the edge to update. - * @param iStartVert The vertex that represents the start of the edge. - * Used to determine which side of the edge is left. - * @param faceValue The new value to apply. - * @param edges The list of edges in the form - * (vertAIndex, vertBIndex, valueA, valueB) - * where valueA represents the left side of the edge A->B and valueB - * represents the left side of the edge B->A. - */ - private static void updateLeftFace(int iEdge - , int iStartVert - , int faceValue - , ArrayList edges) - { - final int pEdge = iEdge*4; - if (edges.get(pEdge) == iStartVert - && edges.get(pEdge+2) == UNDEFINED) - edges.set(pEdge+2, faceValue); - else if (edges.get(pEdge+1) == iStartVert - && edges.get(pEdge+3) == UNDEFINED) - edges.set(pEdge+3, faceValue); - } -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/FilterOutSmallRegions.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/FilterOutSmallRegions.java deleted file mode 100644 index 52335d57..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/FilterOutSmallRegions.java +++ /dev/null @@ -1,716 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Removes and merges small regions within a height field. - *

      Applies two algorithms:

      - *
        - *
      • Searches for island regions (regions only connected to the null region) - * and removes the ones that are smaller than the chosen threshold.
      • - *
      • If a region is below a threshold size, attempts to merge the region - * into the most appropriate larger neighbor region.
      • - *
      - * - * - * @see Region Generation - */ -public final class FilterOutSmallRegions - implements IOpenHeightFieldAlgorithm -{ - - /* - * Recast Reference: filerSmallRegions() in RecastRegion.cpp - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private final int mMinUnconnectedRegionSize; - private final int mMergeRegionSize; - - /** - * Constructor - * @param minUnconnectedRegionSize The minimum region size for - * unconnected (island) regions. (Voxels) - *

      Any generated regions that are not connected to any other region - * and are smaller than this size will be culled before final navmesh - * generation. I.e. No longer considered traversable.

      - *

      Constraints: > 0

      - * - * @param mergeRegionSize Any regions smaller than this size will, - * if possible, be merged with larger regions. (Voxels) - *

      Helps reduce the number of unnecessarily small regions that can - * be formed. This is especially an issue in diagonal path regions - * where inherent faults in the region generation algorithm can result in - * unnecessarily small regions.

      - *

      If a region cannot be legally merged with a neighbor region, then - * it will be left alone.

      - *

      Constraints: >= 0

      - * - * @see Detailed parameter information. - */ - public FilterOutSmallRegions(int minUnconnectedRegionSize - , int mergeRegionSize) - { - mMinUnconnectedRegionSize = Math.max(1, minUnconnectedRegionSize); - mMergeRegionSize = Math.max(0, mergeRegionSize); - } - - /** - * {@inheritDoc} - *

      The height field must contain valid region information in order - * for this algorithm to be effective.

      - */ - @Override - public void apply(OpenHeightfield field) - { - - if (field.regionCount() < 2) - // No spans or all spans are in the null region. - return; - - /* - * Over the life of the region array, the ids of region objects - * contained within the array may be changed as follows: - * - To the null region. This indicates the region has been - * abandoned. All spans assigned to it will be merged into - * the null region. - * - To another region id. This indicates that the spans - * assigned to the region will be re-assigned to the new - * region. (This occurs when region merging occurs.) - * So the index of the array indicates the original region id. The - * region objects within the array contain the current target - * region id. - */ - final Region[] regions = new Region[field.regionCount()]; - - for (int i = 0; i < field.regionCount(); i++) - { - regions[i] = new Region(i); - } - - final OpenHeightFieldIterator iter = field.dataIterator(); - - /* - * Region object initialization. - * For all non-null regions: - * - Tally the number of spans that belong to the region. - * - Record connections to other regions. (Including connections - * to the null region.) - * - Record regions that lie above (overlap) the region. - * (Only non-null regions.) - */ - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - - if (span.regionID() <= NULL_REGION) - // Span is in the null region. So skip it. - continue; - - // Get current span's region object and increment its membership - // count. - Region region = regions[span.regionID()]; - region.spanCount++; - - // Step up the list of spans above the current span. - for (OpenHeightSpan nextHigherSpan = span.next() - ; nextHigherSpan != null - ; nextHigherSpan = nextHigherSpan.next()) - { - if (nextHigherSpan.regionID() <= NULL_REGION) - // Span is in the null region. So ignore it. - continue; - if (!region.overlappingRegions.contains( - nextHigherSpan.regionID())) - // This is a previously undetected region above the - // current region. - region.overlappingRegions.add(nextHigherSpan.regionID()); - } - - if (region.connections.size() > 0) - // Have already found the connections for this span's region. - // So move to the next span. - continue; - - // Is this span on the edge of the its region? - int edgeDirection = getRegionEdgeDirection(span); - if (edgeDirection != -1) - // This is the first span detected that lies on the edge of - // its region. Can generate this region's the connection - // information. - findRegionConnections(span, edgeDirection, region.connections); - } - - /* - * Region information has been gathered. - * - * Find unconnected (island) regions that are below the allowed - * minimum size and convert them to null regions. - * - * This will result in all spans assigned to these regions being - * re-assigned to the null region. - * - * Starting at region 1 since zero is the null region. - */ - for (int regionID = 1; regionID < field.regionCount(); regionID++) - { - Region region = regions[regionID]; - if (region.spanCount == 0) - // Skip empty regions. - continue; - if (region.connections.size() == 1 - && region.connections.get(NULL_REGION) == NULL_REGION) - { - // This region is only connected to the null region. - // (It is an island region.) - if (region.spanCount < mMinUnconnectedRegionSize) - { - // This region is too small to be allowed as an - // island region. Make it a null region. - region.resetWithID(0); - } - } - } - - /* - * Search for small regions to merge with other regions. - * - * This is accomplished by searching for regions that are allowed to - * be merged with other regions, then searching through the region's - * connections for regions to be merged with. - * - * A region only looks for a single other region to merge with - * during each iteration of the loop. The loop will continue until - * no successful merges are detected. - * - * At the end of this process, regions that have been merged into - * other regions will have had their IDs replaced by the region's - * they were merged into. - * - * Example: - * - * Region 11 is at array index 11. It is merged with region 18 - * at index 18. After the merge, the region OBJECT at index 11 - * and will have an id of 18. - */ - int mergeCount; - do - { - mergeCount = 0; - // Loop through all regions. - for (Region region : regions) - { - if (region.id <= NULL_REGION || region.spanCount == 0) - // Skip null and empty regions. - continue; - - if (region.spanCount > mMergeRegionSize) - // Region is not a candidate for being merged into - // another region. - continue; - - // Region is either a small region, or a large region - // not connected to a null region. - // Find its smallest neighbor region. - Region targetMergeRegion = null; - int smallestSizeFound = Integer.MAX_VALUE; - // Loop through all region's neighbor (connections). - for (Integer nRegionID : region.connections) - { - if (nRegionID <= 0) - // This neighbor is the null region. So skip it. - continue; - final Region nRegion = regions[nRegionID]; - if (nRegion.spanCount < smallestSizeFound - && canMerge(region, nRegion)) - { - // This neighbor region is the smallest merge-able - // region found so far. - targetMergeRegion = nRegion; - smallestSizeFound = nRegion.spanCount; - } - } - // If a target was found, try to merge. - if (targetMergeRegion != null - && mergeRegions(targetMergeRegion, region)) - { - // A successful merge took place. - // Discard the old region and replace it with the region - // it was merged into. - final int oldRegionID = region.id; - region.resetWithID(targetMergeRegion.id); - // Update region ID in all regions which reference the - // discarded region. - for (Region r : regions) - { - if (r.id <= 0) - // Ignore null region. - continue; - if (r.id == oldRegionID) - // This region was merged into the old - // outdated region. Re-point its id to the new - // target region. - r.id = targetMergeRegion.id; - else - // Fix connection and overlap information. - replaceNeighborRegionID(r - , oldRegionID - , targetMergeRegion.id); - - } - mergeCount++; - } - } - // Continue looping as long as there were merges in the last iteration. - } while (mergeCount > 0); - - /* - * At this point the region ids may no longer be sequential. - * This next section re-maps the region ids so they are again - * sequential. - * - * Flag regions that need to be considered for id re-mapping. - * This flagging is necessary since multiple regions may be sharing - * the same id. Only want to consider a single id for mapping at - * a time. - */ - for (Region region : regions) - { - if (region.id > 0) - // This is not a null region. So it needs to be considered - // for remapping. - region.remap = true; - } - - // Next variable will be incremented to 1 the first iteration - // of the loop. - int currRegionID = 0; - for (Region region : regions) - { - if (!region.remap) - // Region already considered for re-mapping. - continue; - // Will re-assign all regions that use the current region ID to - // the next available sequential region ID. - currRegionID++; - final int oldID = region.id; - // Search all regions for ones using the old region ID. - for (Region r : regions) - { - if (r.id == oldID) - { - // This region uses the old ID. - // Re-assign it to the new ID. - r.id = currRegionID; - r.remap = false; // Don't consider this region again. - } - } - } - // Update the number of regions in the field. - // Add one to account for null region. - field.setRegionCount(currRegionID+1); - - // Finally, update the span region ID's to their final values. - iter.reset(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - if (span.regionID() == 0) - // Leave null regions alone. - continue; - else - // Re-map by getting the region object at the old index - // and assigning its current region id to the span. - span.setRegionID(regions[span.regionID()].id); - } - - } - - /** - * Determines if two regions can be legally merged. - *

      Regions cannot be merged if:

      - *
        - *
      • They do not connect.
      • - *
      • They connect at more than one point.
      • - *
      • They overlap vertically.
      • - *
      - *

      Behavior is undefined if either region is a null region.

      - * @param regionA A region connected with regionB. - * @param regionB A region connected with regionA. - * @return TRUE if the two regions can be merged. Otherwise FALSE. - */ - private static boolean canMerge(Region regionA, Region regionB) - { - // Only checking connections from A to B since checking B to A would - // be redundant. - int connectionsAB = 0; - for (Integer connectionID : regionA.connections) - { - if (connectionID == regionB.id) - // Connection detected. - connectionsAB++; - } - if (connectionsAB != 1) - /* - * Either the regions are not connected or there is a connection - * in more than one location. So a valid simple polygon can't - * be formed if the regions are merged. - */ - return false; - - // Can't merge regions that overlap vertically. - // This check needs to be checked in both directions due to the way - // the data is built. - if (regionA.overlappingRegions.contains(regionB.id)) - // Region B overlaps region A. Can't merge. - return false; - if (regionB.overlappingRegions.contains(regionA.id)) - // Region A overlaps region B. Can't merge. - return false; - - // OK to merge. - return true; - } - - /** - * Walks the edge of a region adding all neighbor region connections to - * a connection array. - *

      WARNING: Only run this operation on spans that are already known - * to be on a region edge. The direction must also be pointing to - * a valid edge.

      - * @param startSpan A span that is known to be on the edge of a region. - * @param startDirection The direction of the edge of the span that is - * known to point across the region edge. - * @param outConnections A reference to the region's connection object. - * This object will be filled with connection data. - */ - private static void findRegionConnections(OpenHeightSpan startSpan - , int startDirection - , ArrayList outConnections) - { - - /* - * Traversing the contour: A good way to visualize it is to think - * of a robot sitting on the floor facing a known wall. It then - * does the following to skirt the wall: - * 1. If there is a wall in front of it, turn clockwise in 90 degrees - * increments until it finds the wall is gone. - * 2. Move forward one step. - * 3. Turn counter-clockwise by 90 degrees. - * 4. Repeat from step 1 until it finds itself at its original - * location facing its original direction. - * - * See also: http://www.critterai.org/nmgen_contourgen#robotwalk - */ - - OpenHeightSpan span = startSpan; - int dir = startDirection; - // Default in case no neighbor exists. - int lastEdgeRegionID = NULL_REGION; - - // Add the first known connection. - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null) - // Found a neighbor in this direction. Use it's region ID. - lastEdgeRegionID = nSpan.regionID(); - // Add the first region ID to the list. - outConnections.add(lastEdgeRegionID); - - int loopCount = 0; - /* - * The loop limit is arbitrary. It exists only to guarantee that bad - * input data doesn't result in an infinite loop. The only down side - * of this loop limit is that it limits the number of detectable - * region connections. (The longer the region edge and the higher - * the number of "turns" in a region's edge, the less connections - * can be detected for that region.) - */ - while (++loopCount < 65534) - { - - // NOTE: The design of this loop is such that the span variable - // will always reference a span from the same region as the - // start span. - - nSpan = span.getNeighbor(dir); - // Default in case no neighbor exists. - int currEdgeRegionID = NULL_REGION; - if (nSpan == null || nSpan.regionID() != span.regionID()) - { - // The current direction points across a region edge. - if (nSpan != null) - // There is a span in this direciton. Get its region ID. - currEdgeRegionID = nSpan.regionID(); - if (currEdgeRegionID != lastEdgeRegionID) - { - // The region across this edge is different from - // the last edge region detected. (Is a transition to a - // new region connection.) Add it to the list. - outConnections.add(currEdgeRegionID); - lastEdgeRegionID = currEdgeRegionID; - } - - dir = (dir+1) & 0x3; // Rotate in clockwise direction. - - } - else - { - /* - * The current direction points to a neighbor in the same - * region as the current span. (And therefore in the same - * region as the start span.) - * Move to the neighbor and swing the search direction back - * one increment (counterclockwise). By moving the direction - * back one increment we guarantee we don't miss any edges. - */ - span = nSpan; - dir = (dir+3) & 0x3; // Rotate counterclockwise direction. - } - - if (startSpan == span && startDirection == dir) - // Have returned to the original span and direction. - // The search is complete. - break; - } - - // Make sure the first and last regions are not the same. This is - // the only type of connection adjacency that has the possibility - // of existing. - if (outConnections.size() > 1 - && outConnections.get(0) - .equals(outConnections.get(outConnections.size() - 1))) - // The fist and last connection is the same. - // Remove the last connection. - outConnections.remove(outConnections.size() - 1); - - } - - /** - * Checks to see if a span is on a region edge. If so, returns the - * direction of the neighbor region. - *

      This is an axis-neighbor search. Diagonal neighbors are not - * considered.

      - *

      The direction of the first detected neighbor region is - * returned.

      - * @param span The span to check. - * @return The direction of span edge that lies along a neighbor region, - * or -1 if the span is not on a region edge. - */ - private static int getRegionEdgeDirection(OpenHeightSpan span) - { - // Search axis-neighbors. - for (int dir = 0; dir < 4; ++dir) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null || nSpan.regionID() != span.regionID()) - // Doesn't have a neighbor or its neighbor is in a - // different region. - return dir; - } - // All neighbors are in the same region. - return -1; - } - - - /** - * Merges the candidate region into the target region. - *

      Only the target region is updated. The candidate is not altered. - * So if the candidate is to be discarded, it should be cleaned up after - * this operation successfully completes.

      - *

      IMPORTANT: The provided regions should already have been checked - * to ensure they are valid for merging. E.g. Using - * {@link #canMerge(Region, Region)}. Otherwise, behavior will be undefined. - * The only time this operation will detect a failure and abort - * (return false) is if the failure check is inherent to the merge - * process.

      - * @param target The region to merge the candidate into. - * @param candidate The region to merge into the target. - * @return TRUE if the spans in the candidate region were successfully - * added to the target region. - */ - private static boolean mergeRegions(Region target, Region candidate) - { - - // Get connection indices for target and candidate. - // (Where the two regions connect.) - final int connectionPointOnTarget = - target.connections.indexOf(candidate.id); - if (connectionPointOnTarget == -1) - // The target knows of no connection between the regions. - return false; - final int connectionPointOnCandidate = - candidate.connections.indexOf(target.id); - if (connectionPointOnCandidate == -1) - // The candidate knows of no connection between the regions. - return false; - - // Merging candidate into target. So need to save original target - // connections prior to the rebuilding them. - final ArrayList targetConns = - new ArrayList(target.connections); - - /* - * Merge connection information. - * - * Step 1: Rebuild the target connections. - * - * Start from the point just past where the candidate connection - * exists and loop back until just before the candidate connection. - * Scenario: - * Original target connections are 0, 2, 3, 4, 5 - * Merging with region 2. - * Then: - * Rebuild starting at index 2 and stop building at - * index 0 to get: 3, 4, 5, 0. - */ - target.connections.clear(); - int workingSize = targetConns.size(); - for (int i = 0; i < workingSize - 1; i++) - { - // The modulus calculation is what results in the wrapping. - target.connections.add(targetConns.get( - (connectionPointOnTarget + 1 + i) % workingSize)); - } - /* - * Step 2: Insert candidate connections into target connections at - * their mutual connection point. - * - * Same extraction process as for step one, but inserting data - * into target connection data. - * - * Scenario: - * Target connections after step 1 are 3, 4, 5, 0 - * Candidate connections are 3, 1, 0 - * Target region id is 1. - * Then: - * The loop will insert 0, 3 from the candidate at the end of - * the target connections. - * The final target connections: 3, 4, 5, 0, 0, 3 - * Note that this process can result in adjacent duplicate - * connections which will be fixed later. - */ - workingSize = candidate.connections.size(); - for (int i = 0; i < workingSize - 1; i++) - { - target.connections.add(candidate.connections.get( - (connectionPointOnCandidate + 1 + i) % workingSize)); - } - /* - * Step 3: Get rid of any adjacent duplicate connections that may - * have been created. - */ - removeAdjacentDuplicateConnections(target); - - // Add overlap data from the candidate to the target. - for (Integer i : candidate.overlappingRegions) - { - if (!target.overlappingRegions.contains(i)) - // This is a new overlap. Add it to the target. - target.overlappingRegions.add(i); - } - - // Merge span counts. - target.spanCount += candidate.spanCount; - - return true; - - } - - /** - * If a regions connection list contains adjacent duplicate connections, - * this operation removes them. Example of a cleanup: - * 3, 4, 5, 0, 0, 3 -> 4, 5, 0, 3 - * @param region The region to cleanup. - */ - private static void removeAdjacentDuplicateConnections(Region region) - { - int iConnection = 0; - // Loop through all adjacent connections. - while (iConnection < region.connections.size() - && region.connections.size() > 1) - { - int iNextConnection = iConnection+1; - if (iNextConnection >= region.connections.size()) - // Need to loop back to zero. - iNextConnection = 0; - if (region.connections.get(iConnection) - .equals(region.connections.get(iNextConnection))) - { - // Found duplicate. - // Remove duplicate and stay at current index. - region.connections.remove(iNextConnection); - } - else - // Move to next connection. - iConnection++; - } - } - - /** - * Searches through a region's connection and overlap information - * for any references to an old region ID and replaces with the new ID. - * @param region The region to perform the search and replace on. - * @param oldID The old region ID to replace. - * @param newID The ID to replace the old ID with. - */ - private static void replaceNeighborRegionID(Region region - , int oldID - , int newID) - { - boolean connectionsChanged = false; - // Perform the search and replace on the region connections. - for (int i = 0; i < region.connections.size(); i++) - { - if (region.connections.get(i) == oldID) - { - // Found a match. Replace it. - region.connections.set(i, newID); - connectionsChanged = true; - } - } - // Perform a search and replace on the overlap regions. - for (int i = 0; i < region.overlappingRegions.size(); i++) - { - if (region.overlappingRegions.get(i) == oldID) - // Found a match. Replace it. - region.overlappingRegions.set(i, newID); - } - if (connectionsChanged) - // Connections changed. This might have resulted in - // two connections being merged into one. Search for and - // fix as needed. - removeAdjacentDuplicateConnections(region); - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Geometry.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Geometry.java deleted file mode 100644 index b02be38e..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Geometry.java +++ /dev/null @@ -1,212 +0,0 @@ -package org.critterai.nmgen; - -/** - * Provides shared computational geometry operations. - *

      This is a temporary class. Its functionality will eventually - * be merged into classes in the utility library.

      - */ -public final class Geometry -{ - - /* - * Design Notes: - * - * Until computational geometry functions are moved to the utilities - * library, they will slowly be migrated here as needed for easier - * unit testing. - * - */ - - // TODO: GENERALIZATION: Move these algorithms to the utility library. - - private Geometry() { } - - /** - * Returns the distance squared from the point to the line segment. - *

      Behavior is undefined if the the closest distance is outside the - * line segment.

      - * @param px The x-value of point (px, py). - * @param py The y-value of point (px, py) - * @param ax The x-value of the line segment's vertex A. - * @param ay The y-value of the line segment's vertex A. - * @param bx The x-value of the line segment's vertex B. - * @param by The y-value of the line segment's vertex B. - * @return The distance squared from the point (px, py) to line segment AB. - */ - public static float getPointSegmentDistanceSq(int px, int py - , int ax, int ay - , int bx, int by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line segment AB - * that is closest to P and then calculate the distance between P - * and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = - deltaABx * deltaABx + deltaABy * deltaABy; - - if (segmentABLengthSq == 0) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = - (deltaAPx * deltaABx + deltaAPy * deltaABy) / segmentABLengthSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and - // closer to A. So return distanceSq from P to A. - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) + (py - by)*(py - by); - - // Closest point on lineAB is inside segment AB. So find the exact - // point on AB and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on - // the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - public static float getPointSegmentDistanceSq(float px - , float py - , float pz - , float ax - , float ay - , float az - , float bx - , float by - , float bz) - { - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaABz = bz - az; - float deltaAPx = px - ax; - float deltaAPy = py - ay; - float deltaAPz = pz - az; - - final float segmentABDistSq = deltaABx * deltaABx - + deltaABy * deltaABy - + deltaABz * deltaABz; - if (segmentABDistSq == 0) - // AB is not a line segment. So just return - // distanceSq from P to A. - return deltaAPx * deltaAPx - + deltaAPy * deltaAPy - + deltaAPz * deltaAPz; - - float u = (deltaABx * deltaAPx - + deltaABy * deltaAPy - + deltaABz * deltaAPz) / segmentABDistSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and - // closer to A. So return distanceSq from P to A. - return deltaAPx * deltaAPx - + deltaAPy * deltaAPy - + deltaAPz * deltaAPz; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) - + (py - by)*(py - by) - + (pz - bz)*(pz - bz); - - - // Closest point on lineAB is inside segment AB. So find the exact - // point on AB and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on - // the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - final float deltaZ = (az + u * deltaABz) - pz; - - return deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; - - } - - /** - * Returns TRUE if line segment AB intersects with line segment CD in any - * manner. Either collinear or at a single point. - * @param ax The x-value for point (ax, ay) in line segment AB. - * @param ay The y-value for point (ax, ay) in line segment AB. - * @param bx The x-value for point (bx, by) in line segment AB. - * @param by The y-value for point (bx, by) in line segment AB. - * @param cx The x-value for point (cx, cy) in line segment CD. - * @param cy The y-value for point (cx, cy) in line segment CD. - * @param dx The x-value for point (dx, dy) in line segment CD. - * @param dy The y-value for point (dx, dy) in line segment CD. - * @return TRUE if line segment AB intersects with line segment CD in any - * manner. - */ - public static boolean segmentsIntersect(int ax - , int ay - , int bx - , int by - , int cx - , int cy - , int dx - , int dy) - { - - /* - * This is modified 2D line-line intersection/segment-segment - * intersection test. - */ - - int deltaABx = bx - ax; - int deltaABy = by - ay; - int deltaCAx = ax - cx; - int deltaCAy = ay - cy; - int deltaCDx = dx - cx; - int deltaCDy = dy - cy; - - int numerator = (deltaCAy * deltaCDx) - (deltaCAx * deltaCDy); - int denominator = (deltaABx * deltaCDy) - (deltaABy * deltaCDx); - - // Perform early exit tests. - if (denominator == 0 && numerator != 0) - { - // If numerator is zero, then the lines are colinear. - // Since it isn't, then the lines must be parallel. - return false; - } - - // Lines intersect. But do the segments intersect? - - // Forcing float division on both of these via casting of the - // denominator. - float factorAB = numerator / (float)denominator; - float factorCD = ((deltaCAy * deltaABx) - (deltaCAx * deltaABy)) - / (float)denominator; - - // Determine the type of intersection - if ((factorAB >= 0.0f) - && (factorAB <= 1.0f) - && (factorCD >= 0.0f) - && (factorCD <= 1.0f)) - { - return true; // The two segments intersect. - } - - // The lines intersect, but segments to not. - - return false; - } -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/HeightSpan.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/HeightSpan.java deleted file mode 100644 index 2a21961f..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/HeightSpan.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents a span within the cell column of a heightfield. - * Spans represent one or more contiguous voxels. - * @see Introduction to Heightfields - */ -public final class HeightSpan -{ - - /* - * Recast Reference: rcSpan in Recast.h - */ - - private int mMinimum; - private int mMaximum; - private int mFlags = 0; - private HeightSpan mNext = null; - - /** - * Constructor - * @param min The minimum increment of the span. - * (Usually the height increment.) - * @param max The maximum increment of the span. - * (Usually the height increment.) - * @param flags The span flags. - * @throws IllegalArgumentException If the minimum is greater than or - * equal to the maximum. - */ - public HeightSpan(int min, int max, int flags) - throws IllegalArgumentException - { - if (min > max) - throw new IllegalArgumentException( - "Minimum is greater than or equal to the maximum."); - mMinimum = min; - mMaximum = max; - mFlags = flags; - } - - /** - * The flags for the span. - * @return The flags for the span. - */ - public int flags() { return mFlags; } - - /** - * The span maximum. - * @return The span maximum. - */ - public int max() { return mMaximum; } - - /** - * The span minimum. - * @return The span minimum. - */ - public int min() { return mMinimum; } - - /** - * The next span in the column. (Usually above the current span.) - * @return The next span in the column. Or null if there is no next span. - */ - public HeightSpan next() { return mNext; } - - /** - * Set the flags for the span. - * @param value The new flags for the span. - */ - public void setFlags(int value) { mFlags = value; } - - /** - * Sets the span maximum. - *

      Auto-clamps the value to ({@link #min()} + 1).

      - * @param value The new maximum. - */ - public void setMax(int value) - { - if (value <= mMinimum) - mMaximum = mMinimum + 1; - else - mMaximum = value; - } - - /** - * Sets the span minimum. - *

      Auto-clamps the value to ({@link #max()} - 1).

      - * @param value The new minimum. - */ - public void setMin(int value) - { - if (value >= mMaximum) - mMinimum = mMaximum - 1; - else - mMinimum = value; - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() - { - return mMinimum + "->" + mMaximum + ", Flags: " + mFlags; - } - - /** - * Set the next span value. - * @param value The new next span. (null is a valid value.) - */ - void setNext(HeightSpan value) { mNext = value; } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IContourAlgorithm.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IContourAlgorithm.java deleted file mode 100644 index ef906473..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IContourAlgorithm.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Provides for the application of an algorithm to a contour. - */ -public interface IContourAlgorithm -{ - /** - * Apply an algorithm to a contour. - *

      The implementation is permitted to require that the the result - * vertices be seeded with existing data. In this case the argument - * becomes an in/out argument rather than just an out argument.

      - * @param sourceVerts The source vertices that represent the contour - * in the form (x, y, z, regionID). - * @param resultVerts The contour vertices produced by the operation - * in the form (x, y, z, sourceIndex). - *

      Source index is the index (not pointer) of the related source - * vertex in sourcVerts. E.g. If the vertex in resultsList references - * the vertex at position 12 of sourceVerts, then sourceIndex will - * be 3 (12 / 4).

      - */ - void apply(ArrayList sourceVerts, ArrayList resultVerts); -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IOpenHeightFieldAlgorithm.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IOpenHeightFieldAlgorithm.java deleted file mode 100644 index 3c0aa62f..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IOpenHeightFieldAlgorithm.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Applies an algorithm to an {@link OpenHeightfield} - *

      The algorithm may require the field to be in a supported state. - * E.g. The regions must have been generated.

      - */ -public interface IOpenHeightFieldAlgorithm -{ - /** - * Applies the algorithm to the height field. - * @param field The field to apply the algorithm to. - */ - void apply(OpenHeightfield field); -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IntermediateData.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IntermediateData.java deleted file mode 100644 index 0353eeb4..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/IntermediateData.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * A class used to hold intermediate and performance data related to building - * the navigation mesh. - *

      The entire build process is represented when this data is combined with - * the source geometry and final navigation mesh.

      - */ -public final class IntermediateData -{ - - /* - * Recast Reference: None - */ - - /** - * The data is undefined. (Has not been set.) - */ - public static final long UNDEFINED = -1; - - /** - * The time to perform voxelization. (ns) - */ - public long voxelizationTime; - - /** - * The time to perform region generation. (ns) - */ - public long regionGenTime; - - /** - * The time to perform contour generation. (ns) - */ - public long contourGenTime; - - /** - * The time to perform polygon generation. (ns) - */ - public long polyGenTime; - - /** - * The time to perform the final triangulation. (ns) - */ - public long finalMeshGenTime; - - private SolidHeightfield mSolidHeightfield; - private OpenHeightfield mOpenHeightfield; - private ContourSet mContours; - private PolyMeshField mPolyMesh; - - /** - * The contour set associated with the open heightfield. - * @return The contours associated with the open heightfield. - */ - public ContourSet contours() { return mContours; } - - /** - * Returns the total time to generate the navigation mesh. (ns) - * @return The total time to generate the navigation mesh. (ns) - */ - public long getTotalGenTime() - { - if (finalMeshGenTime == UNDEFINED) - return UNDEFINED; - return voxelizationTime - + regionGenTime - + contourGenTime - + polyGenTime - + finalMeshGenTime; - } - - /** - * The open heightfield associated with the solid heightfield. - * @return The open heightfield associated with the solid heightfield. - */ - public OpenHeightfield openHeightfield() { return mOpenHeightfield; } - - /** - * The polygon mesh associated with the contour set. - * @return The polygon mesh associated with the contour set. - */ - public PolyMeshField polyMesh() { return mPolyMesh; } - - /** - * Resets all data to null. - */ - public void reset() - { - voxelizationTime = UNDEFINED; - regionGenTime = UNDEFINED; - contourGenTime = UNDEFINED; - polyGenTime = UNDEFINED; - finalMeshGenTime = UNDEFINED; - mSolidHeightfield = null; - mOpenHeightfield = null; - mContours = null; - mPolyMesh = null; - } - - /** - * Sets the contour set. - * @param contours The contour set. - */ - public void setContours(ContourSet contours) - { - mContours = contours; - } - - /** - * Sets the open heightfield. - * @param field The open heightfield. - */ - public void setOpenHeightfield(OpenHeightfield field) - { - mOpenHeightfield = field; - } - - /** - * Sets the polygon mesh. - * @param mesh The polygon mesh. - */ - public void setPolyMesh(PolyMeshField mesh) - { - mPolyMesh = mesh; - } - - /** - * Sets the solid height field. - * @param field The solid heightfield. - */ - public void setSolidHeightfield(SolidHeightfield field) - { - mSolidHeightfield = field; - } - - /** - * The solid heightfield associated with the source geometry. - * @return The solid heightfield derived from the source geometry. - */ - public SolidHeightfield solidHeightfield() { return mSolidHeightfield; } -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/MatchNullRegionEdges.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/MatchNullRegionEdges.java deleted file mode 100644 index 35b23fa0..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/MatchNullRegionEdges.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Applies an algorithm to contours which results in null-region edges - * following the original detail source geometry edge more closely. - * @see Visualizations - */ -public final class MatchNullRegionEdges - implements IContourAlgorithm -{ - - /* - * Recast Reference: simplifyContour() in RecastContour.cpp - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * The maximum distance the edge of the contour may deviate from the source - * geometry. - */ - private final float mThreshold; - - /** - * Constructor. - * @param threshold The maximum distance the edge of the contour may - * deviate from the source geometry. - *

      Setting this lower will result in the navmesh edges following the - * geometry contour more accurately at the expense of an increased - * vertex count.

      - *

      Setting the value to zero is not recommended since it can result - * in a large increase in the number of vertices at a high processing - * cost.

      - *

      Constraints: >= 0

      - */ - public MatchNullRegionEdges(float threshold) - { - this.mThreshold = Math.max(threshold, 0); - } - - /** - * {@inheritDoc} - *

      Adds vertices from the source list to the result list such that - * if any null region vertices are compared against the result list, - * none of the vertices will be further from the null region edges than - * the allowed threshold.

      - *

      Only null-region edges are operated on. All other edges are - * ignored.

      - *

      The result vertices is expected to be seeded with at least two - * source vertices.

      - */ - @Override - public void apply(ArrayList sourceVerts - , ArrayList inoutResultVerts) - { - if (sourceVerts == null || inoutResultVerts == null) - return; - - final int sourceVertCount = sourceVerts.size() / 4; - int simplifiedVertCount = inoutResultVerts.size() / 4; // Will change. - int iResultVertA = 0; - - /* - * Loop through all edges in this contour. - * - * NOTE: The simplifiedVertCount in the loop condition - * increases over iterations. That is what keeps the loop going beyond - * the initial vertex count. - */ - while (iResultVertA < simplifiedVertCount) - { - int iResultVertB = (iResultVertA + 1) % simplifiedVertCount; - - // The line segment's beginning vertex. - final int ax = inoutResultVerts.get(iResultVertA*4); - final int az = inoutResultVerts.get(iResultVertA*4+2); - final int iVertASource = inoutResultVerts.get(iResultVertA*4+3); - - // The line segment's ending vertex. - final int bx = inoutResultVerts.get(iResultVertB*4); - final int bz = inoutResultVerts.get(iResultVertB*4+2); - final int iVertBSource = inoutResultVerts.get(iResultVertB*4+3); - - // The source index of the next vertex to test. (The vertex just - // after the current vertex in the source vertex list.) - int iTestVert = (iVertASource + 1) % sourceVertCount; - float maxDeviation = 0; - - // Default to no index. No new vert to add. - int iVertToInsert = -1; - - if (sourceVerts.get(iTestVert*4+3) == NULL_REGION) - { - /* - * This test vertex is part of a null region edge. - * Loop through the source vertices until the end vertex - * is found, searching for the vertex that is farthest from - * the line segment formed by the begin/end vertices. - * - * Visualizations: - * http://www.critterai.org/nmgen_contourgen#nulledgesimple - */ - while (iTestVert != iVertBSource) - { - final float deviation = Geometry.getPointSegmentDistanceSq( - sourceVerts.get(iTestVert * 4) - , sourceVerts.get(iTestVert * 4 + 2) - , ax - , az - , bx - , bz); - if (deviation > maxDeviation) - { - // A new maximum deviation was detected. - maxDeviation = deviation; - iVertToInsert = iTestVert; - } - // Move to the next vertex. - iTestVert = (iTestVert+1) % sourceVertCount; - } - } - - if (iVertToInsert != -1 && maxDeviation > (mThreshold * mThreshold)) - { - // A vertex was found that is further than allowed from the - // current edge. Add this vertex to the contour. - inoutResultVerts.add((iResultVertA+1)*4 - , sourceVerts.get(iVertToInsert*4)); - inoutResultVerts.add((iResultVertA+1)*4+1 - , sourceVerts.get(iVertToInsert*4+1)); - inoutResultVerts.add((iResultVertA+1)*4+2 - , sourceVerts.get(iVertToInsert*4+2)); - inoutResultVerts.add((iResultVertA+1)*4+3 - , iVertToInsert); - // Update the vertex count since a new vertex was added. - simplifiedVertCount = inoutResultVerts.size() / 4; - // Not incrementing the vertex since we need to test the edge - // formed by vertA and this this new vertex on the next - // iteration of the loop. - } - else - // This edge segment does not need to be altered. Move to - // the next vertex. - iResultVertA++; - } - } -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/NavmeshGenerator.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/NavmeshGenerator.java deleted file mode 100644 index 94d75099..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/NavmeshGenerator.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Used to generate static triangle meshes representing the traversable - * surfaces of arbitrary source geometry. - *

      When the build operation is provided with source geometry, several - * meshes are generated which represent the traversable (walkable) - * surfaces of the source geometry. A large number of configuration options - * are used to adjust the final result.

      - *

      - *

      - * @see Project Home - * @see Process Overview - * @see Configuration Options - */ -public final class NavmeshGenerator -{ - - /* - * Design notes: - * - * Recast reference: Sample_StatMeshSimple.cpp - * - * Configuration getters will not be added until they are needed. - * Do not add setters. The design is meant to be thread friendly and - * setters would compromise that. - * Never add getters for the builder fields. That would not be thread - * friendly. - */ - - // The builders used by this class. - private final SolidHeightfieldBuilder mSolidHeightFieldBuilder; - private final OpenHeightfieldBuilder mOpenHeightFieldBuilder; - private final ContourSetBuilder mContourSetBuilder; - private final PolyMeshFieldBuilder mPolyMeshBuilder; - private final DetailMeshBuilder mTriangleMeshBuilder; - - /** - * Constructor - * @param cellSize The width and depth resolution used when sampling - * the source mesh. - *

      Constraints: > 0

      - * - * @param cellHeight The height resolution used when sampling the - * source mesh. - *

      Constraints: > 0

      - * - * @param minTraversableHeight Represents the minimum floor to ceiling - * height that will still allow the floor area to be considered walkable. - *

      Permits detection of overhangs in the geometry which make the - * geometry below become unwalkable.

      - *

      Constraints: > 0

      - * - * @param maxTraversableStep Represents the maximum ledge height that - * is considered to still be walkable. - *

      Prevents minor deviations in height from improperly showing - * as obstructions. Permits detection of stair-like structures, curbs, etc. - *

      - *

      Constraints: >= 0

      - * - * @param maxTraversableSlope The maximum slope that is considered - * walkable. (Degrees) - *

      Constraints: 0 <= value <= 85

      - * - * @param clipLedges Indicates whether ledges should be marked - * as unwalkable. - *

      A ledge is a normally walkable voxel that has one or more - * accessible neighbors with a an un-steppable drop from voxel top to - * voxel top.

      - *

      E.g. If an agent using the navmesh were to travel down from the - * ledge voxel to its neighbor voxel, it would result in the maximum - * traversable step distance being violated. The agent cannot legally - * "step down" from a ledge to its neighbor.

      - * - * @param traversableAreaBorderSize Represents the closest any part of - * the navmesh can get to an obstruction in the source mesh. - *

      Usually set to the maximum bounding radius of entities utilizing - * the navmesh for navigation decisions.

      - *

      Constraints: >= 0

      - * - * @param smoothingThreshold The amount of smoothing to be performed - * when generating the distance field. - *

      This value impacts region formation and border detection. A - * higher value results in generally larger regions and larger border - * sizes. A value of zero will disable smoothing.

      - *

      Constraints: 0 <= value <= 4

      - * - * @param useConservativeExpansion Applies extra algorithms to regions - * to help prevent poorly formed regions from forming. - *

      If the navigation mesh is missing sections that should be present, - * then enabling this feature will likely fix the problem

      - *

      Enabling this feature significantly increased processing cost.

      - * - * @param minUnconnectedRegionSize The minimum region size for - * unconnected (island) regions. (Voxels) - *

      Any generated regions that are not connected to any other region - * and are smaller than this size will be culled before final navmesh - * generation. I.e. No longer considered walkable.

      - *

      Constraints: > 0

      - * - * @param mergeRegionSize Any regions smaller than this size will, if - * possible, be merged with larger regions. (Voxels) - *

      Helps reduce the number of unnecessarily small regions that can - * be formed. This is especially an issue in diagonal path regions - * where inherent faults in the region generation algorithm can result in - * unnecessarily small regions.

      - *

      If a region cannot be legally merged with a neighbor region, then - * it will be left alone.

      - *

      Constraints: >= 0

      - * - * @param maxEdgeLength The maximum length of polygon edges that - * represent the border of the navmesh. - *

      More vertices will be added to navmesh border edges if this value - * is exceeded for a particular edge. In certain cases this will reduce - * the number of thin, long triangles in the navmesh.

      - *

      A value of zero will disable this feature.

      - *

      Constraints: >= 0

      - * - * @param edgeMaxDeviation The maximum distance the edge of the navmesh - * may deviate from the source geometry. - *

      Setting this lower will result in the navmesh edges following the - * geometry contour more accurately at the expense of an increased - * triangle count.

      - *

      Setting the value to zero is not recommended since it can result - * in a large increase in the number of - * triangles in the final navmesh at a high processing cost.

      - *

      Constraints: >= 0

      - * - * @param maxVertsPerPoly The maximum number of vertices per polygon - * for polygons generated during the voxel to polygon conversion stage. - *

      Higher values reduce performance, but can also result in better - * formed triangles in the navmesh. A value of around 6 is generally - * adequate with diminishing returns for values higher than 6.

      - *

      Contraints: >= 3

      - * - * @param contourSampleDistance Sets the sampling distance to use when - * matching the navmesh to the surface of the original geometry. - *

      Impacts how well the final mesh conforms to the original - * geometry's surface contour. Higher values result in a navmesh which - * conforms more closely to the original geometry's surface at the cost - * of a higher final triangle count and higher processing cost.

      - *

      Setting this argument to zero will disable this functionality.

      - *

      Constraints: >= 0

      - * - * @param contourMaxDeviation The maximum distance the surface of the - * navmesh may deviate from the surface of the original geometry. - *

      The accuracy of the algorithm which uses this value is impacted - * by the value of the contour sample distance argument.

      - *

      The value of this argument has no meaning if the contour sample - * distance argument is set to zero.

      - *

      Setting the value to zero is not recommended since it can result - * in a large increase in the number of triangles in the final navmesh - * at a high processing cost.

      - *

      Constraints: >= 0

      - * - * @throws IllegalArgumentException If there are any unresolvable - * argument errors. (Most argument errors are avoided through value - * clamping and other auto-correction methods.) - * - * @see Detailed parameter information. - */ - public NavmeshGenerator(float cellSize - , float cellHeight - , float minTraversableHeight - , float maxTraversableStep - , float maxTraversableSlope - , boolean clipLedges - , float traversableAreaBorderSize - , int smoothingThreshold - , boolean useConservativeExpansion - , int minUnconnectedRegionSize - , int mergeRegionSize - , float maxEdgeLength - , float edgeMaxDeviation - , int maxVertsPerPoly - , float contourSampleDistance - , float contourMaxDeviation) - throws IllegalArgumentException - { - - // Convert certain values from world units to voxel units. - int vxMinTraversableHeight = 1; - if (minTraversableHeight != 0) - { - vxMinTraversableHeight = (int)Math.ceil( - Math.max(Float.MIN_VALUE, minTraversableHeight) / - Math.max(Float.MIN_VALUE, cellHeight)); - } - - int vxMaxTraversableStep = 0; - if (maxTraversableStep != 0) - { - vxMaxTraversableStep = (int)Math.ceil( - Math.max(Float.MIN_VALUE, maxTraversableStep) / - Math.max(Float.MIN_VALUE, cellHeight)); - } - - int vxTraversableAreaBorderSize = 0; - if (traversableAreaBorderSize != 0) - { - vxTraversableAreaBorderSize = (int)Math.ceil( - Math.max(Float.MIN_VALUE, traversableAreaBorderSize) / - Math.max(Float.MIN_VALUE, cellSize)); - } - - int vxMaxEdgeLength = 0; - if (maxEdgeLength != 0) - { - vxMaxEdgeLength = (int)Math.ceil( - Math.max(Float.MIN_VALUE, maxEdgeLength) / - Math.max(Float.MIN_VALUE, cellSize)); - } - - // Construct the solid field builder. - mSolidHeightFieldBuilder = new SolidHeightfieldBuilder(cellSize - , cellHeight - , vxMinTraversableHeight - , vxMaxTraversableStep - , maxTraversableSlope - , clipLedges); - - // Construct the open field builder. - // The order of the algorithms is the order they are applied. - ArrayList regionAlgorithms = - new ArrayList(); - if (vxTraversableAreaBorderSize > 0) - // Since there will be a boarder around all null regions, - // we can use the more efficient form of the algorithm. - regionAlgorithms.add(new CleanNullRegionBorders(true)); - else - regionAlgorithms.add(new CleanNullRegionBorders(false)); - regionAlgorithms.add(new FilterOutSmallRegions(minUnconnectedRegionSize - , mergeRegionSize)); - mOpenHeightFieldBuilder = new OpenHeightfieldBuilder( - vxMinTraversableHeight - , vxMaxTraversableStep - , vxTraversableAreaBorderSize - , smoothingThreshold - , SpanFlags.WALKABLE - , useConservativeExpansion - , regionAlgorithms); - - // Construct the contour set builder. - // The order of the algorithms is the order they are applied. - ArrayList contourAlgorithms = - new ArrayList(); - /* - * Note: Semi-converting edgeMaxDeviation to voxel unit. - * (It's still a float.) - * This is needed because the null region edges algorithm has no - * concept of world units. It only knows about the units it - * is passed, and it is being passed voxel sized units. - */ - contourAlgorithms.add( - new MatchNullRegionEdges(edgeMaxDeviation / cellSize)); - contourAlgorithms.add(new NullRegionMaxEdge(vxMaxEdgeLength)); - mContourSetBuilder = new ContourSetBuilder(contourAlgorithms); - - // Construct the polymesh and triange mesh builders. - mPolyMeshBuilder = new PolyMeshFieldBuilder(maxVertsPerPoly); - mTriangleMeshBuilder = new DetailMeshBuilder(contourSampleDistance - , contourMaxDeviation); - } - - /** - * Build a navigation mesh from the source geometry. - * @param vertices The source geometry vertices in the form (x, y, z) - * @param indices The triangle mesh vertices in the form - * (vertA, vertB, vertC), wrapped clockwise. - * @param outIntermediateData If non-null, the intermediate build - * results will be added to this object. If the build fails, the object - * will contain all intermediate results which were successfully generated. - * @return The generated navigation mesh, or null if generation failed. - * @see Process Overview - */ - public TriangleMesh build(float[] vertices - , int[] indices - , IntermediateData outIntermediateData) - { - - if (outIntermediateData != null) - outIntermediateData.reset(); - - long timerStart = 0; - - // Reference: Heightfield overview - // http://www.critterai.org/?q=nmgen_hfintro - - // Generate a height field representing obstructed (solid) space. - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final SolidHeightfield solidField = - mSolidHeightFieldBuilder.build(vertices, indices); - if (solidField == null || !solidField.hasSpans()) - return null; - - if (outIntermediateData != null) - outIntermediateData.voxelizationTime = - System.nanoTime() - timerStart; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setSolidHeightfield(solidField); - - /* - * Generate a heightfield representing the open space - * - * Instead of spans representing obstructed space, spans - * represent open space above obstructed space and between obstructions. - * - * Note: Only a partial build of the heightfield object is being - * performed here. - * The only reason for doing a partial build is for ease of prototyping. - * I.e. Can comment out portions of the height field build without - * touching the open heightfield builder class. - */ - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final OpenHeightfield openField = - mOpenHeightFieldBuilder.build(solidField, false); - if (openField == null) - return null; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setOpenHeightfield(openField); - - // Finish the build of the field. - // Order is important. - mOpenHeightFieldBuilder.generateNeighborLinks(openField); - mOpenHeightFieldBuilder.generateDistanceField(openField); - mOpenHeightFieldBuilder.blurDistanceField(openField); - mOpenHeightFieldBuilder.generateRegions(openField); - - if (outIntermediateData != null) - outIntermediateData.regionGenTime = System.nanoTime() - timerStart; - - // Terminology references: - // http://en.wikipedia.org/wiki/Polygon - // http://en.wikipedia.org/wiki riangulation_%28advanced_geometry%29 - - // Generate contours from the open heightfield's regions. - // Contours are simply polygons that represent the edges of regions. - - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final ContourSet contours = mContourSetBuilder.build(openField); - if (contours == null) - return null; - - if (outIntermediateData != null) - outIntermediateData.contourGenTime = System.nanoTime() - timerStart; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setContours(contours); - - // Generate a convex polygon mesh from the contours. - // Converts contours (simple polygons) to convex polygons. - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - final PolyMeshField polyMesh = mPolyMeshBuilder.build(contours); - if (polyMesh == null) - return null; - - if (outIntermediateData != null) - outIntermediateData.polyGenTime = System.nanoTime() - timerStart; - - if (outIntermediateData != null) - // Store intermediate data. - outIntermediateData.setPolyMesh(polyMesh); - - // Triangulate the convex polygon mesh. This is where contour - // matching is performed. Also referred to as tesselation. - - if (outIntermediateData != null) - timerStart = System.nanoTime(); - - TriangleMesh mesh = mTriangleMeshBuilder.build(polyMesh, openField); - - if (outIntermediateData != null && mesh != null) - outIntermediateData.finalMeshGenTime = System.nanoTime() - timerStart; - - return mesh; - - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/NullRegionMaxEdge.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/NullRegionMaxEdge.java deleted file mode 100644 index a9ba45d5..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/NullRegionMaxEdge.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Adds vertices to a contour such that no null region edge segment exceeds - * the allowed edge length. - *

      Only null region edges are operated on.

      - *

      - * - * - *

      - *

      - * - * - *

      - */ -public final class NullRegionMaxEdge - implements IContourAlgorithm -{ - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * The maximum length allowed for line segments that are part of a null - * region edge. - */ - private final int mMaxEdgeLength; - - /** - * Constructor - * @param maxEdgeLength The maximum length of polygon edges that - * represent the border of the navmesh. - *

      More vertices will be added to navmesh border edges if this value - * is exceeded for a particular edge. In certain cases this will reduce - * the number of thin, long triangles in the navmesh.

      - *

      A value of zero will disable this feature.

      - *

      Constraints: >= 0

      - */ - public NullRegionMaxEdge(int maxEdgeLength) - { - mMaxEdgeLength = Math.max(maxEdgeLength, 0); - } - - /** - * {@inheritDoc} - *

      The resultVerts argument is expected to be seeded with at least - * one edge.

      - */ - @Override - public void apply(ArrayList sourceVerts - , ArrayList resultVerts) - { - - // See the interface documentation for details on what the argument - // lists contain. - - if (mMaxEdgeLength <= 0) - return; - - final int sourceVertCount = sourceVerts.size() / 4; - int resultVertCount = resultVerts.size() / 4; - int iVertA = 0; - - /* - * Insert verts into null-region edges that are two long. - * - * The basic process is to look at each edge in the result list. - * If it connects to the null region and exceeds the allowed length - * then insert a vertex from the source vertices list that is - * closest to the middle of the current edge, splitting it in half. - * - * Note: The number of result vertices may increase, which is why a - * while loop is being used. - */ - while (iVertA < resultVertCount) - { - - // Get vertices for the current edge. - - // Wrap if necessary. - final int iVertB = (iVertA + 1) % resultVertCount; - - final int ax = resultVerts.get(iVertA * 4); - final int az = resultVerts.get(iVertA * 4 + 2); - final int iVertASource = resultVerts.get(iVertA * 4 + 3); - - final int bx = resultVerts.get(iVertB * 4); - final int bz = resultVerts.get(iVertB * 4 + 2); - final int iVertBSource = resultVerts.get(iVertB * 4 + 3); - - int iNewVert = -1; // -1 indicates no need to add new vertex. - // Wrap if necessary. - final int iTestVert = (iVertASource + 1) % sourceVertCount; - - // Find maximum deviation from the edge. - - if (sourceVerts.get(iTestVert * 4 + 3) == NULL_REGION) - { - // This is a null-region edge. Check its length against - // the maximum allowed. - final int dx = bx - ax; - final int dz = bz - az; - if (dx * dx + dz * dz > mMaxEdgeLength * mMaxEdgeLength) - { - // The current edge is too long and needs to be split. - // Find original number of vertices between the vertA - // and vertB. - final int indexDistance = iVertBSource < iVertASource - ? (iVertBSource + (sourceVertCount - iVertASource)) - : (iVertBSource - iVertASource); - // Choose the vertex that is half way between vertA - // and vertB. Not distance wise, but step wise. - // More wrapping. - iNewVert = - (iVertASource + indexDistance/2) % sourceVertCount; - } - } - - if (iNewVert != -1) - { - // A new vertex needs to be inserted. Do it. - resultVerts.add((iVertA + 1) * 4 - , sourceVerts.get(iNewVert * 4)); - resultVerts.add((iVertA + 1) * 4 + 1 - , sourceVerts.get(iNewVert * 4 + 1)); - resultVerts.add((iVertA + 1) * 4 + 2 - , sourceVerts.get(iNewVert * 4 + 2)); - resultVerts.add((iVertA + 1) * 4 + 3 - , iNewVert); - // Update the vertex count since a new vertex was added. - resultVertCount = resultVerts.size() / 4; - // The vertex index is not being incremented because on the - // next loop we want to perform the check from iVertA to - // the newly inserted vertex. - } - else - // This edge is finished. Move to the next vertex. - iVertA++; - } - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightSpan.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightSpan.java deleted file mode 100644 index c0601924..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightSpan.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents the open space above a solid span within the cell column of - * a heightfield. - *

      - * - *

      - *

      - * @see Introduction to Heightfields - * @see HeightSpan - */ -public final class OpenHeightSpan -{ - /* - * Design Notes: - * - * Structurally this class is so similar with HeightSpan that it can - * extend HeightSpan. But it is being kept separate for clarity. - * As an independent class it can use the floor and ceiling nomenclature - * that makes reading code much easier. - * - */ - - /** - * A value representing a span in the null region. Spans in the null - * are considered not traversable. - *

      Spans in the null-region are often skipped during processing. - * Other processing is only applied when the null-region is involved.

      - */ - public static final int NULL_REGION = 0; - - /** - * Temporary flags associated with the span. - *

      The value is meaningless outside the operation in which the flags - * are needed. Since various operations may use this flag for their own - * purpose, always reset the flag after use.

      - *

      The contract is that an operation expects the flag to be zero when - * it receives the span data.

      - */ - public int flags = 0; - - private int mRegionID = 0; - private int mDistanceToRegionCore = 0; - private int mDistanceToBorder = 0; - - private int mFloor; - private int mHeight; - - private OpenHeightSpan mNext = null; - private OpenHeightSpan mNeighborConnection0 = null; - private OpenHeightSpan mNeighborConnection1 = null; - private OpenHeightSpan mNeighborConnection2 = null; - private OpenHeightSpan mNeighborConnection3 = null; - - /** - * Constructor - * @param floor The base height of the span. - * @param height The height of the unobstructed space above the floor. - * {@link Integer#MAX_VALUE} is generally used to indicate no obstructions - * exist above the floor. - * @throws IllegalArgumentException If the floor is below zero or the - * height is less than 1. - */ - public OpenHeightSpan(int floor, int height) - throws IllegalArgumentException - { - if (floor < 0) - throw new IllegalArgumentException("Floor is less than zero."); - if (height < 1) - throw new IllegalArgumentException("Height is less than one."); - this.mFloor = floor; - this.mHeight = height; - } - - /** - * The height of the ceiling. - * @return The height of the ceiling. - */ - public int ceiling() { return mFloor + mHeight; } - - /** - * The distance this span is from the nearest border of the heightfield - * it belongs to. - * @return The distance this span is from the nearest heightfield border. - */ - public int distanceToBorder() { return mDistanceToBorder; } - - /** - * The distance this span is from the core of the heightfield region - * it belongs to. - * @return The distance this span is from the core of the heightfield - * region it belongs to. - */ - public int distanceToRegionCore() { return mDistanceToRegionCore; } - - /** - * The base height of the span. - * @return The base height of the span. - */ - public int floor() { return mFloor; } - - /** - * Populates an array with information on the regions a span's - * 8-neighbors are assigned to. - *

      If necessary, both of a diagonal neighbor's associated - * axis-neighbors will be used to detect the diagonal neighbor.

      - *

      Special case: Since, diagonal neighbors are detected through - * axis-neighbors, if the span has no axis-neighbors in the - * direction of the diagonal-neighbor, then the diagonal-neighbor - * will not be detected.

      - *

      Neighbor order:
      - * 0 - 3 : Standard axis-neighbor order. - * (E.g. Starting at standard zero direction.)
      - * 4 - 7 : Standard diagonal neighbors. - * (E.g. Clockwise of associated axis-neighbor.)
      - * So the standard diagonal neigbor of an axis-neighbor can be - * found at "axis-neighbor index + 4". - *

      - * @param out An array of at least size 8. - * @see Neighbor Searches - */ - public void getDetailedRegionMap(int[] out, int insertIndex) - { - for (int i = 0; i < 8; i++) - out[insertIndex+i] = NULL_REGION; - OpenHeightSpan nSpan = null; - OpenHeightSpan nnSpan = null; - for (int dir = 0; dir < 4; dir++) - { - nSpan = getNeighbor(dir); - if (nSpan != null) - { - out[insertIndex+dir] = nSpan.regionID(); - nnSpan = nSpan.getNeighbor((dir+1) & 0x3); - if (nnSpan != null) - out[insertIndex+dir+4] = nnSpan.regionID(); - nnSpan = nSpan.getNeighbor((dir+3) & 0x3); - if (nnSpan != null) - out[insertIndex+((dir+3)&0x3)+4] = nnSpan.regionID(); - } - } - } - - /** - * Gets a reference to the span that is considered an axis-neighbor to - * this span for the specified direction. Uses the standard direction - * indices (0 through 3) where zero is the neighbor offset at (-1, 0) - * and the search proceeds clockwise. - * @param direction The direction to search. - * @return A reference to the axis-neighbor in the specified direction. - * Or null if there is no neighbor in the direction or the direction - * index is invalid. - * @see Neighbor Searches - */ - public OpenHeightSpan getNeighbor(int direction) - { - switch (direction) - { - case 0: return mNeighborConnection0; - case 1: return mNeighborConnection1; - case 2: return mNeighborConnection2; - case 3: return mNeighborConnection3; - default: return null; - } - } - - /** - * The height of the unobstructed space above the floor. - *

      {@link Integer#MAX_VALUE} is generally used to indicate no - * obstructions exist above the floor.

      - * @return The height of the unobstructed space above the floor. - */ - public int height() { return mHeight; } - - /** - * The next span higher in the span's heightfield column. - *

      The space between this span's ceiling and the next span's floor is - * considered to be obstructed space.

      - * @return The next higher span in the span's heightfield column. - * Or null if there is no heigher span. - */ - public OpenHeightSpan next() { return mNext; } - - /** - * The heightfield region this span belongs to. - *

      This value will never be less than {@link #NULL_REGION} - * for a finished, properly constructed heightfield.

      - *

      For a partially constructed heightfield the contract - * is that any region ID less than or equal to {@link #NULL_REGION} - * belongs to the null region.

      - * @return The heightfield region this span belongs to. - */ - public int regionID() { return mRegionID; } - - /** - * Set the distance this span is from the nearest border of the - * heightfield it belongs to. - * @param value The new distance. Auto-clamped at a minimum of zero. - */ - public void setDistanceToBorder(int value) - { - mDistanceToBorder = Math.max(value, 0); - } - - /** - * Set the distance this span is from the core of the heightfield region - * it belongs to. - * @param value The new distance. Auto-clamped at a minimum of zero. - */ - public void setDistanceToRegionCore(int value) - { - mDistanceToRegionCore = Math.max(value, 0); - } - - /** - * Sets the specified span at the neighbor of the current span. - *

      Uses the standard direction indices (0 through 3) where - * Zero is the neighbor offset at (-1, 0) and the search proceeds - * clockwise.

      - * @param direction The direction of the neighbor. - * @param neighbor The neighbor of this span. - * @see Neighbor Searches - */ - public void setNeighbor(int direction, OpenHeightSpan neighbor) - { - switch (direction) - { - case 0: mNeighborConnection0 = neighbor; break; - case 1: mNeighborConnection1 = neighbor; break; - case 2: mNeighborConnection2 = neighbor; break; - case 3: mNeighborConnection3 = neighbor; break; - } - } - - /** - * Set the next heigher span in the span's heightfield column. - * @param value The new value. null is an acceptable value. - */ - public void setNext(OpenHeightSpan value) { mNext = value; } - - /** - * The heightfield region this span belongs to. - *

      See {@link #regionID()} for important contract information.

      - * @param value The new value. - */ - public void setRegionID(int value) { mRegionID = value; } - - /** - * {@inheritDoc} - */ - @Override - public String toString() - { - return "Floor: " + mFloor - + ", Ceiling: " + mHeight - + ", Region: " + mRegionID; - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightfield.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightfield.java deleted file mode 100644 index a00b4343..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightfield.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.Hashtable; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Provides a representation of the open (unobstructed) space above solid - * surfaces in a voxel field. - *

      For this type of heightfield, spans represent the floor and ceiling - * of the open spaces.

      - *

      WARNING: This class has very little protections build into it. It - * is basically an uncontrolled data structure with convenience functions.

      - *

      - * - *

      - * @see Introduction to Height Fields - */ -public final class OpenHeightfield - extends BoundedField -{ - /* - * Recast Reference: rcCompactHeightfield in Recast.h - * The internal structure of this class is very different from Recast. - * See: http://www.critterai.org/nmgen_diffs for the reason. - */ - - /** - * An iterator that will iterate through all spans within a - * height field. (Not just the base spans.) - *

      Behavior of the iterator is undefined if the interator's source - * is changed during iteration.

      - * The iterator returned by {@link OpenHeightfield#dataIterator()}. - */ - public final class OpenHeightFieldIterator - implements Iterator - { - - // See reset() for initialization information. - - private int mNextWidth; - private int mNextDepth; - private OpenHeightSpan mNext; - - private int mLastWidth; - private int mLastDepth; - - /** - * Constructor. - */ - private OpenHeightFieldIterator() - { - reset(); - } - - /** - * The depth index of the last span returned by {@link #next()} - * @return The depth index of the last span returned by {@link #next()} - */ - public int depthIndex() { return mLastDepth; } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasNext() - { - return (mNext != null); - } - - /** - * {@inheritDoc} - */ - @Override - public OpenHeightSpan next() - { - if (mNext == null) - throw new NoSuchElementException(); - // Select value cursor. - OpenHeightSpan next = mNext; - mLastWidth = mNextWidth; - mLastDepth = mNextDepth; - // Move the cursor to the next value. - moveToNext(); - return next; - } - - /** - * {@inheritDoc} - * This operation is not supported. - */ - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } - - /** - * Resets the iterator so that it can be re-used. - */ - public void reset() - { - mNextWidth = 0; - mNextDepth = 0; - mNext = null; - mLastWidth = 0; - mLastDepth = 0; - moveToNext(); - } - - /** - * The width index of the last span returned by {@link #next()} - * @return The width index of the last span returned by {@link #next()} - */ - public int widthIndex() { return mLastWidth; } - - /** - * This operation is called in order to move the - * cursor to the next span after the {@link #next()} operation - * has selected its span to return. - */ - private void moveToNext() - { - if (mNext != null) - { - // There is a current cell selected. - if (mNext.next() != null) - { - // The current cell has a next. Select it - mNext = mNext.next(); - return; - } - else mNextWidth++; // Move to next cell. - } - // Need to find the next grid location that contains a span. - // Loop until one is found or no more are available. - for (int depthIndex = mNextDepth - ; depthIndex < depth() - ; depthIndex++) - { - for (int widthIndex = mNextWidth - ; widthIndex < width() - ; widthIndex++) - { - OpenHeightSpan span = - mSpans.get(gridIndex(widthIndex, depthIndex)); - if (span != null) - { - // A span was found. Set the cursor to it. - mNext = span; - mNextWidth = widthIndex; - mNextDepth = depthIndex; - return; - } - } - mNextWidth = 0; - } - // If got here then there are no more spans. - // Set values to indicate the end of iteration. - mNext = null; - mNextDepth = -1; - mNextWidth = -1; - } - } - - /** - * Indicates that a value is unknown and need to be derived. - */ - private static final int UNKNOWN = -1; - private int mSpanCount = 0; - - // These next fields are derived only when the value is needed. - - private int mRegionCount = 0; - - /** - * The maximum distance a span is from a border span. - */ - private int mMaxBorderDistance = UNKNOWN; - - /** - * The minimum distance a span is from a border span. - */ - private int mMinBorderDistance = UNKNOWN; - - /** - * Key = Grid index from {@link #gridIndex(int, int)}. - * Value = The first (lowest) span in the grid column. - */ - private final Hashtable mSpans = - new Hashtable(); - - /** - * Constructor - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the base - * of the field.) - * @param cellHeight The height increment of the field. - * @throws IllegalArgumentException If the bounds are null or the - * wrong size. - */ - public OpenHeightfield(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize, float cellHeight) - throws IllegalArgumentException - { - super(gridBoundsMin, gridBoundsMax, cellSize, cellHeight); - } - - /** - * Puts the span at the grid location, replacing any spans already at the - * location. The added span becomes the new base span for the location. - *

      WARNING: The span count must be manually updated to reflect changes - * in span count

      - *

      Behavior is undefined if the indices are invalid.

      - * @param widthIndex The width index of the grid location to add the - * span to. (0 <= value < {@link #width()}) - * @param depthIndex The depth index of the grid location to add the - * span to. (0 <= value < {@link #depth()}) - * @param span The span to put at the grid location. - * @return The original base span that was in the grid location, or null - * if there was no pre-existing span in the location. - */ - public OpenHeightSpan addData(int widthIndex - , int depthIndex - , OpenHeightSpan span) - { - return mSpans.put(gridIndex(widthIndex, depthIndex), span); - } - - /** - * Resets the border distance values so they will - * be recacluated the next time they are needed. - */ - public void clearBorderDistanceBounds() - { - mMaxBorderDistance = UNKNOWN; - mMinBorderDistance = UNKNOWN; - } - - /** - * An iterator for the heightfields spans. - * The returned iterator does not support the - * {@link Iterator#remove()} operation. - */ - public OpenHeightFieldIterator dataIterator() - { - return this.new OpenHeightFieldIterator(); - } - - /** - * Retrieves the base (lowest) grid for the specified grid location. - *

      Behavior is undefined if the indices are invalid.

      - * @param widthIndex The width index of the grid location the span is - * located in. (0 <= value < {@link #width()}) - * @param depthIndex The depth index of the grid location the span is - * located in. (0 <= value < {@link #depth()}) - * @return The base (lowest) span for the specified grid location. Null - * if there is no data for the grid location. - */ - public OpenHeightSpan getData(int widthIndex, int depthIndex) - { - return mSpans.get(gridIndex(widthIndex, depthIndex)); - } - - /** - * Increments the span count. - *

      IMPORTANT: There is no automatic span count updates. Span count - * must be managed manually.

      - * @return The new span count. - */ - public int incrementSpanCount() { return ++mSpanCount; } - - /** - * The maximum distance a span in the heightfield is from its - * nearest border. - * @return The maximum distance a span in the heightfield is from - * its nearest border. - */ - public int maxBorderDistance() - { - if (mMaxBorderDistance == UNKNOWN) - calcBorderDistanceBounds(); - return mMaxBorderDistance; - } - - /** - * The minimum distance a span in the height field is from its nearest - * border. (Usually zero. But can depend on the generation method.) - * @return The minimum distance a span in the height field is from its - * nearest border. - */ - public int minBorderDistance() - { - if (mMinBorderDistance == UNKNOWN) - calcBorderDistanceBounds(); - return mMinBorderDistance; - } - - /** - * Sends a tab delimited table of the distance field values to - * standard out. - *

      Only the lowest spans in the field are output. So this operation - * is really only suitable for simple tests on fields - * that don't contain overlapping spans.

      - *

      Columns: Width
      - * Rows: Depth

      - */ - public void printDistanceField() - { - System.out.println("Distance Field (Spans: " + mSpanCount + ")"); - final OpenHeightFieldIterator iter = new OpenHeightFieldIterator(); - int depth = -1; - System.out.print("\t"); - for (int width = 0; width < width(); width++) - System.out.print(width + "\t"); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (iter.depthIndex() != depth) - System.out.print("\n" + ++depth + "\t"); - System.out.print(span.distanceToBorder() + "\t"); - } - System.out.println(); - } - - /** - * Sends a tab delimited table of the region ID values to standard out. - *

      Only the lowest spans in the field are output. So this operation - * is really only suitable for simple tests on fields - * that don't contain overlapping spans.

      - *

      Columns: Width
      - * Rows: Depth

      - */ - public void printRegionField() - { - System.out.println("Distance Field (Spans: " + mSpanCount - + ", Regions: " + mRegionCount + ")"); - System.out.print("\t"); - for (int width = 0; width < width(); width++) - System.out.print(width + "\t"); - for (int iDepth = 0; iDepth < depth(); iDepth++) - { - System.out.print("\n" + iDepth + "\t"); - for (int iWidth = 0; iWidth < width(); iWidth++) - { - OpenHeightSpan span = getData(iWidth, iDepth); - if (span == null) - System.out.print(" \t"); - else - System.out.print(span.regionID() + "\t"); - } - } - System.out.println(); - } - - /** - * The number of regions in the height field. - *

      Includes the null region. So unless all spans are in the - * null region, this value will be >= 2. (E.g. The null region and at - * least one other region.)

      - */ - public int regionCount() { return mRegionCount; } - - /** - * Sets the region count. - *

      The region count is expected to be zero based with the zero - * region representing the null region. So the region count is - * expected to be one more that the maximum region value. E.g. If the - * highest region value is 14, then the region count is 15.

      - *

      IMPORTANT: There is no automatic region count management. - * Region count must be managed manually.

      - * @param value The new region count. - */ - public void setRegionCount(int value) { mRegionCount = value; } - - /** - * The number of spans in the heightfield. - *

      A value of zero indicates an empty heightfield.

      - */ - public int spanCount() { return mSpanCount; } - - /** - * Calculates the min/max distance a span in the field is from it - * nearest border. Allows on-demand calculation of this information. - */ - private void calcBorderDistanceBounds() - { - if (mSpanCount == 0) - return; - - // Default the values. - mMinBorderDistance = Integer.MAX_VALUE; - mMaxBorderDistance = UNKNOWN; - - // Iterate through all spans and reset the values if new min/max's are - // found. - OpenHeightFieldIterator iter = - this.new OpenHeightFieldIterator(); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - mMinBorderDistance = Math.min(mMinBorderDistance - , span.distanceToBorder()); - mMaxBorderDistance = Math.max(mMaxBorderDistance - , span.distanceToBorder()); - } - if (mMinBorderDistance == Integer.MAX_VALUE) - // There ware a problem locating the maximum. - // So set it back to unknown. - mMinBorderDistance = UNKNOWN; - - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightfieldBuilder.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightfieldBuilder.java deleted file mode 100644 index a1c253d0..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/OpenHeightfieldBuilder.java +++ /dev/null @@ -1,1112 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Hashtable; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; - -/** - * Builds an open heightfield from the solid data contained by an - * {@link SolidHeightfield}. It does this by locating and creating spans - * representing the area above spans within the source field that have a - * specified flag. - *

      Options are provided to generate neighbor, distance field, and - * region information for the open span data

      - *

      Example of a fully formed open heightfield. (I.e. With region - * information.) Only the floor of the spans is shown.

      - *

      - * - *

      - * @see Introduction to Height Fields - * @see Region Generation - * @see OpenHeightfield - * @see OpenHeightSpan - */ -public final class OpenHeightfieldBuilder -{ - - /* - * Design notes: - * - * Recast references: - * rcBuildCompactHeightfield in Recast.cpp - * rcBuildDistanceField in RecastRegion.cpp - * rcBuildRegions in RecastRegion.cpp - * - * Configuration getters won't be added until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private final int mMinTraversableHeight; - private final int mMaxTraversableStep; - private final int mSmoothingThreshold; - private final int mTraversableAreaBorderSize; - private final int mFilterFlags; - private final boolean mUseConservativeExpansion; - - private final ArrayList mRegionAlgorithms - = new ArrayList(); - - /** - * Constructor - * - * @param minTraversableHeight Represents the minimum floor to ceiling - * height that will still allow the floor area to be considered walkable. - *

      Permits detection of overhangs in the geometry which make the - * geometry below become unwalkable.

      - *

      Constraints: > 0

      - * - * @param maxTraversableStep Represents the maximum ledge height that - * is considered to still be walkable. - *

      Prevents minor deviations in height from improperly showing as - * obstructions. Permits detection of stair-like structures, curbs, etc. - *

      - *

      Constraints: >= 0

      - * - * @param traversableAreaBorderSize Represents the closest any part - * of the navmesh can get to an obstruction in the source mesh. - *

      Usually set to the maximum bounding radius of entities utilizing - * the navmesh for navigation decisions.

      - *

      Constraints: >= 0

      - * - * @param smoothingThreshold The amount of smoothing to be performed - * when generating the distance field. - *

      This value impacts region formation and border detection. A higher - * value results in generally larger regions and larger border sizes. - * A value of zero will disable smoothing.

      - *

      Constraints: 0 <= value <= 4

      - * - * @param filterFlags The flags used to determine which spans from the - * source {@link SolidHeightfield} should be used to build the - * {@link OpenHeightfield}. Only those spans which whose flags - * exactly match the filter flag will be considered for inclusion in - * the generated open field. - *

      Note: Spans from the source field which do not match the filter - * flags are still taken into account as height obstructions.

      - * - * @param useConservativeExpansion Applies extra algorithms to regions - * to help prevent poorly formed regions from forming. - *

      If the navigation mesh is missing sections that should be present, - * then enabling this feature will likely fix the problem

      - *

      Enabling this feature significantly increased processing cost.

      - * - * @param regionAlgorithms A list of the algorithms to run after - * initial region generation is complete. The algorithms will be run - * in the order of the list. - */ - public OpenHeightfieldBuilder(int minTraversableHeight - , int maxTraversableStep - , int traversableAreaBorderSize - , int smoothingThreshold - , int filterFlags - , boolean useConservativeExpansion - , ArrayList regionAlgorithms) - { - mMaxTraversableStep = Math.max(0, maxTraversableStep); - mMinTraversableHeight = Math.max(1, minTraversableHeight); - mTraversableAreaBorderSize = Math.max(0, traversableAreaBorderSize); - mFilterFlags = filterFlags; - mSmoothingThreshold = Math.min(4, Math.max(0, smoothingThreshold)); - mUseConservativeExpansion = useConservativeExpansion; - if (regionAlgorithms != null) - mRegionAlgorithms.addAll(regionAlgorithms); - } - - /** - * Performs a smoothing pass on the distance field data. - *

      This operation depends on distance field information. So the - * {@link #generateDistanceField(OpenHeightfield)} operation must be - * run before this operation.

      - *

      This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

      - * @param field A populated open height field with distance field data - * already generated. - */ - public void blurDistanceField(OpenHeightfield field) - { - // TODO: DOC: Need to find source documentation. - // The basic process is to combine a span's original distance with - // that of its neighbors. - - if (field == null) - return; - - // Reference: Neighbor searches and nomenclature. - // http://www.critterai.org/?q=nmgen_hfintro#nsearch - - if (mSmoothingThreshold <= 0) - // Not configured to perform smoothing. Exit early. - return; - - // TODO: EVAL: Try to optimize out this hash table. - /* - * Holds information on the final blurred distance for each span. - * Key = span - * Value = new blurred distance. - */ - final Hashtable blurResults - = new Hashtable(field.spanCount()); - - // Loop through all spans. - final OpenHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - final int origDist = span.distanceToBorder(); - if (origDist <= mSmoothingThreshold) - { - // This span is at the minimum threshold. - // Add it to the results and continue to next span. - blurResults.put(span, mSmoothingThreshold); - continue; - } - - int workingDist = origDist; - // Loop through neighbors. - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); // axis-neighbor. - if (nSpan == null) - // No neighbor on this side. Self buff using own - // original distance. - workingDist += origDist * 2; - else - { - // Neighbor on this side. Add its distance to the - // current span. - workingDist += nSpan.distanceToBorder(); - // Get diagonal neighbor. - nSpan = nSpan.getNeighbor((dir+1) & 0x3); - if (nSpan == null) - // No diagonal neighbor. Self buff using own - // original distance. - workingDist += origDist; - else - // Has diagonal neighbor. Add its distance to - // the current span. - workingDist += nSpan.distanceToBorder(); - } - } - // Adjust and store the result. - // Don't know the why behind this specific formula. - blurResults.put(span, ((workingDist + 5) / 9)); - } - - // Replace the original distance information with the new - // distance information. - for (OpenHeightSpan span : blurResults.keySet()) - { - span.setDistanceToBorder(blurResults.get(span)); - } - - // Reset the known min/max border distance. This will force a - // recalculation if the values are needed later. - field.clearBorderDistanceBounds(); - } - - /** - * Builds an {@link OpenHeightfield} from the provided - * {@link SolidHeightfield} based on the configuration settings. - * @param sourceField The solid field to derive the open field from. - * @param performFullGeneration If TRUE, neighbor link, distance field - * (including blurring), - * and region information will be generated. If FALSE, only the spans - * will be generated. - */ - public OpenHeightfield build(SolidHeightfield sourceField - , boolean performFullGeneration) - { - if (sourceField == null) - return null; - - // Construct the open field object. - OpenHeightfield result = new OpenHeightfield(sourceField.boundsMin() - , sourceField.boundsMax() - , sourceField.cellSize() - , sourceField.cellHeight()); - - // Loop through all solid field grid locations. - for (int depthIndex = 0 - ; depthIndex < sourceField.depth() - ; depthIndex++) - { - for (int widthIndex = 0 - ; widthIndex < sourceField.width() - ; widthIndex++) - { - // The lowest span in this column. - OpenHeightSpan baseSpan = null; - // The last span processed in this column. - OpenHeightSpan previousSpan = null; - // Climb up the list of spans at this grid location. - // A loop will only occur if the grid location has at least - // one span. - for (HeightSpan span = - sourceField.getData(widthIndex, depthIndex) - ; span != null - ; span = span.next()) - { - // Ignore spans that do not match the filter flags. - if (span.flags() != mFilterFlags) - continue; - - /* - * Determine the open space between this span and the next - * higher span. Note that the flag of the ceiling span - * does not matter. All spans matter when it comes to - * this step. - */ - int floor = span.max(); - int ceiling = (span.next() != null ? - span.next().max() : Integer.MAX_VALUE); - - // Add the span. - // Note that the original span flags are being discarded. - OpenHeightSpan oSpan = new OpenHeightSpan(floor - , (ceiling - floor)); - if (baseSpan == null) - // This is the first span created at this grid location. - baseSpan = oSpan; - if (previousSpan != null) - // There is a span at a lower location in this grid - // location. Link the lower (previous) span to this - // span. - previousSpan.setNext(oSpan); - previousSpan = oSpan; - result.incrementSpanCount(); - } - if (baseSpan != null) - { - // There is one or more spans at this grid location. - // Add the first span in the chain to the spans hash. - result.addData(widthIndex, depthIndex, baseSpan); - } - } - } - - if (performFullGeneration) - { - // Need to perform a full generation. - generateNeighborLinks(result); - generateDistanceField(result); - blurDistanceField(result); - generateRegions(result); - } - - return result; - - } - - /** - * Generates distance field information. - * The {@link OpenHeightSpan#distanceToBorder()} information is generated - * for all spans in the field. - *

      A boundary is a span with a missing neighbor. It will always have - * a distance value of zero. A span is not a boundary if is has 4 neighbors. - * Its boundary distance value will be higher the further it is from a - * boundary span.

      - *

      All distance values are relative and do not represent explicit - * distance values (such as grid unit distance). The algorithm which is - * used results in an approximation only. It is not exhaustive.

      - *

      This operation depends on neighbor information. So the - * {@link #generateNeighborLinks(OpenHeightfield)} operation must be - * run before this operation.

      - *

      This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

      - *

      The data generated by this operation is required by - * {@link #blurDistanceField(OpenHeightfield)} and - * {@link #generateRegions(OpenHeightfield)}

      - * @param field A field with spans and neighbor information already - * generated. - */ - public void generateDistanceField(OpenHeightfield field) - { - - // TODO: DOC: Need to find source documentation for this algorithm. - - if (field == null) - return; - - // Reference: Neighbor searches and nomenclature. - // http://www.critterai.org/?q=nmgen_hfintro#nsearch - - // Enumerated values for border distance: - - // Represents a border span. The value for a border span will never be - // changed during any stage. - final int BORDER = 0; - - // Represents an uninitialized non-border span. - // All non-border spans will have this value going into pass 1. - // No span will have this value by the end of pass 1. - final int NEEDS_INIT = Integer.MAX_VALUE; - - /* - * Initialization pass. - * Loop through each span. - * Set distance to BORDER for boundary spans. (Spans with less than - * 4 known neighbors.) - * Set distance to NEEDS_INIT for non-boundary spans. - */ - final OpenHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - // Perform 8-neighbor search. If any neighbor is missing, this - // is a border. - boolean isBorder = false; - for (int dir = 0; dir < 4; dir++) - { - final OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null - || nSpan.getNeighbor(dir == 3 ? 0 : dir + 1) == null) - { - // Either this axis-neighbor or the diagonal-neighbor - // associated with it is missing. This is a border span. - isBorder = true; - break; - } - } - if (isBorder) - // Mark as a border span. - span.setDistanceToBorder(BORDER); - else - // Marks as a non-border span that needs initialization. - span.setDistanceToBorder(NEEDS_INIT); - } - - /* - * The next two phases basically check the neighbors of a span and - * set the span's distance field to be slightly greater than the - * neighbor with the lowest border distance. Distance is increased - * slightly more for diagonal-neighbors than for axis-neighbors. - * - * Example: - * Span.dist = 5 // Current estimated distance from border. - * Neighor1.dist = 3 - * Neighor2.dist = 1 <- Neighbor with lowest border distance. - * Neighor3.dist = 2 - * Neighor4.dist = 4 - * Then set Span.dist = Neighbor2.dist + 2 - * - * See the first pass (below) for comments that detail the algorithm. - */ - - /* - * Pass 1 - * During this pass, the following neighbors are checked: - * (-1, 0) (-1, -1) (0, -1) (1, -1) - * - * There is a special case during this pass since non-border spans may - * have a value of NEEDS_INIT: If a neighbor's border distance is not - * known, then it is treated at if it is a border span. - * - * By the end of this pass, no spans will have the value NEEDS_INIT - * since all non-border spans will have a neighbor that forces - * its value to change. - */ - - // Loop through all spans. - iter.reset(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - int dist = span.distanceToBorder(); - if (dist == BORDER) - // This is a border cell. Skip it. - continue; - // This span is guaranteed to have 4 axis neighbors. - // (-1, 0) Guaranteed to exist. - OpenHeightSpan nSpan = span.getNeighbor(0); - int ndist = nSpan.distanceToBorder(); - /* - * At this point, dist is guaranteed to equal NEEDS_INIT. - * (This is the first time this span has been selected for - * change.) So the value of dist will always have its value set - * to slightly higher than this first neighbor. - */ - if (ndist == NEEDS_INIT) - // Don't know how far from border this neighbor is. - // Default to slightly away from the border. - dist = 1; - else - // Set to slightly further from the border than this neighbor. - dist = ndist + 2; - // (-1, -1) Diagonal. Not guaranteed to exist. - nSpan = nSpan.getNeighbor(3); - if (nSpan != null) - { - // There is a diagonal neighbor. - ndist = nSpan.distanceToBorder(); - if (ndist == NEEDS_INIT) - // Don't know how far from border this neighbor is. - // Default to slightly away from the border. - ndist = 2; - else - // Set to slightly further from the border than - // this neighbor. - ndist += 3; - if (ndist < dist) - /* - * This neighbor is closer to the border than - * previously detected neighbors. Use this neighbor's - * increment. (I.e. Slightly further from border than - * this neighbor.) - */ - dist = ndist; - } - nSpan = span.getNeighbor(3); // (0, -1) Guaranteed to exist. - ndist = nSpan.distanceToBorder(); - if (ndist == NEEDS_INIT) - // Don't know how far from border this neighbor is. - // Default to slightly away from the border. - ndist = 1; - else - // Set to slightly further from the border than this neighbor. - ndist += 2; - if (ndist < dist) - // This neighbor is closer to the border than previously - // detected neighbors. Use this neighbor's increment. - // (I.e. Slightly further from border than this neighbor.) - dist = ndist; - // (1, -1) Diagonal. Not guaranteed to exist. - nSpan = nSpan.getNeighbor(2); - // More of the same. So no new comments. - if (nSpan != null) - { - ndist = nSpan.distanceToBorder(); - if (ndist == NEEDS_INIT) - ndist = 2; - else - ndist += 3; - if (ndist < dist) - dist = ndist; - } - // At this point, dist will contain this shortest estimated - // distance. Set the span to this value. - span.setDistanceToBorder(dist); - } - - /* - * Pass 2 - * During this pass, the following neighbors are checked: - * (1, 0) (1, 1) (0, 1) (-1, 1) - * - * Besides checking different neighbors, this pass performs its - * grid search in reverse order. - * - * This pass does the same thing as the first pass, but is much - * simpler because it doesn't need to handle the NEEDS_INIT special - * case. - * - * Minimal commenting is provided since nothing new is happening - * here that isn't already described in the the previous pass. - */ - - // Loop through all spans in reverse order. The looping method is - // slightly more complex since the standard iterator cannot be used. - for (int depthIndex = field.depth() - 1; depthIndex >= 0; depthIndex--) - { - for (int widthIndex = field.width() - 1 - ; widthIndex >= 0 - ; widthIndex--) - { - // Loop through all spans in the current grid location. - for (OpenHeightSpan span = - field.getData(widthIndex, depthIndex) - ; span != null - ; span = span.next()) - { - int dist = span.distanceToBorder(); - if (dist == BORDER) continue; // Border cells never change. - OpenHeightSpan nSpan = span.getNeighbor(2); // (1, 0) - int ndist = nSpan.distanceToBorder(); - ndist = nSpan.distanceToBorder() + 2; - if (ndist < dist) - dist = ndist; - nSpan = nSpan.getNeighbor(1); // (1, 1) - if (nSpan != null) - { - ndist = nSpan.distanceToBorder() + 3; - if (ndist < dist) - dist = ndist; - } - nSpan = span.getNeighbor(1); // (0, 1) - ndist = nSpan.distanceToBorder(); - ndist = nSpan.distanceToBorder() + 2; - if (ndist < dist) - dist = ndist; - nSpan = nSpan.getNeighbor(0); // (-1, 1) - if (nSpan != null) - { - ndist = nSpan.distanceToBorder() + 3; - if (ndist < dist) - dist = ndist; - } - span.setDistanceToBorder(dist); - } - } - } - - // Reset the known min/max border distance. This will force a - // recalculation if the values are needed later. - field.clearBorderDistanceBounds(); - - } - - /** - * Generates axis-neighbor link information for all spans in the field. - * This information is required for algorithms which perform neighbor - * searches. - *

      After this operation is run, the - * {@link OpenHeightSpan#getNeighbor(int)} operation can be used for - * neighbor searches.

      - *

      This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

      - *

      The data generated by this operation is required by - * {@link #generateDistanceField(OpenHeightfield)}

      - * @param field A field already loaded with span information. - * @see Neighbor Searches - */ - public void generateNeighborLinks(OpenHeightfield field) - { - if (field == null) - return; - - // Loop through all spans and generate neighbor information. - OpenHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - final OpenHeightSpan span = iter.next(); - // Loop through all neighbor grid locations and check to see if - // any of their spans are accessible from this span. - for (int dir = 0; dir < 4; dir++) - { - // Get the neighbor offset for this direction. - final int nWidthIndex = - (iter.widthIndex() + BoundedField.getDirOffsetWidth(dir)); - final int nDepthIndex = - (iter.depthIndex() + BoundedField.getDirOffsetDepth(dir)); - /* - * Loop through all spans in the neighbor grid location. - * Note: Because of the way solid heightfields are built, only - * one span in each neighbor column can ever meet the - * conditions to be a neighbor of the current span. - */ - for (OpenHeightSpan nSpan = - field.getData(nWidthIndex, nDepthIndex) - ; nSpan != null - ; nSpan = nSpan.next()) - { - // Select the floor, current or neighbor span, that is - // higher. - int maxFloor = Math.max(span.floor(), nSpan.floor()); - // Select the ceiling, current or neighbor span, this is - // lower. - int minCeiling = Math.min(span.ceiling(), nSpan.ceiling()); - /* - * The above values are used to determine if the the gap - * formed by the two spans is large enough for agents to - * walk through? E.g. Without bumping its head on anything. - */ - if ((minCeiling - maxFloor) >= mMinTraversableHeight - && Math.abs(nSpan.floor() - span.floor()) - <= mMaxTraversableStep) - { - // There is space to walk between current and neighbor - // span, and the step up/down between this and - // neighbor span is acceptable. - span.setNeighbor(dir, nSpan); - break; - } - } - } - } - - } - - /** - * Groups spans into contiguous regions using an watershed based algorithm. - *

      This operation depends on neighbor and distance field information. - * So the {@link #generateNeighborLinks(OpenHeightfield)} and - * {@link #generateDistanceField(OpenHeightfield)} operations must be - * run before this operation.

      - *

      This operation does not need to be run if the - * {@link #build(SolidHeightfield, boolean) build} operation - * was run with performFullGeneration set to TRUE.

      - * @param field A field with span, neighbor, and distance information - * fully generated. - */ - public void generateRegions(OpenHeightfield field) - { - if (field == null) - return; - /* - * Watershed Algorithm - * - * Reference: http://en.wikipedia.org/wiki/Watershed_%28algorithm%29 - * A good visualization: - * http://artis.imag.fr/Publications/2003/HDS03/ (PDF) - * - * Summary: - * - * This algorithm utilizes the span.distanceToBorder() value, which - * is generated by the generateDistanceField() operation. - * - * Using the watershed analogy, the spans which are furthest from - * a border (highest distance to border) represent the lowest points - * in the watershed. A border span represents the highest possible - * water level. - * - * The main loop iterates, starting at the lowest point in the - * watershed, then incrementing with each loop until the highest - * allowed water level is reached. This slowly "floods" the spans - * starting at the lowest points. - * - * (Remember: From this algorithm's point of view "lower" refers - * to distance from a border, not height within the heightfield.) - * - * During each iteration of the loop, spans that are below the - * current water level are located and an attempt is made to either - * add them to exiting regions or create new regions from them. - * - * During the region expansion phase, if a newly flooded span - * borders on an existing region, it is usually added to the region. - * - * Any newly flooded span that survives the region expansion phase - * is used as a seed for a new region. - * - * At the end of the main loop, a final region expansion is - * performed which should catch any stray spans that escaped region - * assignment during the main loop. - */ - - /* - * Represents the minimum distance to an obstacle that is considered - * traversable. I.e. Can't traverse spans closer than this distance - * to a border. This provides a way of artificially capping the - * height to which watershed flooding can occur. - * I.e. Don't let the algorithm flood all the way to the actual border. - * - * We add the minimum border distance to take into account the - * blurring algorithm which can result in a border span having a - * border distance > 0. - * - */ - final int minDist = - mTraversableAreaBorderSize + field.minBorderDistance(); - - // TODO: EVAL: Figure out why this iteration limit is needed. - final int expandIterations = 4 + (mTraversableAreaBorderSize * 2); - - /* - * This value represents the current distance from the border which - * is to be searched. The search starts at the maximum distance then - * moves toward zero. (Toward borders.) - * - * This number will always be divisible by 2. - */ - int dist = (field.maxBorderDistance() - 1) & ~1; - - /* - * Contains a list of spans that are considered to be flooded and - * therefore are ready to be processed. This list may contain nulls - * at certain points in the process. Nulls indicate spans that were - * initially in the list but have been successfully added to a region. - * The initial size is arbitrary. - */ - final ArrayList floodedSpans = - new ArrayList(1024); - - /* - * A predefined stack for use in the flood operation. Its content - * has no meaning outside the new region flooding operation. - * (Saves on object creation time.) - */ - final ArrayDeque workingStack = - new ArrayDeque(1024); - - final OpenHeightFieldIterator iter = field.dataIterator(); - - // Zero is reserved for the null-region. So initializing to 1. - int nextRegionID = 1; - - /* - * Search until the current distance reaches the minimum allowed - * distance. - * - * Note: This loop will not necessarily complete all region - * assignments. This is OK since a final region assignment step - * occurs after the loop iteration is complete. - */ - while (dist > minDist) - { - - // Find all spans that are at or below the current "water level" - // and are not already assigned to a region. Add these spans to - // the flooded span list for processing. - iter.reset(); - floodedSpans.clear(); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (span.regionID() == NULL_REGION - && span.distanceToBorder() >= dist) - // The span is not already assigned a region and is - // below the current "water level". So the span can be - // considered for region assignment. - floodedSpans.add(span); - } - - if (nextRegionID > 1) - { - // At least one region has already been created, so first - // try to put the newly flooded spans into existing regions. - if (dist > 0) - expandRegions(floodedSpans, expandIterations); - else - expandRegions(floodedSpans, -1); - } - - // Create new regions for all spans that could not be added to - // existing regions. - for (OpenHeightSpan span : floodedSpans) - { - if (span == null || span.regionID() != 0) - // This span was assigned to a newly created region - // during an earlier iteration of this loop. - // So it can be skipped. - continue; - // Fill to slightly more than the current "water level". - // This improves efficiency of the algorithm. - int fillTo = Math.max(dist - 2, minDist); - if (floodNewRegion(span, fillTo, nextRegionID, workingStack)) - // A new region was successfully generated. - nextRegionID++; - } - - // Increment the "water level" by 2, clamping at 0. - dist = Math.max(dist - 2, 0); - - } - - // Find all spans that haven't been assigned regions by the main loop. - // (Up to the minimum distance.) - iter.reset(); - floodedSpans.clear(); - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (span.distanceToBorder() >= - minDist && span.regionID() == NULL_REGION) - // Not a border or null region span. Should be in a region. - floodedSpans.add(span); - } - - // Perform a final expansion of existing regions. - // Allow more iterations than normal for this last expansion. - if (minDist > 0) - expandRegions(floodedSpans, expandIterations * 8); - else - expandRegions(floodedSpans, -1); - - field.setRegionCount(nextRegionID); - - // Run the post processing algorithms. - for (IOpenHeightFieldAlgorithm algorithm : mRegionAlgorithms) - { - algorithm.apply(field); - } - - } - - /** - * Attempts to find the most appropriate regions to attach spans to. - *

      Any spans successfully attached to a region will have their list - * entry set to null. So any non-null entries in the list will be spans - * for which a region could not be determined.

      - * @param inoutSpans As input, the list of spans available for formation - * of new regions. As output, the spans that could not be assigned - * to new regions. - * @param maxIterations If set to -1, will iterate through completion. - */ - private void expandRegions(ArrayList inoutSpans - , int maxIterations) - { - if (inoutSpans.size() == 0) - return; // No spans available to process. - - int iterCount = 0; - while(true) - { - /* - * The number of spans in the working list that have been - * successfully processed or could not be processed successfully - * for some reason. - * This value controls when iteration ends. - */ - int skipped = 0; - - // Loop through all spans in the working list. - for (int iSpan = 0; iSpan < inoutSpans.size(); iSpan++) - { - OpenHeightSpan span = inoutSpans.get(iSpan); - if (span == null) - { - // The span originally at this index location has - // already been successfully assigned a region. Nothing - // else to do with it. - skipped++; - continue; - } - // Default to unassigned. - int spanRegion = NULL_REGION; - // Default to highest possible distance. - int regionCenterDist = Integer.MAX_VALUE; - /* - * Search through this span's axis-neighbors. - * Reference: Neighbor searches - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - */ - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null) - // No neighbor at this location. - continue; - // There is a neighbor at this location. - if (nSpan.regionID() > NULL_REGION) - { - /* - * This neighbor span belongs to a region. - */ - if (nSpan.distanceToRegionCore() + 2 < regionCenterDist) - { - /* - * This neighbor is closer to its region core - * than previously detected neighbors. - */ - int sameRegionCount = 0; - if (mUseConservativeExpansion) - { - /* - * Check to ensure that this neighbor has - * at least two other neighbors in its region. - * This makes sure that adding this span to - * this neighbor's region will not result - * in a single width line of voxels. - */ - for (int ndir = 0; ndir < 4; ndir++) - { - OpenHeightSpan nnSpan = - nSpan.getNeighbor(ndir); - if (nnSpan == null) - // No diagonal-neighbor. - continue; - // There is a diagonal-neighbor - if (nnSpan.regionID() == nSpan.regionID()) - // This neighbor has a neighbor in - // the same region. - sameRegionCount++; - } - } - if (!mUseConservativeExpansion - || sameRegionCount > 1) - { - /* - * Either conservative expansion is turned off, - * or it is on and this neighbor's region is - * acceptable for the current span. - * Choose this neighbor's region. - * Set the current distance to center as - * slightly further than this neighbor. - */ - spanRegion = nSpan.regionID(); - regionCenterDist = - nSpan.distanceToRegionCore() + 2; - } - } - } - } - if (spanRegion != NULL_REGION) - { - // Found a suitable region for this span to belong to. - // Mark this index as having been processed. - inoutSpans.set(iSpan, null); - span.setRegionID(spanRegion); - span.setDistanceToRegionCore(regionCenterDist); - } - else - // Could not find an existing region for this span. - skipped++; - } - - if (skipped == inoutSpans.size()) - // All spans have either been processed or could not be - // processed during the last cycle. - break; - - if (maxIterations != -1) - { - iterCount++; - if (iterCount > maxIterations) - // Reached the iteration limit. - break; - } - - } - - } - - /** - * Creates a new region surrounding a span, adding neighbor spans to the - * new region as appropriate. - *

      The new region creation will fail if the root span is on the - * border of an existing region.

      - *

      All spans added to the new region as part of this process become - * "core" spans with a distance to region core of zero.

      - * @param rootSpan The span used to seed the new region. - * @param fillToDist The watershed distance to flood to. - * @param regionID The region ID to use for the new region. - * (If creation is successful.) - * @param workingStack A stack used internally. The content is - * cleared before use. Its content has no meaning outside of - * this operation. - * @return TRUE if a new region was created. Otherwise FALSE. - */ - private static boolean floodNewRegion(OpenHeightSpan rootSpan - , int fillToDist - , int regionID - , ArrayDeque workingStack) - { - workingStack.clear(); - // TODO: EVAL: Change this into a working argument? - // Don't want unneeded object creation. - ArrayList workingList = - new ArrayList(); - // See stack and list. - workingStack.push(rootSpan); - workingList.add(rootSpan); - rootSpan.setRegionID(regionID); // Seed with region id. - rootSpan.setDistanceToRegionCore(0); // Set as center of region. - - int regionSize = 0; - - while (workingStack.size() > 0) - { - - OpenHeightSpan span = workingStack.pop(); - - /* - * Check regions of neighbor spans. - * - * If any neighbor is found to have a region assigned, then - * the current span can't be in the new region. - * (Want standard flooding algorithm to handle deciding which - * region this span should go in.) - * - * Up to 8 neighbors are checked. - * - * Reference: Neighbor searches. - * http://www.critterai.org/?q=nmgen_hfintro#nsearch - */ - boolean isOnRegionBorder = false; - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan == null) - // No neighbor in this direction. - continue; - - // Check this axis-neighbor. - if (nSpan.regionID() != NULL_REGION - && nSpan.regionID() != regionID) - { - // Current span borders the null region or another region. - // No need to check rest of neighbors. - isOnRegionBorder = true; - break; - } - - // Check the diagonal-neighbor. - nSpan = nSpan.getNeighbor((dir+1) & 0x3); - if (nSpan != null - && nSpan.regionID() != NULL_REGION - && nSpan.regionID() != regionID) - { - // Current span borders the null region or another region. - // No need to check rest of neighbors. - isOnRegionBorder = true; - break; - } - } - if (isOnRegionBorder) - { - // Current span borders the null region or another region. - // Can't be part of the new region. - span.setRegionID(NULL_REGION); - continue; - } - - regionSize++; - - // If got this far, we know the current span is part of the new - // region. Now check its neighbors to see if they should be - // assigned to this new region. - for (int dir = 0; dir < 4; dir++) - { - OpenHeightSpan nSpan = span.getNeighbor(dir); - if (nSpan != null - && nSpan.distanceToBorder() >= fillToDist - && nSpan.regionID() == 0) - { - // This neighbor does not have a region assignment and - // it is within the allowed fill range. Set it as a - // candidate for this new region. - nSpan.setRegionID(regionID); - nSpan.setDistanceToRegionCore(0); - workingStack.push(nSpan); - workingList.add(nSpan); - } - } - } - - return (regionSize > 0); - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/PolyMeshField.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/PolyMeshField.java deleted file mode 100644 index 921ada6a..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/PolyMeshField.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents a set of related convex polygons within a bounded field. - *

      The polygons are usually connected (share edges), but are expected - * to not intersect.

      - *

      The data within this class is unprotected. So care must be taken.

      - *

      - * - *

      - * @see PolyMeshFieldBuilder - */ -public final class PolyMeshField - extends BoundedField -{ - - /* - * Recast Reference: rcPolyMesh in Recast.h - */ - - /** - * Represents an index value for a null (non-existent) vertex. - *

      This is required since polygons held within {@link #polys} are - * variable in size. So all entries for polygons within {@link #polys} - * that have fewer vertices than {@link #maxVertsPerPoly()} are padded - * with this value. See {@link #polys} for more information.

      - */ - public static final int NULL_INDEX = -1; - - /** - * The maximum vertices per polygon held within the {@link #polys} array. - * ({@link #maxVertsPerPoly()} * 2) represents the stride of the array. - *

      This value is informational only. There is no enforcement. - */ - private final int mMaxVertsPerPoly; - - /** - * The vertices that make up the field in the form (x, y, z). Value - * defaults to null. - */ - public int[] verts = null; - - /** - * Holds flattened polygon index and neighbor information. Value - * defaults to null. - *

      Where mvpp = {@link #maxVertsPerPoly()}:

      - *
        - *
      • Each polygon entry is 2*mvpp.
      • - *
      • The first mvpp of each entry contains the indices of the polygon. - * The first instance of {@link #NULL_INDEX} means the end of polygon - * indices for the entry.
      • - *
      • The second mvpp of each entry contains indices to neighbor - * polygons. A value of NULL_INDEX indicates no connection for that - * particular edge.
      • - *
      - *

      Example:

      - *

      If mvpp = 6, the polygon has 4 vertices and 2 neighbor - * connections.
      - * Then for (1, 3, 4, 8, NULL_INDEX, NULL_INDEX, 18, NULL_INDEX, 21, - * NULL_INDEX, NULL_INDEX, NULL_INDEX)
      - * (1, 3, 4, 8) defines the polygon.
      - * Polygon 18 shares edge 1->3.
      - * Polygon 21 shares edge 4->8.
      - * Edges 3->4 and 8->1 are border edges. (Not shared with any other - * polygon.)

      - */ - public int[] polys = null; - - /** - * Holds membership region data for each polygon in the form (regionID). - * Value defaults to null. - */ - public int[] polyRegions = null; - - /** - * Consructor - * @param gridBoundsMin The minimum bounds of the field in the form - * (minX, minY, minZ). - * @param gridBoundsMax The maximum bounds of the field in the form - * (maxX, maxY, maxZ). - * @param cellSize The size of the cells. (The grid that forms the base - * of the field.) - * @param cellHeight The height increment of the field. - * @param maxVertsPerPoly The maximum vertices per polygon. Value will - * be auto-clamped to >=3. - * @throws IllegalArgumentException If the bounds are null or the - * wrong size. - */ - public PolyMeshField(float[] gridBoundsMin - , float[] gridBoundsMax - , float cellSize - , float cellHeight - , int maxVertsPerPoly) - throws IllegalArgumentException - { - super(gridBoundsMin, gridBoundsMax, cellSize, cellHeight); - mMaxVertsPerPoly = Math.max(maxVertsPerPoly, 3); - } - - /** - * Gets the region ID of the polygon. - * @param polyIndex The index of the polygon. - * @return The region ID of the polygon, or -1 if the polygon index - * is invalid. - */ - public int getPolyRegion(int polyIndex) - { - if (polyIndex < 0 || polyIndex >= polyRegions.length) - return -1; - return polyRegions[polyIndex]; - } - - /** - * Gets an array containing the vertices of the polygon. - *

      This is a costly convenience operation.

      - * @param polyIndex The index of the polygon. - * @return An array containing the vertices of the polygon. - */ - public int[] getPolyVerts(int polyIndex) - { - - int pPoly = polyIndex*mMaxVertsPerPoly*2; - if (polyIndex < 0 || pPoly >= polys.length) - return null; - - // Determine the vertex count for this polygon. - int polyVertCount = getPolyVertCount(pPoly, polys, mMaxVertsPerPoly); - int[] result = new int[polyVertCount*3]; - - // Get the vertices. - for (int i = 0; i < polyVertCount; i++) - { - int pVert = polys[pPoly+i]*3; - result[i*3] = verts[pVert]; - result[i*3+1] = verts[pVert+1]; - result[i*3+2] = verts[pVert+2]; - } - - return result; - } - - /** - * The maximum vertices per polygon held within the {@link #polys} array. - * ({@link #maxVertsPerPoly()} * 2) represents the stride of the array. - *

      This value is informational only. There is no enforcement. - * @return The maximum vertices per polygon held within the - * {@link #polys} array. - */ - public int maxVertsPerPoly() { return mMaxVertsPerPoly; } - - /** - * The number of polygons in the {@link #polys} array. - * @return The number of vertices in the {@link #verts} array. - */ - public int polyCount() - { - if (polys == null) - return 0; - return polys.length / (2 * mMaxVertsPerPoly); - } - - /** - * The number of vertices in the {@link #verts} array. - * @return The number of vertices in the {@link #verts} array. - */ - public int vertCount() - { - if (verts == null) - return 0; - return verts.length / 3; - } - - /** - * Returns the vertex count for the specified polygon in the polygon array. - *

      The array is assumed to to be well formed (correct size and layout). - * Otherwise behavior is undefined.

      - *

      Basically, this operation starts counting array entries starting at - * the pointer. It continues to count until it runs into a NULL_INDEX - * value or reaches maxVertsPerPoly, whichever occurs first.

      - * @param polyPointer A pointer of the start of the polygon. - * @param polys An array of polygons in the standard format. - * (E.g. NULL_INDEX indicates end of the polygon and each entry is - * maxVertsPerPoly long.) - * @param maxVertsPerPoly The maximum number of vertices for a polygon - * in the array. - * @return The number of vertices for the specified polygon. - */ - static int getPolyVertCount(int polyPointer - , int[] polys - , int maxVertsPerPoly) - { - for (int i = 0; i < maxVertsPerPoly; i++) - if (polys[polyPointer+i] == NULL_INDEX) - // Ran into a null index. No more vertices for this polygon. - return i; - return maxVertsPerPoly; - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/PolyMeshFieldBuilder.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/PolyMeshFieldBuilder.java deleted file mode 100644 index 01065970..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/PolyMeshFieldBuilder.java +++ /dev/null @@ -1,1487 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; -import java.util.Hashtable; -import java.util.logging.Logger; - -/** - * Builds an convex polygon mesh consisting of variable sized polygons. - * The mesh is generated from contour data contained by a {@link ContourSet} - * object. - *

      - *

      - * @see Convex Polygon Generation - * @see PolyMeshField - */ -public final class PolyMeshFieldBuilder -{ - - /* - * Design notes: - * - * Recast Reference: rcBuildPolyMesh in RecastMesh.cpp - * - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - */ - - private static final Logger logger = - Logger.getLogger(PolyMeshFieldBuilder.class.getName()); - - /* - * Flag and associated deflag. Used during triangulation. - */ - private static final int FLAG = 0x80000000; - private static final int DEFLAG = 0x0fffffff; - - /** - * IMPORTANT: Only use this value during creation of the - * {@link PolyMeshField} objects. After that, use the value from the - * object since the object may alter the value. - */ - private final int mMaxVertsPerPoly; - - /** - * Constructor. - * @param maxVertsPerPoly The maximum vertices per polygon. The builder - * will not create polygons with more than this number of vertices. - */ - public PolyMeshFieldBuilder(int maxVertsPerPoly) - { - mMaxVertsPerPoly = maxVertsPerPoly; - } - - /** - * Builds a convex polygon mesh from the provided contour set. - *

      This build algorithm will fail and return null if the - * {@link ContourSet} contains any single contour with more than - * 0x0fffffff vertices. - * @param contours A properly populated contour set. - * @return The result of the build operation. - */ - public PolyMeshField build(ContourSet contours) - { - // Initialize - if (contours == null || contours.size() == 0) - return null; - - // Construct the result object. - PolyMeshField result = new PolyMeshField(contours.boundsMin() - , contours.boundsMax() - , contours.cellSize() - , contours.cellHeight() - , mMaxVertsPerPoly); - - // Number of vertices found in the source. - int sourceVertCount = 0; - - // The maximum possible number of polygons assuming that all will - // be triangles. - int maxPossiblePolygons = 0; - - // The maximum vertices found in a single contour. - int maxVertsPerContour = 0; - - // Loop through all contours. Determine the values for the - // variables above. - for (int contourIndex = 0 - ; contourIndex < contours.size() - ; contourIndex++) - { - int count = contours.get(contourIndex).vertCount; - sourceVertCount += count; - maxPossiblePolygons += count - 2; - maxVertsPerContour = Math.max(maxVertsPerContour, count); - } - - if (sourceVertCount - 1 > DEFLAG) - { - // Too man vertices to be able to process. Will run into the - // the flag value. - logger.severe("Polygon mesh generation failed: One or more" + - " input contours contain more than the maximum" + - " allowed vertices. (" + DEFLAG + ")"); - return null; - } - - /* - * Holds the unique vertices found during triangulation. - * This array is sized to hold the maximum possible vertices. - * The actual number of vertices will be smaller due to duplication - * in the source contours. - */ - final int[] globalVerts = new int[sourceVertCount * 3]; - int globalVertCount = 0; - - /* - * Holds polygon indices. - * - * The array is sized to hold the maximum possible polygons. - * The actual number will be significantly smaller once polygons - * are merged. - * - * Where mvpp = maximum vertices per polygon: - * - * Each polygon entry is mvpp. The first instance of NULL_INDEX means - * the end of poly indices. - * - * Example: If nvp = 6 and the the polygon has 4 vertices -> - * (1, 3, 4, 8, NULL_INDEX, NULL_INDEX) - * then (1, 3, 4, 8) defines the polygon. - */ - final int[] globalPolys = - new int[maxPossiblePolygons * mMaxVertsPerPoly]; - - // Fill with null index. - for (int i = 0; i < globalPolys.length; i++) - globalPolys[i] = PolyMeshField.NULL_INDEX; - - final int[] globalRegions = new int[maxPossiblePolygons]; - int globalPolyCount = 0; - - /* - * Holds information that allows mapping of contour vertex indices to - * shared vertex indices. (i.e. Index of vertex in contour.verts[] - * to index of vertex in within this operation.) - * - * index (key): The original vertex index of the contour. - * value in array: The vertex index in the shared vertex array. - * - * This is a working variable whose content is meaningless between - * iterations. It will contain cross-iteration trash. But that is - * OK because of the way the array is used. (I.e. Trash data left - * over from a previous iteration will never be accessed in the - * current iteration.) - */ - final int[] contourToGlobalIndicesMap = new int[maxVertsPerContour]; - - /* - * Key = Hash representing a unique vertex location. - * Value = The index of the vertex in the global vertices array. - * When a new vertex is found, it is added to the vertices array and - * its global index stored in this hash table. If a duplicate is - * found, the value from this table is used. - * There will always be duplicate vertices since different contours - * are connected by these duplicate vertices. - */ - final Hashtable vertIndices = - new Hashtable(); - - // Each list is initialized to a size that will minimize resizing. - final ArrayList workingIndices = - new ArrayList(maxVertsPerContour); - final ArrayList workingTriangles = - new ArrayList(maxVertsPerContour); - - // Various working variables. - // (Values are meaningless outside of the iteration.) - final int[] workingPolys = - new int[(maxVertsPerContour + 1) * mMaxVertsPerPoly]; - int workingPolyCount = 0; - final int[] mergeInfo = new int[3]; - final int[] mergedPoly = new int[mMaxVertsPerPoly]; - - // Process all contours. - for (int contourIndex = 0 - ; contourIndex < contours.size() - ; contourIndex++) - { - Contour contour = contours.get(contourIndex); - if (contour.verts.length < 3 * 4) - { - // This indicates a problem with contour creation - // since the contour builder should detect for this. - logger.severe("Polygon generation failure: Contour has " + - "too few vertices. Bad input data. Region " + - contour.regionID); - continue; - } - - // Create working indices for the contour vertices. - workingIndices.clear(); - for (int i = 0; i < contour.vertCount; i++) - workingIndices.add(i); - - // Triangulate the contour. - int triangleCount = triangulate(contour.verts - , workingIndices - , workingTriangles); - - if (triangleCount <= 0) - { - /* - * Failure of the triangulation. - * This is known to occur if the source polygon is - * self-intersecting or the source region contains internal - * holes. In both cases, the problem is likely due to bad - * region formation. - */ - logger.severe("Polygon generation failure: Could not" + - " triangulate contour. Region " + contour.regionID); - continue; - } - - /* - * Loop through the vertices in this contour. - * For new vertices (not seen in previous contours) get a new - * index and add it to the global vertices array. - */ - for (int iContourVert = 0 - ; iContourVert < contour.vertCount - ; iContourVert++) - { - int pContourVert = iContourVert*4; - int vertHash = getHashCode(contour.verts[pContourVert] - , contour.verts[pContourVert+1] - , contour.verts[pContourVert+2]); - Integer iGlobalVert = vertIndices.get(vertHash); - if (iGlobalVert == null) - { - // This is the first time this vertex has been seen. - // Assign it an index and add it to the vertex array. - iGlobalVert = globalVertCount; - globalVertCount++; - vertIndices.put(vertHash, iGlobalVert); - globalVerts[iGlobalVert*3] = contour.verts[pContourVert]; - globalVerts[iGlobalVert*3+1] = - contour.verts[pContourVert+1]; - globalVerts[iGlobalVert*3+2] = - contour.verts[pContourVert+2]; - } - // Creat the map entry. Contour vertex index -> global - // vertex index. - contourToGlobalIndicesMap[iContourVert] = iGlobalVert; - } - - - - // Initialize the working polygon array. - for (int i = 0; i < workingPolys.length; i++) - workingPolys[i] = PolyMeshField.NULL_INDEX; - - // Load the triangles into to the working polygon array, updating - // indices in the process. - workingPolyCount = 0; - for (int i = 0; i < triangleCount; i++) - { - /* - * The working triangles list contains vertex index data - * from the contour. The working polygon array needs the - * global vertex index. So the indices mapping array created - * above is used to do the conversion. - */ - workingPolys[workingPolyCount*mMaxVertsPerPoly] - = contourToGlobalIndicesMap[ - workingTriangles.get(i*3)]; - workingPolys[workingPolyCount*mMaxVertsPerPoly+1] - = contourToGlobalIndicesMap[ - workingTriangles.get(i*3+1)]; - workingPolys[workingPolyCount*mMaxVertsPerPoly+2] - = contourToGlobalIndicesMap[ - workingTriangles.get(i*3+2)]; - workingPolyCount++; - } - - if (mMaxVertsPerPoly > 3) - { - // Merging of triangles into larger polygons is permitted. - // Continue until no polygons can be found to merge. - // http://www.critterai.org/nmgen_polygen#mergepolys - while(true) - { - - int longestMergeEdge = -1; - int pBestPolyA = -1; - int iPolyAVert = -1; // Start of the shared edge. - int pBestPolyB = -1; - int iPolyBVert = -1; // Start of the shared edge. - - // Loop through all but the last polygon looking for the - // best polygons to merge in this iteration. - for (int iPolyA = 0 - ; iPolyA < workingPolyCount - 1 - ; iPolyA++) - { - for (int iPolyB = iPolyA + 1 - ; iPolyB < workingPolyCount - ; iPolyB++) - { - // Can polyB merge with polyA? - getPolyMergeInfo(iPolyA*mMaxVertsPerPoly - , iPolyB*mMaxVertsPerPoly - , workingPolys - , globalVerts - , result.maxVertsPerPoly() - , mergeInfo); - if (mergeInfo[0] > longestMergeEdge) - { - // polyB has the longest shared edge with - // polyA found so far. Save the merge - // information. - longestMergeEdge = mergeInfo[0]; - pBestPolyA = iPolyA * mMaxVertsPerPoly; - iPolyAVert = mergeInfo[1]; - pBestPolyB = iPolyB * mMaxVertsPerPoly; - iPolyBVert = mergeInfo[2]; - } - } - } - - if (longestMergeEdge <= 0) - // No valid merges found during this iteration. - break; - - // Found polygons to merge. Perform the merge. - - // Prepare the merged polygon array. - for (int i = 0; i < mergedPoly.length; i++) - mergedPoly[i] = PolyMeshField.NULL_INDEX; - - // Get the size of each polygon. - final int vertCountA - = PolyMeshField.getPolyVertCount(pBestPolyA - , workingPolys - , result.maxVertsPerPoly()); - final int vertCountB - = PolyMeshField.getPolyVertCount(pBestPolyB - , workingPolys - , result.maxVertsPerPoly()); - int position = 0; - - /* - * Fill the mergedPoly array. - * Start the vertex at the end of polygon A's shared edge. - * Add all vertices until looping back to the vertex just - * before the start of the shared edge. Repeat for - * polygon B. - * - * Duplicate vertices are avoided, while ensuring we get - * all vertices, since each loop drops the vertex that - * starts its polygon's shared edge and: - * - * PolyAStartVert == PolyBEndVert and - * PolyAEndVert == PolyBStartVert. - */ - for (int i = 0; i < vertCountA - 1; i++) - mergedPoly[position++] = workingPolys[pBestPolyA - + ((iPolyAVert+1+i) % vertCountA)]; - for (int i = 0; i < vertCountB - 1; i++) - mergedPoly[position++] = workingPolys[pBestPolyB - + ((iPolyBVert+1+i) % vertCountB)]; - - // Copy the merged polygon over the top of polygon A. - System.arraycopy(mergedPoly - , 0 - , workingPolys - , pBestPolyA - , mMaxVertsPerPoly); - // Remove polygon B by shifting all information to the - // left by one polygon, starting at polygon B. - System.arraycopy(workingPolys - , pBestPolyB + mMaxVertsPerPoly - , workingPolys, pBestPolyB - , workingPolys.length - - pBestPolyB - mMaxVertsPerPoly); - workingPolyCount--; - } - - } - - // Polygon creation for this contour is complete. - // Add polygons to the global polygon array and store region - // information. - - for (int i = 0; i < workingPolyCount; i++) - { - // Copy the polygon from the working array to the - // correct position in the global array. - System.arraycopy(workingPolys, i * mMaxVertsPerPoly - , globalPolys, globalPolyCount * mMaxVertsPerPoly - , mMaxVertsPerPoly); - globalRegions[globalPolyCount] = contour.regionID; - globalPolyCount++; - } - - } - - /* - * Transfer global array information into instance fields. - * Could have loaded data directly into instance fields and saved this - * processing cost. But this method has memory benefits since it is - * not necessary to oversize the instance arrays. - */ - - // Transfer vertex data. - result.verts = new int[globalVertCount * 3]; - System.arraycopy(globalVerts, 0, result.verts, 0, globalVertCount * 3); - - /* - * Transfer polygon indices data. - * - * The global polygon array is half the size of the instance polygon - * array since the instance polygon array also contains edge adjacency - * information. So array copy can't be used. - * - * Instead, copy the global polygon array over to instance polygon - * array in blocks and initialize the instance polygon array's - * adjacency information. - */ - result.polys = new int[globalPolyCount * mMaxVertsPerPoly * 2]; - for (int iPoly = 0; iPoly < globalPolyCount; iPoly++) - { - int pPoly = iPoly*mMaxVertsPerPoly; - for (int offset = 0; offset < mMaxVertsPerPoly; offset++) - { - // Transfer index information. - result.polys[pPoly*2+offset] = globalPolys[pPoly+offset]; - // Initialize edge's adjacency field. - result.polys[pPoly*2+mMaxVertsPerPoly+offset] = - PolyMeshField.NULL_INDEX; - } - } - - // Transfer region data. - result.polyRegions = new int[globalPolyCount]; - System.arraycopy(globalRegions - , 0 - , result.polyRegions - , 0 - , globalPolyCount); - - // Build polygon adjacency information. - buildAdjacencyData(result); - - return result; - - } - - /** - * The maximum vertices per polygon. The builder will not create - * polygons with more than this number of vertices. - * @return The maximum vertices per polygon. - */ - public int maxVertsPerPoly() { return mMaxVertsPerPoly; } - - /** - * Searches all polygons and adds adjacency data to the - * {@link PolyMeshField#polys} array. - *

      All other data initialization must have been completed before - * calling this operation. It is expected that all adjacency fields - * within the {@link PolyMeshField#polys} array have been initialized - * to NULL_INDEX before calling this operation. - * @param mesh The mesh to use. - */ - private static void buildAdjacencyData(PolyMeshField mesh) - { - - int vertCount = mesh.verts.length / 3; - // Purposely using the region count to avoid the division. - int polyCount = mesh.polyRegions.length; - - int maxEdgeCount = polyCount * mesh.maxVertsPerPoly(); - - /* - * Holds edge information - * - * IMPORTANT: This array does not catalog all edges. It is only - * guaranteed to catalog all shared edges. It will contain only a - * sub-set of border edges, which are edges only connected to a - * single polygon. - * - * Format: - * 0: Index of primary vertex connected to the edge. This index's - * value will always be less than the value of the secondary index. - * 1: Index of secondary vertex connected to the edge. - * 2: Index of polygon A connected to this edge. - * 3: Polygon A vertex offset. - * 4: Index of polygon B connected to this edge. - * (Or NULL_INDEX if this is a border edge.) - * 5: Polygon B vertex offset. - * (Only meaningful if 4 != NULL_INDEX.) - */ - int[] edges = new int[maxEdgeCount * 6]; - int edgeCount = 0; - - /* - * An array used in edge searches based on an edge's primary index. - * - * Index: Vertex index - * Value: An index to an edge in the edges array that has the vertex - * as its primary vertex. - * - * Example of use: - * - * Vertex index = 10; - * startEdge[10] = 8 -> This vertex is the primary vertex for edge 8. - * edges[8 * 6] <- Edge definition. - * nextEdge[8] = 12 -> This vertex is also the primary vertex for - * edge 12. - * nextEdge[12] = 15 -> This vertex is also the primary vertex for - * edge 15. - * nextEdge[15] = NULL_INDEX -> This edge is not the primary index - * for any further edges. - * - * If the value for a vertex is NULL_INDEX then the vertex is not a - * primary vertex for any known edge. (This can occur because not - * all border edges are cataloged by this algorithm.) - */ - int[] startEdge = new int[vertCount]; - for (int i = 0; i < startEdge.length; i++) - startEdge[i] = PolyMeshField.NULL_INDEX; - - /* - * An array used in edge searches. - * - * Use the startEdge array to get an index to a value in this array - * in order to start an edge search. See doc for startEdge for details. - * - * Index: Edge Index Same index used for the edges array and as - * values in the startEdge array. - * - * Value: Edge index of next edge attacked to the same vertex. - * (Or NULL_INDEX if there are no more connected edges.) - */ - int[] nextEdge = new int[maxEdgeCount]; - - /* - * Loop through all polygons. - * Find all shared edges. Populate all data arrays. - * At the end of this loop, all data will be gathered except for - * fields 4 and 5 in the edge array entries. - */ - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - int pPoly = iPoly * mesh.maxVertsPerPoly() * 2; - // Loop through each polygon vertex index. - for (int vertOffset = 0 - ; vertOffset < mesh.maxVertsPerPoly() - ; vertOffset++) - { - int iVert = mesh.polys[pPoly+vertOffset]; - if (iVert == PolyMeshField.NULL_INDEX) - // Reached the end of this polygon. - break; - - int iNextVert; - if (vertOffset + 1 >= mesh.maxVertsPerPoly() - || mesh.polys[pPoly+vertOffset+1] - == PolyMeshField.NULL_INDEX) - // Need to wrap to the beginning. This will only happen - // once per iteration since the loop will be forced to - // end during the next iteration. - iNextVert = mesh.polys[pPoly]; - else - // The next vertex in the array is a valid vertex in - // the polygon. - iNextVert = mesh.polys[pPoly+vertOffset+1]; - - /* - * This next check does several useful things: - * - It ensures that a particular edge is never selected - * twice since, for shared edges, this condition will - * only exist for one of the polygons. - * - Some border edges will be skipped entirely, saving - * some processing time. - */ - if (iVert < iNextVert) - { - // This is an edge's primary vertex. - // Set the vertices connected to this edge. - edges[edgeCount*6] = iVert; - edges[edgeCount*6+1] = iNextVert; - // Set the polygons associated with this edge. - edges[edgeCount*6+2] = iPoly; - edges[edgeCount*6+3] = vertOffset; - // Default to unconnected. (Border edge.) - edges[edgeCount*6+4] = PolyMeshField.NULL_INDEX; - edges[edgeCount*6+5] = PolyMeshField.NULL_INDEX; - - /* - * Update the search arrays. - * The first time a vertex is assigned as an edge's - * primary vertex, the NULL_INDEX will be copied into - * nextEdge, indicating the end of a vertex chain. - * - * The 2nd time a vertex is assign as an edge's primary - * vertex, the original edge pointer from startEdge - * is added to nextEdge, and startEdge is assigned - * the new starting edge. This results in a stack-like - * storage mechanism. - * - * The process is repeated every time the vertex is - * assigned as a primary vertex, creating a chain. - */ - nextEdge[edgeCount] - = startEdge[iVert]; - startEdge[iVert] = edgeCount; - - edgeCount++; - } - - } - } - - /* - * Loop through all polygons. - * Find the the 2nd polygon's information for all shared edges. - * (Fields 4 and 5 of the edge array entries.) - */ - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - int pPoly = iPoly * mesh.maxVertsPerPoly() * 2; - // Loop through each polygon vertex index. - for (int vertOffset = 0 - ; vertOffset < mesh.maxVertsPerPoly() - ; ++vertOffset) - { - int iVert = mesh.polys[pPoly+vertOffset]; - if (iVert == PolyMeshField.NULL_INDEX) - // Reached the end of this polygon. - break; - - int iNextVert; - if (vertOffset + 1 >= mesh.maxVertsPerPoly() - || mesh.polys[pPoly+vertOffset+1] - == PolyMeshField.NULL_INDEX) - // Need to wrap to the beginning. This will only happen - // once per iteration since the loop will be forced to - // end during the next iteration. - iNextVert = mesh.polys[pPoly]; - else - // The next vertex in the array is a valid vertex in - // the polygon. - iNextVert = mesh.polys[pPoly+vertOffset+1]; - - // Note that this next conditional is reversed from that - // used in the previous loop. - if (iVert > iNextVert) - { - /* - * iVert is NOT a primary vertex in this case. We are - * looking for the "other" polygon that shares this edge. - * If there is another polygon sharing this edge, its - * primary vertex will be iNextVert. - * - * Climb the edge chain for iNextVert, looking for an - * edge that has iVert as its secondary vertex. - */ - // Loop halts at the end of the chain. - for (int edgeIndex = startEdge[iNextVert] - ; edgeIndex != PolyMeshField.NULL_INDEX - ; edgeIndex = nextEdge[edgeIndex]) - { - if (edges[edgeIndex*6+1] == iVert) - { - // Found a shared edge. Assign this polygon - // as the secondary connected polygon. - edges[edgeIndex*6+4] = iPoly; - edges[edgeIndex*6+5] = vertOffset; - break; - } - } - } - } - } - - // All necessary data has been gathered. Any edge in the edge array - // that has both polygons assigned is a shared edge. - - // Store adjacency information. - // Loop through all edges. - for (int pEdge = 0; pEdge < edgeCount; pEdge += 6) - { - if (edges[pEdge+4] != PolyMeshField.NULL_INDEX) - { - // The second polygon in this edge is set. - // So this is a shared edge. - int pPolyA = edges[pEdge+2] * mesh.maxVertsPerPoly() * 2; - int pPolyB = edges[pEdge+4] * mesh.maxVertsPerPoly() * 2; - // In the second section of the polygon definition, where - // connection information is stored, put the polygon index - // into the same position as the edge's primary vertex. - mesh.polys[pPolyA + mesh.maxVertsPerPoly() + edges[pEdge+3]] - = edges[pEdge+4]; - mesh.polys[pPolyB + mesh.maxVertsPerPoly() + edges[pEdge+5]] - = edges[pEdge+2]; - } - } - - } - - /** - * Provides a hash value unique to the combination of values. - * @param x The vertices x-value. (x, y, z) - * @param y The vertices y-value. (x, y, z) - * @param z The vertices z-value. (x, y, z) - * @return A hash that is unique to the vertex. - */ - private static int getHashCode(int x, int y, int z) - { - /* - * Note: Tried the standard eclipse hash generation method. But - * it resulted in non-unique hash values during testing. Switched - * to this method. - * Hex values are arbitrary prime numbers. - */ - return 0x8da6b343 * x + 0xd8163841 * y + 0xcb1ab31f * z; - } - - /** - * Returns the index incremented by one, or if the increment causes - * an out of range high the minimum allowed index is returned. - * (e.g. Wrapping) - * @param i The index. - * @param n The size of the array the index belongs to. - * @return Returns the index incremented by one with wrapping. - */ - private static int getNextIndex(int i, int n) - { - return i+1 < n ? i+1 : 0; - } - - /** - * Checks two polygons to see if they can be merged. If a merge is - * allowed, provides data via the outResult argument. - *

      outResult will be an array of size 3 with the following - * information:

      - *

      0: The lenghtSq of the edge shared between the polygons.
      - * 1: The index (not pointer) of the start of the shared edge in - * polygon A.
      - * 2: The index (not pointer) of the start of the shared edge in - * polygon B.
      - *

      - *

      A value of -1 at index zero indicates one of the following:

      - *
        - *
      • The polygons cannot be merged because they would contain too - * many vertices.
      • - *
      • The polygons do not have a shared edge.
      • - *
      • Merging the polygons would result in a concave polygon.
      • - *
      - *

      To convert the values at indices 1 and 2 to pointers: - * (polyPointer + value)

      - * @param polyAPointer The pointer to the start of polygon A in the - * polys argument. - * @param polyBPointer The pointer to the start of polygon B in the - * polys argument. - * @param polys An array of polygons in the form: - * (vert1, vert2, vert3, ..., vertN, NULL_INDEX). - * The null index terminates every polygon. This permits polygons - * with different vertex counts. - * @param verts The vertex data associated with the polygons. - * @param outResult An array of size three which contains merge information. - */ - private static void getPolyMergeInfo(int polyAPointer - , int polyBPointer - , int[] polys - , int[] verts - , int maxVertsPerPoly - , int[] outResult) - { - - outResult[0] = -1; // Default to invalid merge - outResult[1] = -1; - outResult[2] = -1; - - final int vertCountA = PolyMeshField.getPolyVertCount(polyAPointer - , polys - , maxVertsPerPoly); - final int vertCountB = PolyMeshField.getPolyVertCount(polyBPointer - , polys - , maxVertsPerPoly); - - // If the merged polygon would would have to many vertices, do not - // merge. Subtracting two since to take into account the effect of - // a merge. - if (vertCountA + vertCountB - 2 > maxVertsPerPoly) - return; - - /* - * Check if the polygons share an edge. - * - * Loop through all of vertices for polygonA and extract its edge. - * (vertA -> vertANext) Then loop through all vertices for polygonB - * and check to see if any of its edges use the same vertices as - * polygonA. - */ - for (int iPolyVertA = 0; iPolyVertA < vertCountA; iPolyVertA++) - { - // Get the vertex indices for the polygonA edge - final int iVertA = polys[polyAPointer+iPolyVertA]; - final int iVertANext = polys[polyAPointer - + getNextIndex(iPolyVertA, vertCountA)]; - // Search polygonB for matches. - for (int iPolyVertB = 0; iPolyVertB < vertCountB; iPolyVertB++) - { - // Get the vertex indices for the polygonB edge. - final int iVertB = polys[polyBPointer+iPolyVertB]; - final int iVertBNext = polys[polyBPointer - + getNextIndex(iPolyVertB, vertCountB)]; - if (iVertA == iVertBNext && iVertANext == iVertB) - { - // The vertex indices for this edge are the same and - // sequenced in opposite order. So the edge is shared. - outResult[1] = iPolyVertA; - outResult[2] = iPolyVertB; - } - } - } - - if (outResult[1] == -1) - // No common edge, cannot merge. - return; - - /* - * Check to see if the merged polygon would be convex. - * - * Gets the vertices near the section where the merge would occur. - * Do they form a concave section? If so, the merge is invalid. - * - * Note that the following algorithm is only valid for clockwise - * wrapped convex polygons. - */ - - int pSharedVertMinus, pSharedVert, pSharedVertPlus; - - pSharedVertMinus = polys[polyAPointer - + getPreviousIndex(outResult[1], vertCountA)] * 3; - pSharedVert = polys[polyAPointer + outResult[1]] * 3; - pSharedVertPlus = polys[polyBPointer - + ((outResult[2]+2) % vertCountB)] * 3; - if (!isLeft(verts[pSharedVert] - , verts[pSharedVert+2] - , verts[pSharedVertMinus] - , verts[pSharedVertMinus+2] - , verts[pSharedVertPlus] - , verts[pSharedVertPlus+2])) - /* - * The shared vertex (center) is not to the left of segment - * vertMinus->vertPlus. For a clockwise wrapped polygon, this - * indicates a concave section. Merged polygon would be concave. - * Invalid merge. - */ - return; - - pSharedVertMinus = polys[polyBPointer - + getPreviousIndex(outResult[2], vertCountB)] * 3; - pSharedVert = polys[polyBPointer + outResult[2]] * 3; - pSharedVertPlus = polys[polyAPointer - + ((outResult[1]+2) % vertCountA)] * 3; - if (!isLeft(verts[pSharedVert] - , verts[pSharedVert+2] - , verts[pSharedVertMinus] - , verts[pSharedVertMinus+2] - , verts[pSharedVertPlus] - , verts[pSharedVertPlus+2])) - /* - * The shared vertex (center) is not to the left of segment - * vertMinus->vertPlus. For a clockwise wrapped polygon, this - * indicates a concave section. Merged polygon would be concave. - * Invalid merge. - */ - return; - - // Get the vertex indices that form the shared edge. - pSharedVertMinus = polys[polyAPointer + outResult[1]] * 3; - pSharedVert = polys[polyAPointer - + getNextIndex(outResult[1], vertCountA)] * 3; - - // Store the lengthSq of the shared edge. - final int deltaX = verts[pSharedVertMinus+0] - verts[pSharedVert+0]; - final int deltaZ = verts[pSharedVertMinus+2] - verts[pSharedVert+2]; - outResult[0] = deltaX*deltaX + deltaZ*deltaZ; - - } - - /** - * Returns the index decremented by one, or if the decrement causes an - * out of range low the maximum allowed index is returned. (e.g. Wrapping) - * @param i The index. - * @param n The size of the array the index belongs to. - * @return Returns the index decremented by one with wrapping. - */ - private static int getPreviousIndex(int i, int n) - { - return i-1 >= 0 ? i-1 : n-1; - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle defined by points (A, B, C). - *

      A positive value indicates:

      - *
        - *
      • Counterclockwise wrapping of the points.
      • - *
      • Point B lies to the right of line AC, looking from A to C.
      • - *
      - *

      A negative value indicates:

      - *
        - *
      • Clockwise wrapping of the points.
      • - *
      • Point B lies to the left of line AC, looking from A to C.
      • - *
      - *

      A value of zero indicates that all points are collinear or - * represent the same point.

      - *

      This is a fast operation.

      - * @param ax The x-value for point (ax, ay) for vertex A of the triangle. - * @param ay The y-value for point (ax, ay) for vertex A of the triangle. - * @param bx The x-value for point (bx, by) for vertex B of the triangle. - * @param by The y-value for point (bx, by) for vertex B of the triangle. - * @param cx The x-value for point (cx, cy) for vertex C of the triangle. - * @param cy The y-value for point (cx, cy) for vertex C of the triangle. - * @return The signed value of two times the area of the triangle defined - * by the points (A, B, C). - */ - private static int getSignedAreaX2(int ax, int ay - , int bx, int by - , int cx, int cy) - { - /* - * References: - * - * http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm - * #Modern%20Triangles - * http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - * - */ - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - - /** - * Returns TRUE if the line segment AB intersects any edges not already - * connected to one of the two vertices. - *

      The test is only performed on the xz-plane.

      - *

      Assumptions:

      - *
        - *
      • The vertices and indices arguments define a valid simple polygon - * with vertices wrapped clockwise.
      • - *
      • indexA != indexB
      • - *
      - *

      Behavior is undefined if the arguments to not meet these - * assumptions

      - * @param indexA An polygon index of a vertex that will form segment AB. - * @param indexB An polygon index of a vertex that will form segment AB. - * @param verts The vertices array in the form (x, y, z, id). The value - * stored at the id position is not relevant to this operation. - * @param indices A simplpe polygon wrapped clockwise. - * @return TRUE if the line segment AB intersects any edges not already - * connected to one of the two vertices. Otherwise FALSE. - */ - private static boolean hasIllegalEdgeIntersection(int indexA - , int indexB - , int[] verts - , ArrayList indices) - { - - // Get pointers to the primary vertices being tested. - int pVertA = (indices.get(indexA) & DEFLAG) * 4; - int pVertB = (indices.get(indexB) & DEFLAG) * 4; - - // Loop through the polygon edges. - for (int iPolyEdgeBegin = 0 - ; iPolyEdgeBegin < indices.size() - ; iPolyEdgeBegin++) - { - int iPolyEdgeEnd = getNextIndex(iPolyEdgeBegin, indices.size()); - if (!(iPolyEdgeBegin == indexA - || iPolyEdgeBegin == indexB - || iPolyEdgeEnd == indexA - || iPolyEdgeEnd == indexB)) - { - // Neither of the test indices are endpoints of this edge. - // Get pointers for this edge's verts. - int pEdgeVertBegin = (indices.get(iPolyEdgeBegin) & DEFLAG) * 4; - int pEdgeVertEnd = (indices.get(iPolyEdgeEnd) & DEFLAG) * 4; - if ((verts[pEdgeVertBegin] == verts[pVertA] - && verts[pEdgeVertBegin+2] == verts[pVertA+2]) - || (verts[pEdgeVertBegin] == verts[pVertB] - && verts[pEdgeVertBegin+2] == verts[pVertB+2]) - || (verts[pEdgeVertEnd] == verts[pVertA] - && verts[pEdgeVertEnd+2] == verts[pVertA+2]) - || (verts[pEdgeVertEnd] == verts[pVertB] - && verts[pEdgeVertEnd+2] == verts[pVertB+2])) - /* - * One of the test vertices is co-located on the xz plane - * with one of the endpoints of this edge. (This is a - * test of the actual position of the verts rather than - * simply the index check performed earlier.) - * Skip this edge. - */ - continue; - - /* - * This edge is not connected to either of the test vertices. - * If line segment AB intersects with this edge, then the - * intersection is illegal. - * I.e. New edges cannot cross existing edges. - */ - if (Geometry.segmentsIntersect(verts[pVertA] - , verts[pVertA+2] - , verts[pVertB] - , verts[pVertB+2] - , verts[pEdgeVertBegin] - , verts[pEdgeVertBegin+2] - , verts[pEdgeVertEnd] - , verts[pEdgeVertEnd+2])) - return true; - - } - } - - return false; - } - - /** - * Returns TRUE if point P is to the left of line AB when looking - * from A to B. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the left of line AB when looking - * from A to B. Otherwise FALSE. - */ - private static boolean isLeft(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) < 0; - } - - /** - * Returns TRUE if point P is to the left of line AB when looking - * from A to B or is collinear with line AB. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the left of line AB when looking - * from A to B, or is collinear with line AB. Otherwise FALSE. - */ - private static boolean isLeftOrCollinear(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) <= 0; - } - - /** - * Returns TRUE if point P is to the right of line AB when looking - * from A to B. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the right of line AB when looking - * from A to B. - */ - private static boolean isRight(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) > 0; - } - - /** - * Returns TRUE if point P is to the right of or on line AB when looking - * from A to B. - * @param px The x-value of the point to test. - * @param py The y-value of the point to test. - * @param ax The x-value of the point (ax, ay) that is point A on line AB. - * @param ay The y-value of the point (ax, ay) that is point A on line AB. - * @param bx The x-value of the point (bx, by) that is point B on line AB. - * @param by The y-value of the point (bx, by) that is point B on line AB. - * @return TRUE if point P is to the right of or on line AB when looking - * from A to B. - */ - private static boolean isRightOrCollinear(int px, int py - , int ax, int ay - , int bx, int by) - { - return getSignedAreaX2(ax, ay, px, py, bx, by) >= 0; - } - - /** - * Returns TRUE if the line segment formed by vertex A and vertex B will - * form a valid partition of the polygon. - *

      I.e. New line segment AB is internal to the polygon and will not - * cross existing line segments.

      - *

      The test is only performed on the xz-plane.

      - *

      Assumptions:

      - *
        - *
      • The vertices and indices arguments define a valid simple polygon - * with vertices wrapped clockwise.
      • - *
      • indexA != indexB
      • - *
      - *

      Behavior is undefined if the arguments to not meet these - * assumptions

      - * @param indexA An polygon index of a vertex that will form segment AB. - * @param indexB An polygon index of a vertex that will form segment AB. - * @param verts The vertices array in the form (x, y, z, id). The value - * stored at the id position is not relevant to this operation. - * @param indices A simplpe polygon wrapped clockwise. - * @return TRUE if the line segment formed by vertex A and vertex B will - * form a valid partition of the polygon. Otherwise false. - */ - private static boolean isValidPartition(int indexA - , int indexB - , int[] verts - , ArrayList indices) - { - /* - * First check whether the segment AB lies within the internal - * angle formed at A. (This is the faster check.) - * If it does, then perform the more costly check. - */ - return liesWithinInternalAngle(indexA, indexB, verts, indices) - && !hasIllegalEdgeIntersection(indexA, indexB, verts, indices); - } - - /** - * Returns TRUE if vertex B lies within the internal angle of the polygon - * at vertex A. - * - *

      Vertex B does not have to be within the polygon border. It just has - * be be within the area encompassed by the internal angle formed at - * vertex A.

      - * - *

      This operation is a fast way of determining whether a line segment - * can possibly form a valid polygon partition. If this test returns - * FALSE, then more expensive checks can be skipped.

      - * Visualizations - *

      Special case: - * FALSE is returned if vertex B lies directly on either of the rays - * cast from vertex A along its associated polygon edges. So the test - * on vertex B is exclusive of the polygon edges.

      - *

      The test is only performed on the xz-plane.

      - *

      Assumptions:

      - *
        - *
      • The vertices and indices arguments define a valid simple polygon - * with vertices wrapped clockwise.
      • - *
      • indexA != indexB
      • - *
      - *

      Behavior is undefined if the arguments to not meet these - * assumptions

      - * @param indexA An polygon index of a vertex that will form segment AB. - * @param indexB An polygon index of a vertex that will form segment AB. - * @param verts The vertices array in the form (x, y, z, id). The value - * stored at the id position is not relevant to this operation. - * @param indices A simplpe polygon wrapped clockwise. - * @return Returns TRUE if vertex B lies within the internal angle of - * the polygon at vertex A. - */ - private static boolean liesWithinInternalAngle(int indexA - , int indexB - , int[] verts - , ArrayList indices) - { - - // Get pointers to the main vertices being tested. - int pVertA = (indices.get(indexA) & DEFLAG) * 4; - int pVertB = (indices.get(indexB) & DEFLAG) * 4; - - // Get poitners to the vertices just before and just after vertA. - int pVertAMinus // The vertex just before A. - = (indices.get(getPreviousIndex(indexA, indices.size())) & DEFLAG) - * 4; - int pVertAPlus // The vert just after A. - = (indices.get(getNextIndex(indexA, indices.size())) & DEFLAG) * 4; - - /* - * First, find which of the two angles formed by the line segments - * AMinus->A->APlus is internal to (pointing towards) the polygon. - * Then test to see if B lies within the area formed by that angle. - */ - - - // TRUE if A is left of or on line AMinus->APlus - if (isLeftOrCollinear(verts[pVertA] - , verts[pVertA+2] - , verts[pVertAMinus] - , verts[pVertAMinus+2] - , verts[pVertAPlus] - , verts[pVertAPlus+2])) - // The angle internal to the polygon is <= 180 degrees - // (non-reflex angle). - // Test to see if B lies within this angle. - - return isLeft( - // TRUE if B is left of line A->AMinus - verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - ,verts[pVertAMinus] - , verts[pVertAMinus+2]) - // TRUE if B is right of line A->APlus - && isRight(verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertAPlus] - , verts[pVertAPlus+2]); - - /* - * The angle internal to the polygon is > 180 degrees (reflex angle). - * Test to see if B lies within the external (<= 180 degree) angle and - * flip the result. (If B lies within the external angle, it can't - * lie within the internal angle.) - */ - - - return !( - // TRUE if B is left of or on line A->APlus - isLeftOrCollinear(verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertAPlus] - , verts[pVertAPlus+2]) - // TRUE if B is right of or on line A->AMinus - && isRightOrCollinear(verts[pVertB] - , verts[pVertB+2] - , verts[pVertA] - , verts[pVertA+2] - , verts[pVertAMinus] - , verts[pVertAMinus+2])); - } - - /** - * Attempts to triangluate a polygon. - *

      Assumes the verts and indices arguments define a valid simple - * (concave or convex) polygon - * with vertices wrapped clockwise. Otherwise behavior is undefined.

      - * @param verts The vertices that make up the polygon in the format - * (x, y, z, id). The value stored at the id position is not relevant to - * this operation. - * @param inoutIndices A working array of indices that define the - * polygon to be triangluated. The content is manipulated during the - * operation and it will be left in an undefined state at the end of - * the operation. (I.e. Its content will no longer be of any use.) - * @param outTriangles The indices which define the triangles derived - * from the original polygon in the form - * (t1a, t1b, t1c, t2a, t2b, t2c, ..., tna, tnb, tnc). The original - * content of this argument is discarded prior to use. - * @return The number of triangles generated. Or, if triangluation - * failed, a negative number. - */ - private static int triangulate(int[] verts - , ArrayList inoutIndices - , ArrayList outTriangles) - { - - outTriangles.clear(); - - /* - * Terminology, concepts and such: - * - * This algorithm loops around the edges of a polygon looking for - * new internal edges to add that will partition the polygon into a - * new valid triangle internal to the starting polygon. During each - * iteration the shortest potential new edge is selected to form that - * iteration's new triangle. - * - * Triangles will only be formed if a single new edge will create - * a triangle. Two new edges will never be added during a single - * iteration. This means that the triangulated portions of the - * original polygon will only contain triangles and the only - * non-triangle polygon will exist in the untrianglulated portion - * of the original polygon. - * - * "Partition edge" refers to a potential new edge that will form a - * new valid triangle. - * - * "Center" vertex refers to the vertex in a potential new triangle - * which, if the triangle is formed, will be external to the - * remaining untriangulated portion of the polygon. Since is - * is now external to the polygon, it can't be used to form any - * new triangles. - * - * Some documentation refers to "iPlus2" even though the variable is - * not in scope or does not exist for that section of code. For - * documentation purposes, iPlus2 refers to the 2nd vertex after the - * primary vertex. - * E.g.: i, iPlus1, and iPlus2. - * - * Visualizations: http://www.critterai.org/nmgen_polygen#triangulation - */ - - // Loop through all vertices, flagging all indices that represent - // a center vertex of a valid new triangle. - for (int i = 0; i < inoutIndices.size(); i++) - { - final int iPlus1 = getNextIndex(i, inoutIndices.size()); - final int iPlus2 = getNextIndex(iPlus1, inoutIndices.size()); - if (isValidPartition(i, iPlus2, verts, inoutIndices)) - { - // A triangle formed by i, iPlus1, and iPlus2 will result - // in a valid internal triangle. - // Flag the center vertex (iPlus1) to indicate a valid triangle - // location. - inoutIndices.set(iPlus1, inoutIndices.get(iPlus1) | FLAG); - } - } - - /* - * Loop through the vertices creating triangles. When there is only a - * single triangle left, the operation is complete. - * - * When a valid triangle is formed, remove its center vertex. So for - * each loop, a single vertex will be removed. - * - * At the start of each iteration the indices list is in the following - * state: - * - Represents a simple polygon representing the un-triangulated - * portion of the original polygon. - * - All valid center vertices are flagged. - */ - while (inoutIndices.size() > 3) - { - - // Find the shortest new valid edge. - - // The minimum length found. - int minLengthSq = -1; - // The index for the start of the minimum length edge. - int iMinLengthSqVert = -1; - - // NOTE: i and iPlus1 are defined in two different scopes in - // this section. So be careful. - - // Loop through all indices in the remaining polygon. - for (int i = 0; i < inoutIndices.size(); i++) - { - final int iPlus1 = getNextIndex(i, inoutIndices.size()); - if ((inoutIndices.get(iPlus1) & FLAG) == FLAG) - { - // Indices i, iPlus1, and iPlus2 are known to form a - // valid triangle. - final int vert - = (inoutIndices.get(i) & DEFLAG) * 4; - final int vertPlus2 - = (inoutIndices.get(getNextIndex(iPlus1 - , inoutIndices.size())) & DEFLAG) * 4; - - // Determine the length of the partition edge. - // (i -> iPlus2) - int deltaX = verts[vertPlus2] - verts[vert]; - int deltaZ = verts[vertPlus2+2] - verts[vert+2]; - int lengthSq = deltaX * deltaX + deltaZ * deltaZ; - - if (minLengthSq < 0 || lengthSq < minLengthSq) - { - // This is either the first valid new edge, or an edge - // that is shorter than others previously found. - // Select it. - minLengthSq = lengthSq; - iMinLengthSqVert = i; - } - } - } - - if (iMinLengthSqVert == -1) - /* - * Could not find a new triangle. Triangulation failed. - * This happens if there are three or more vertices - * left, but none of them are flagged as being a - * potential center vertex. - */ - return -(outTriangles.size()/3); - - int i = iMinLengthSqVert; - int iPlus1 = getNextIndex(i, inoutIndices.size()); - - // Add the new triangle to the output. - outTriangles.add(inoutIndices.get(i) & DEFLAG); - outTriangles.add(inoutIndices.get(iPlus1) & DEFLAG); - outTriangles.add( - inoutIndices.get(getNextIndex(iPlus1 - , inoutIndices.size())) & DEFLAG); - - /* - * iPlus1, the "center" vert in the new triangle, is now external - * to the untriangulated portion of the polygon. Remove it from - * the indices list since it cannot be a member of any new - * triangles. - */ - inoutIndices.remove(iPlus1); - - if (iPlus1 == 0 || iPlus1 >= inoutIndices.size()) - { - /* - * The vertex removal has invalidated iPlus1 and/or i. So - * force a wrap, fixing the indices so they reference the - * correct indices again. This only occurs when the new - * triangle is formed across the wrap location of the polygon. - * Case 1: i = 14, iPlus1 = 15, iPlus2 = 0 - * Case 2: i = 15, iPlus1 = 0, iPlus2 = 1; - */ - i = inoutIndices.size() - 1; - iPlus1 = 0; - } - - /* - * At this point i and iPlus1 refer to the two indices from a - * successful triangluation that will be part of another new - * triangle. We now need to re-check these indices to see if they - * can now be the center index in a potential new partition. - */ - if (isValidPartition(getPreviousIndex(i , inoutIndices.size()) - , iPlus1 - , verts - , inoutIndices)) - inoutIndices.set(i, inoutIndices.get(i) | FLAG); - else - inoutIndices.set(i, inoutIndices.get(i) & DEFLAG); - - if (isValidPartition(i - , getNextIndex(iPlus1, inoutIndices.size()) - , verts - , inoutIndices)) - inoutIndices.set(iPlus1, inoutIndices.get(iPlus1) | FLAG); - else - inoutIndices.set(iPlus1, inoutIndices.get(iPlus1) & DEFLAG); - - } - - // Only three vertices remain. Add their triangle to the output list. - - outTriangles.add(inoutIndices.get(0) & DEFLAG); - outTriangles.add(inoutIndices.get(1) & DEFLAG); - outTriangles.add(inoutIndices.get(2) & DEFLAG); - - return outTriangles.size() / 3; - } - -} - diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Region.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Region.java deleted file mode 100644 index 88b36664..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/Region.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * A utility class which holds meta data related to building regions. - */ -final class Region -{ - /** - * The region ID. - */ - public int id = 0; - - /** - * The number of spans in this region. - */ - public int spanCount = 0; - - /** - * Used to indicate whether or not a re-mapping of the region ID is - * required. - */ - public boolean remap = false; - - /** - * Represents an ordered list of connections between this and other regions. - * All properly initialized regions will have at least one connection, - * even if that connection is only to the null region. - *

      The start point, end point, and direction of the ordering is - * arbitrary. If the current region connects at multiple non-adjacent - * points t another region, then the list will contain multiple references. - * One entry for each non-adjacent connection point.

      - *

      Example: 1, 5, 8, 1, 2 -> This region connects to region 1 at - * two points.

      - *

      The reason that multiple connection information is stored is that - * it can be used to indicate whether two regions, if combined, would - * result in a polygon with internal space, which is an invalid state.

      - */ - public final ArrayList connections = new ArrayList(); - - /** - * A list of non-null regions that overlap this region. - *

      An overlap is considered to have occurred - * if a span in this region is below a span belonging to another region.

      - *

      Note that if two spans in the same grid cell are in the same region, - * then the region will show as overlapping itself.

      - */ - public final ArrayList overlappingRegions = - new ArrayList(); - - /** - * Constructor - * @param id The initial ID of the region. - */ - public Region(int id) - { - this.id = id; - } - - /** - * Reinitializes (clears) all instance fields and sets the id to a - * new value. - * @param newRegionID The new region ID. - */ - public void resetWithID(int newRegionID) - { - id = newRegionID; - spanCount = 0; - connections.clear(); - overlappingRegions.clear(); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() - { - return "id: " + id + ", spans: " + spanCount - + ", connections: " + connections + ", overlaps: " - + overlappingRegions; - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SolidHeightfield.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SolidHeightfield.java deleted file mode 100644 index 1f77cf40..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SolidHeightfield.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import java.util.Hashtable; -import java.util.Iterator; -import java.util.NoSuchElementException; - -/** - * Contains data that represents the obstructed (solid) area of a bounded - * field of voxels. - *

      The data is stored within spans which represent a vertically contiguous - * group of solid voxels. A reference to the lowest span within a grid - * location is stored at that grid location's width/depth index. Height spans - * further up in the grid's column can be accessed via - * {@link HeightSpan#next()} on the base span. (I.e. By climbing up the links.) - *

      - * @see SolidHeightfieldBuilder - * @see The Voxelization Process - * @see Introduction to Height Fields - */ -public final class SolidHeightfield - extends BoundedField -{ - - /* - * Recast Reference: reHeightfield in Recast.h - */ - - /** - * Implements an iterator that will iterate through all spans within a - * height field. (Not just the base spans.) - *

      Behavior of the iterator is undefined if the interator's source - * is changed during iteration.

      - */ - public class SolidHeightFieldIterator - implements Iterator - { - - private int mNextWidth = 0; - private int mNextDepth = 0; - private HeightSpan mNext = null; - - private int mLastWidth = 0; - private int mLastDepth = 0; - - private SolidHeightFieldIterator() - { - moveToNext(); - } - - /** - * The depth index of the last span returned by {@link #next()} - * @return The depth index of the last span returned by {@link #next()} - */ - public int depthIndex() { return mLastDepth; } - - /** - * {@inheritDoc} - */ - @Override - public boolean hasNext() - { - return (mNext != null); - } - - /** - * {@inheritDoc} - */ - @Override - public HeightSpan next() - { - if (mNext == null) throw new NoSuchElementException(); - HeightSpan next = mNext; - mLastWidth = mNextWidth; - mLastDepth = mNextDepth; - moveToNext(); - return next; - } - - /** - * {@inheritDoc} - * This operation is not supported. - */ - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } - - /** - * Resets the iterator so that it can be re-used. - */ - public void reset() - { - mNextWidth = 0; - mNextDepth = 0; - mNext = null; - mLastWidth = 0; - mLastDepth = 0; - moveToNext(); - } - - /** - * The width index of the last span returned by {@link #next()} - * @return The width index of the last span returned by {@link #next()} - */ - public int widthIndex() { return mLastWidth; } - - /** - * Move to the next span in the data set. - */ - private void moveToNext() - { - if (mNext != null) - { - // There is a current span selected. - if (mNext.next() != null) - { - // The current span has a next. - // Move to it. - mNext = mNext.next(); - return; - } - else - // No more spans in the column of the current grid location. - // Move to next grid location. - mNextWidth++; - } - // Search through the grid until a new base span is found. - for (int depthIndex = mNextDepth - ; depthIndex < depth() - ; depthIndex++) - { - for (int widthIndex = mNextWidth - ; widthIndex < width() - ; widthIndex++) - { - HeightSpan span = - mSpans.get(gridIndex(widthIndex, depthIndex)); - if (span != null) - { - // A new base span was found. Select it. - mNext = span; - mNextWidth = widthIndex; - mNextDepth = depthIndex; - return; - } - } - mNextWidth = 0; - } - // If got here, then there are no more spans. - mNext = null; - mNextDepth = -1; - mNextWidth = -1; - } - } - - /** - * Contains the spans within the heightfield's grid. - *

      Key: Grid index obtained via {@link #gridIndex(int, int)}.
      - * Value: The lowest span at the grid location, or null if there are no - * spans at the grid location.

      - */ - private final Hashtable mSpans = - new Hashtable(); - - /** - * Constructor - *

      The bounds of the field will default to min(0, 0, 0) - * and max(1, 1, 1).

      - * @param cellSize The size of the cells. (The grid that forms the - * base of the field.) - * @param cellHeight The height increment of the field. - */ - public SolidHeightfield(float cellSize - , float cellHeight) - { - super(cellSize, cellHeight); - } - - /** - * Adds span data to the heightfield. New span data is either merged - * into existing spans or a new span is created. - *

      Only the following validations are peformed:

      - *
        - *
      • The bounds of the width and depth indices.
      • - *
      • The lower bounds of the height indices. (>=0)
      • - *
      • Height min <= max.
      • - *
      - *

      No check that the height maximum is within bounds is performed.

      - *

      Flags are set as follows:

      - *
        - *
      • If the maximum of the new data coincides with the maximum of an - * existing span, the old and new flags are merged.
      • - *
      • If the new data represents a new maximum (new span or new maximum - * for an existing span), the flags for the new data is used - * exclusively.
      • - *
      • Otherwise, the new data's flags are ignored.
      • - *
      - *

      Basically, only the flags at the top of a span are considered - * to matter.

      - * @param widthIndex The width index of the column that contains the - * new data. - * @param depthIndex The depth index of the column that contains the - * new data. - * @param heightIndexMin The solid span's minimum. The minimum of the - * obstructed space. (In zero-based height increments based on - * {@link #cellHeight()}.) - * @param heightIndexMax The solid span's maximum. The maximum of the - * obstructed space. (In zero-based height increments based on - * {@link #cellHeight()}.) - * @param flags The flags for the new data. - * @return TRUE if the data was successfully added. Otherwise FALSE. - * The only time this operation will fail is if the argument data is - * invalid in some way. - */ - public boolean addData(int widthIndex - , int depthIndex - , int heightIndexMin - , int heightIndexMax - , int flags) - { - if (widthIndex < 0 - || widthIndex >= width() - || depthIndex < 0 - || depthIndex >= depth()) - // Outside of grid bounds. - return false; - - if (heightIndexMin < 0 - || heightIndexMax < 0 - || heightIndexMin > heightIndexMax) - // Invalid height values. - return false; - - // Find the grid location of the span and get existing data for the - // location. - int gridIndex = gridIndex(widthIndex, depthIndex); - HeightSpan currentSpan = mSpans.get(gridIndex); - - if (currentSpan == null) - { - // This is the first span for this grid location. - // Generate a new span. - mSpans.put(gridIndex, new HeightSpan(heightIndexMin - , heightIndexMax - , flags)); - return true; - } - - // Span data already exists at this location. Search the spans in - // this column to see which one should contain this span. Or if a - // new span should be created. - HeightSpan previousSpan = null; - while (currentSpan != null) - { - /* - * Note: The way the spans are built, separate spans are always - * guaranteed to have a gap between them. The minimum gap will - * be the cell height increment. - */ - if (currentSpan.min() > heightIndexMax + 1) - { - /* - * The new span is below the current span and NOT adjacent. - * Due to the structure of the data, the new span is - * guaranteed to fit below the current span. - * - * Create a new span. - */ - HeightSpan newSpan = new HeightSpan(heightIndexMin - , heightIndexMax - , flags); - // Insert this span below the current span. - newSpan.setNext(currentSpan); - if (previousSpan == null) - // The new span is the new first span in this column. - // Insert it at the base of this column. - mSpans.put(gridIndex, newSpan); - else - // The new span is between two spans. - // Link the previous span to the new span. - previousSpan.setNext(newSpan); - return true; - } - else if (currentSpan.max() < heightIndexMin - 1) - { - // Current span is below the new span and NOT adjacent. - if (currentSpan.next() == null) - { - // The new span is the final span. - // Insert it above the current span. - currentSpan.setNext(new HeightSpan(heightIndexMin - , heightIndexMax - , flags)); - return true; - } - // Continue searching up the span's in this column. - previousSpan = currentSpan; - currentSpan = currentSpan.next(); - } - else - { - /* - * There is either overlap or adjacency between the current - * span and the new span. - * Need to perform a merge of some type. - * Will always return after the merge is complete. - * Get easy stuff out of the way first. - */ - if (heightIndexMin < currentSpan.min()) - // This span will result in a new minimum for the current - // span. Adjust the current span's minimum. - currentSpan.setMin(heightIndexMin); - if (heightIndexMax == currentSpan.max()) - { - // The new span ends at same height as current span. - // Merge flags. - currentSpan.setFlags((byte)(currentSpan.flags() | flags)); - return true; - } - if (currentSpan.max() > heightIndexMax) - // The top of the current span is higher than the new span. - // So discard the new span's flag. - return true; - // The new spans's maximum height is higher than the current - // span's maximum height. - // Need to search up the spans to find where the merge ends. - HeightSpan nextSpan = currentSpan.next(); - while (true) - { - if (nextSpan == null || nextSpan.min() > heightIndexMax + 1) - { - /* - * There are no spans above the current span, or the - * height increase caused by this span will not touch - * the next span. Can just expand the current span - * upward. - */ - currentSpan.setMax(heightIndexMax); - // New span is new "top", so its flags replace current - // span's flags. - currentSpan.setFlags(flags); - if (nextSpan == null) - // The current span is at the top of the column. - // Get rid of any links it may have had. - currentSpan.setNext(null); - else - // Take care of re-pointing. (Some spans may have - // been encompassed.) - currentSpan.setNext(nextSpan); - // Finished. - return true; - } - // The new height of the current span will touch the next - // span in some manner. Merging is needed. - if (nextSpan.min() == heightIndexMax + 1 - || heightIndexMax <= nextSpan.max()) - { - // No gap between current and next spans, but no - // overlap with next span. (Spans abut each other.) - // Encompass the next span. - currentSpan.setMax(nextSpan.max()); - // Set the current span to point the the encompassed - // span's next span. - currentSpan.setNext(nextSpan.next()); - // Take the flags of the next span since we know the - // next span's max is higher than the current span. - currentSpan.setFlags(nextSpan.flags()); - if (heightIndexMax == currentSpan.max()) - { - // New span ends at same height as merged span. - // Merge flags. - currentSpan.setFlags(currentSpan.flags() | flags); - return true; - } - return true; - } - // The current span overlaps with the next span. - // Need to continue up the column to see if the next span - // will be fully engulfed. - nextSpan = nextSpan.next(); - } - } - } - - // Will only ever get here if there is a code logic error. - return false; - - } - - /** - * Provides an iterator that iterates all spans in the field. - *

      Unlike {@link #getData(int, int)}, this iterator will iterate - * through all spans, not just the base spans. So their is no need to - * use {@link HeightSpan#next()} to climb the span structure.

      - */ - public SolidHeightFieldIterator dataIterator() - { - return this.new SolidHeightFieldIterator(); - } - - /** - * Gets the lowest span at the grid location, or null if there are no - * spans at the location. - *

      The data will be the lowest span at the grid location.

      - * @return The lowest span at the grid location. - */ - public HeightSpan getData(int widthIndex, int depthIndex) - { - return mSpans.get(gridIndex(widthIndex, depthIndex)); - } - - /** - * Indicates whether or not the field contains any spans. If FALSE is - * returned, then the field does not contain any obstructed space. - * @return TRUE if the field contains spans. Otherwise FALSE. - */ - public boolean hasSpans() { return (mSpans.size() > 0); } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SolidHeightfieldBuilder.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SolidHeightfieldBuilder.java deleted file mode 100644 index c5fdb16f..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SolidHeightfieldBuilder.java +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -import org.critterai.nmgen.SolidHeightfield.SolidHeightFieldIterator; - -/** - * A class used to build solid heightfields from source geometry using a - * given configuration. The solid heightfield represents the space obstructed - * by the source geometry. - *

      Each triangle in the source geometry is voxelized using conservative - * voxelization and added to the field. Conservative voxelization is an - * algorithm that ensures that polygon surfaces are completely encompassed - * by the the generated voxels.

      - *

      At the end of the process, spans with the {@link SpanFlags#WALKABLE} - * flag have survived the following tests:

      - *
        - *
      • The top of the span is at least a minimum distance from the bottom of - * the span above it. (The tallest agent can "stand" on the span without - * colliding with an obstruction above.)
      • - *
      • The top voxel of the span represents geometry with a slope below a - * maximum allowed value. (The slope is low enough to be traversable by - * agents.)
      • - *
      • If ledge culling is enabled, the top of the span does not represent - * a ledge. (Agents can legally "step down" from the span to any of its - * neighbors.)
      • - *
      - * @see The Voxelization Process - * @see Introduction to Heightfields - * @see Conservative Voxelization (PDF) - */ -public final class SolidHeightfieldBuilder -{ - - /* - * Design notes: - * - * Recast reference: - * rcCreateHeightfield in Recast.cpp - * rcMarkWalkableTriangles in Recast.cpp - * rcRasterizeTriangles in RecastRasterization.cpp - * rcFilterLedgeSpans in RecastFilter.cpp - * rcFilterWalkableLowHeightSpans in RecastFilter.cpp - * - * Not adding configuration getters until they are needed. - * Never add setters. Configuration should remain immutable to keep - * the class thread friendly. - * - * TODO: EVAL: It may be better to implement post-processing as external - * algorithms similar to what is done with the open heightfield and - * contour classes. - * - */ - - // Configuration settings. - - private final boolean mClipLedges; - private final int mMinTraversableHeight; - private final int mMaxTraversableStep; - - /** - * A derived value which represent the minimum y-normal permitted for - * a polygon to be considered traversable. - *

      See the constructor for details.

      - */ - private final float mMinNormalY; - - /** - * The cell size to use for all new fields. - *

      IMPORTANT: Only use this value for heightfield object initialization. - * After that, use the value in the heightfield object. (Since the - * heightfield instance may place limitations on the value.)

      - */ - private final float mCellSize; - - /** - * The cell height to use for all new fields. - *

      IMPORTANT: Only use this value for heightfield object initialization. - * After that, use the value in the heightfield object. (Since the height - * field object may place limitations on the value.)

      - */ - private final float mCellHeight; - - /** - * Constructor - * @param cellSize The size of the cells. (The grid that forms the base - * of the field.) - *

      This value represents the x and z-axis sampling resolution to use - * when generating voxels.

      - * - * @param cellHeight The height increment of the field. - *

      This value represents the y-axis sampling resolution to use when - * generating voxels.

      - * - * @param minTraversableHeight Represents the minimum floor to ceiling - * height that will still allow a floor area to be considered traversable. - *

      Permits detection of overhangs in the geometry which make the - * geometry below become unwalkable.

      - *

      Constraints: > 0

      - * - * @param maxTraversableStep Represents the maximum ledge height that - * is considered to still be traversable. - *

      Prevents minor deviations in height from improperly showing as - * obstructions. Permits detection of stair-like structures, curbs, etc.

      - *

      Constraints: >= 0

      - * - * @param maxTraversableSlope The maximum slope that is considered - * traversable. (Degrees) - *

      Spans that are at or above this slope have the - * {@link SpanFlags#WALKABLE} flag removed.

      - *

      Constraints: 0 <= value <= 85

      - * - * @param clipLedges Indicates whether ledges should be marked as - * unwalkable. I.e. The {@link SpanFlags#WALKABLE} flag will be removed. - *

      A ledge is a normally traversable span that has one or more - * accessible neighbors with a an un-steppable drop from span top to - * span top.

      - *

      E.g. If an agent using the navmesh were to travel down from the - * ledge span to its neighbor span, it would result in the maximum - * traversable step distance being violated. The agent cannot legally - * "step down" from a ledge to its neighbor.

      - */ - public SolidHeightfieldBuilder(float cellSize - , float cellHeight - , int minTraversableHeight - , int maxTraversableStep - , float maxTraversableSlope - , boolean clipLedges) - { - - mMinTraversableHeight = Math.max(1, minTraversableHeight); - mMaxTraversableStep = Math.max(0, maxTraversableStep); - maxTraversableSlope = Math.min(85, Math.max(0, maxTraversableSlope)); - mClipLedges = clipLedges; - mCellSize = cellSize; - mCellHeight = cellHeight; - - /* - * Derive the minimum y-normal. - * - * Base Reference: http://mathworld.wolfram.com/DihedralAngle.html - * - * By ensuring n1 and n2 are both normalized before the calculation, the - * denominator in the reference equations evaluate to 1 and - * can be discarded. So the reference equation is simplified to... - * - * cos theta = n1 dot n2 - * - * Using: - * - * n1 = (0, 1, 0) (Represents a flat surface on the (x,z) plane.) - * n2 = (x, y, z) Normalized. (A surface on an arbitrary plane.) - * - * Simplify and solve for y: - * - * cos theta = 0x + 1y + 0z - * y = cos theta - * - * We know theta. It is the value of maxTraversableSlope after - * conversion to radians. So we know what y-normal is at the walk - * slope angle. If a polygon's y-normal is LESS THAN our calculated - * y-normal, then we know we have exceeded the walk angle. - */ - mMinNormalY = (float)Math.cos(Math.abs( - maxTraversableSlope)/180 * Math.PI); - } - - /** - * Generates a solid heightfield from the provided source geometry. The - * solid heightfield will represent the space obstructed by the source - * geometry. - *

      The {@link SpanFlags#WALKABLE} will be applied to spans whose top - * surface is considered traversable. See the class description for - * details.

      - * @param vertices Source geometry vertices in the form (x, y, z). - * @param indices Source geometry indices in the form (VertA, VertB, VertC). - * Wrapped: Clockwise. - * @return The generated solid heightfield, or null if the generation fails. - */ - public SolidHeightfield build(float[] vertices, int[] indices) - { - // Perform basic checks. - if (vertices == null - || indices == null - || vertices.length % 3 != 0 - || indices.length % 3 != 0) - return null; - - // Initialize heightfield. - final SolidHeightfield result = - new SolidHeightfield(mCellSize, mCellHeight); - - // Pre-calculate values to save on the cost of division later. - final float inverseCellSize = 1 / result.cellSize(); - final float inverseCellHeight = 1 / result.cellHeight(); - - // Detect and set the bounds of the source geometry. - // Default to the first vertex. - float xmin = vertices[0]; - float ymin = vertices[1]; - float zmin = vertices[2]; - float xmax = vertices[0]; - float ymax = vertices[1]; - float zmax = vertices[2]; - // Loop through all vertices, expanding the bounds - // as appropriate. - for (int i = 3; i < vertices.length; i += 3) - { - xmax = Math.max(vertices[i], xmax); - ymax = Math.max(vertices[i + 1], ymax); - zmax = Math.max(vertices[i + 2], zmax); - - xmin = Math.min(vertices[i], xmin); - ymin = Math.min(vertices[i + 1], ymin); - zmin = Math.min(vertices[i + 2], zmin); - } - // Set the bounds. - result.setBounds(xmin, ymin, zmin, xmax, ymax, zmax); - - // Detect which polygons in the source mesh have a slope - // that low enough to be considered traversable. (Agent can walk up - // or down the slope.) - final int[] polyFlags = markInputMeshWalkableFlags(vertices, indices); - - // For each polygon in the source mesh: Voxelize it and add the - // resulting spans to the solid field. - final int polyCount = indices.length / 3; - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - voxelizeTriangle(iPoly - , vertices - , indices - , polyFlags[iPoly] - , inverseCellSize - , inverseCellHeight - , result); - } - - // Remove the walkable flag from any span that has another span too - // close above it. - markLowHeightSpans(result); - - if (mClipLedges) - // Remove the walkable flag from any span that is determined to - // be a ledge. - markLedgeSpans(result); - - return result; - - } - - /** - * Checks the slope of each polygon against the maximum allowed. Any - * polygon whose slope is below the maximum permitted gets the - * {@link SpanFlags#WALKABLE} flag. - * @param vertices The source geometry vertices in the form (x, y, z). - * @param indices The source geometry indices in the form - * (vertA, vertB, vertC), clockwise wrapped. - * @return An array of flags in the form - * (polyFlag0, polyFlag1, ..., polyFlagN), stride = 1. - */ - private int[] markInputMeshWalkableFlags(float[] vertices, int[] indices) - { - - // See mMinNormalY in constructor for more information on how this - // works. - - final int[] flags = new int[indices.length / 3]; - - // Working variables. Content changes for every loop - // and has no meaning outside the loop. - float[] diffAB = new float[3]; - float[] diffAC = new float[3]; - float[] crossDiff = new float[3]; - - // Loop through all polygons. - int polyCount = indices.length / 3; - for (int iPoly = 0; iPoly < polyCount; iPoly++) - { - // Get pointers to each polygon vertex. - int pVertA = indices[iPoly*3]*3; - int pVertB = indices[iPoly*3+1]*3; - int pVertC = indices[iPoly*3+2]*3; - - // Determine the y-normal for the polygon. - float normalY = getNormalY( - cross(subtract(pVertB, pVertA, vertices, diffAB) - , subtract(pVertC, pVertA, vertices, diffAC) - , crossDiff)); - - if (normalY > mMinNormalY) - // The slope of this polygon is acceptable. Mark it as - // walkable. - flags[iPoly] = SpanFlags.WALKABLE; - } - - return flags; - } - - /** - * Removes the traversable flag for any spans that represent a ledge. - * A ledge occurs when stepping from the top of one span down to any of its - * neighbor spans exceeds the allowed walk climb distance. (i.e. Can't - * legally "step down" to a neighbor span.) - * @param field The field to operation on. - */ - private void markLedgeSpans(SolidHeightfield field) - { - - /* - * Note: While this is a solid field representing obstructions, much - * of this algorithm deals with the space between obstructions. - * (The gaps.) So you will need to twist your thinking to gaps rather - * than obstructions. - * - * For visualization, see the @see in the class' javadoc. - */ - - // Loop through all spans. - SolidHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - HeightSpan span = iter.next(); - - if ((span.flags() & SpanFlags.WALKABLE) == 0) - // Span is already known to be un-waklable. - // Skip it. - continue; - - final int widthIndex = iter.widthIndex(); - final int depthIndex = iter.depthIndex(); - - // These values represent the gap (floor to ceiling) above the - // current span. - final int currFloor = span.max(); - final int currCeiling = (span.next() != null) ? - span.next().min() : Integer.MAX_VALUE; - - /* - * Represents the minimum distance from the current span's floor - * to a neighbor span's floor. A positive value indicates a step - * up. A negative distance represents a step down. If this - * distance is too far down, then the current span is a ledge - * and isn't traversable. - * - * This algorithm only cares about drops. - * Default to a maximum step up. - */ - int minDistanceToNeighbor = Integer.MAX_VALUE; - - /* - * The lowest possible floor is at -mMaxTraversableStep. No span - * can exist below the zero height index. So stepping from a span - * whose floor is at zero to "empty space" will result in a drop - * to -mMaxTraversableStep. - */ - - /* - * Loop through all neighbor grid cells. - */ - for (int dir = 0; dir < 4; dir++) - { - final int nWidthIndex = widthIndex - + BoundedField.getDirOffsetWidth(dir); - final int nDepthIndex = depthIndex - + BoundedField.getDirOffsetDepth(dir); - - // Get the lowest span in this neighbor column. - HeightSpan nSpan = field.getData(nWidthIndex, nDepthIndex); - - if (nSpan == null) - { - // No neighbor on this side. Treat as the maximum drop. - // (Which is always considered a ledge.) - // TODO: EVAL: Should this be a break rather than a - // continue? (Detected too close to release to risk code - // changes.) - minDistanceToNeighbor = Math.min(minDistanceToNeighbor - , -mMaxTraversableStep - currFloor); - continue; - } - - /* - * First need to take into account the area below the lowest - * span in this neighbor column. - * - * In this special case, the floor of this gap is the lowest - * possible value. The ceiling of this gap is the bottom of - * neighbor span. - */ - // Default to an excessive drop. - int nFloor = -mMaxTraversableStep; - int nCeiling = nSpan.min(); // The bottom of this first span. - - /* - * This check filters out the following: - * - * The distance from the current span's floor this neighbor's - * ceiling is not large enough to permit transit in that - * direction? (Agent will "bump its head" if it moves in this - * direction?) - * - * The neighbor gap is entirely below the floor of the - * current span. - * - * In such cases travel is not allowed to the neghbor gap, so - * it isn't taken into account. - */ - if (Math.min(currCeiling, nCeiling) - currFloor - > mMinTraversableHeight) - // Travel is permitted in this direction. So take this - // neighbor gap into account. - minDistanceToNeighbor = - Math.min(minDistanceToNeighbor, (nFloor - currFloor)); - - /* - * Now process the rest of the gaps in this neighbor column - * normally. E.g. The top of the span is the floor. The - * bottom of the next span is the ceiling. - */ - - for (nSpan = field.getData(nWidthIndex, nDepthIndex) - ; nSpan != null - ; nSpan = nSpan.next()) - { - nFloor = nSpan.max(); - nCeiling = (nSpan.next() != null) ? - nSpan.next().min() : Integer.MAX_VALUE; - /* - * This next check filters out the following: - * - * The distance from the current span's floor this - * neighbor's ceiling is not large enough to permit - * transit in that direction? (Agent will "bump its head" - * if it moves in this direction?) - * - * The neighbor gap is entirely below the floor of the - * current span. - * - * The neighbor gap is entirely above the ceiling of the - * current gap. - * - * In such cases travel is not allowed to the neghbor gap, - * so it isn't taken into account. - */ - if (Math.min(currCeiling, nCeiling) - - Math.max(currFloor, nFloor) - > mMinTraversableHeight) - // Potential travel to this neighbor span. - minDistanceToNeighbor = - Math.min(minDistanceToNeighbor - , (nFloor - currFloor)); - } - - } - - // Remember: A negative distance indicates a drop. - if (minDistanceToNeighbor < -mMaxTraversableStep) - // Can only drop by mMaxTraversableStep, but a neighbor has a - // drop that exceeds this allowed drop. Remove the walkable - // flag. - span.setFlags(span.flags() & ~SpanFlags.WALKABLE); - } - } - - /** - * Remove the traversable flag from spans that have another span too - * close above them. - * @param field The heightfield to operate on. - */ - private void markLowHeightSpans(SolidHeightfield field) - { - // TODO: EVAL: Consider merging this operation with markLedgeSpans. - - // For visualization, see the @see in the class' javadoc. - - // Iterate through all spans in the field. - SolidHeightFieldIterator iter = field.dataIterator(); - while (iter.hasNext()) - { - HeightSpan span = iter.next(); - - if ((span.flags() & SpanFlags.WALKABLE) == 0) - // Span is already known to be un-waklable. - // Skip it. - continue; - - // Find the gap between the current span and the next higher span. - // This represents the open space (floor to ceiling) above the - // current span. - int spanFloor = span.max(); - int spanCeiling = (span.next() != null) ? - span.next().min() : Integer.MAX_VALUE; - - if (spanCeiling - spanFloor <= mMinTraversableHeight) - // Can't stand on this span. Ceiling is too low. - // Remove its walkable flag. - span.setFlags(span.flags() & ~SpanFlags.WALKABLE); - } - } - - /** - * Clamps the value to the specified range. - * @param value The value to clamp. - * @param minimum The minimum allowed value. (Inclusive.) - * @param maximum The maximum allowed value. (Inclusive.) - * @return If minimum <= value <= maximum, will return value. - * If value < minimum, will return minimum. - * If value > maximum, will return maximum. - */ - private static int clamp(int value, int minimum, int maximum) - { - return (value < minimum - ? minimum : (value > maximum ? maximum : value)); - } - - private static int clipPoly(float[] in - , int inputVertCount - , float[] out - , float pnx - , float pnz - , float pd) - { - - // TODO: DOC: Figure out what is going on here. Not familiar with - // algorithm. pnx and pnz are normals. - - float d[] = new float[inputVertCount]; - for (int vertIndex = 0; vertIndex < inputVertCount; ++vertIndex) - d[vertIndex] = (pnx * in[vertIndex * 3]) - + (pnz * in[vertIndex * 3 + 2]) + pd; - - int m = 0; - for (int current = 0, previous = d.length - 1 - ; current < d.length - ; previous=current, ++current) - { - boolean ina = d[previous] >= 0; - boolean inb = d[current] >= 0; - if (ina != inb) - { - float s = d[previous] / (d[previous] - d[current]); - out[m*3+0] = - in[previous*3+0] + (in[current*3+0] - in[previous*3+0])*s; - out[m*3+1] = - in[previous*3+1] + (in[current*3+1] - in[previous*3+1])*s; - out[m*3+2] = - in[previous*3+2] + (in[current*3+2] - in[previous*3+2])*s; - m++; - } - if (inb) - { - out[m*3+0] = in[current*3+0]; - out[m*3+1] = in[current*3+1]; - out[m*3+2] = in[current*3+2]; - m++; - } - } - return m; - } - - /** - * Performs a cross product on the vectors u and v. (u x v) - * @param u The first vector in the form (x, y, z) - * @param v The second vector in the form (x, y, z) - * @param out The array to be loaded with the result. - * @return A reference to the out array loaded with the cross product. - */ - private static float[] cross(float[] u, float[] v, float[] out) - { - // Reference: http://mathworld.wolfram.com/CrossProduct.html - // Reference: http://en.wikipedia.org/wiki/Cross_product - // #Computing_the_cross_product - out[0] = u[1] * v[2] - u[2] * v[1]; - out[1] = -u[0] * v[2] + u[2] * v[0]; - out[2] = u[0] * v[1] - u[1] * v[0]; - return out; - } - - /** - * Normalizes the provided vector and returns the y-value. - * @param v The vector to normalize in the form: (x, y, z) - * @return The y-value of the normalized vector. - */ - private static float getNormalY(float[] v) - { - // This is just the standard normalization algorithm with - // unneeded x and z calculations removed. - - final float epsilon = 0.0001f; - - float length = - (float)Math.sqrt((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2])); - if (length <= epsilon) - length = 1; - - float y = v[1] / length; - - if (Math.abs(y) < epsilon) - y = 0; - - return y; - } - - /** - * Performs vector subtraction on the vertices. (VertexA - VertexB) - * @param pVertA The pointer to a valid vertex in the source vertices array. - * @param pVertB The pointer to a valid vertex in the source vertices array. - * @param out An array of size 3. The array is loaded with the result of - * the subtraction and returned. - * @return A reference to the out array loaded with the result of the - * subtraction. - */ - private static float[] subtract(int pVertA - , int pVertB - , float[] vertices - , float[] out) - { - out[0] = vertices[pVertA] - vertices[pVertB]; - out[1] = vertices[pVertA+1] - vertices[pVertB+1]; - out[2] = vertices[pVertA+2] - vertices[pVertB+2]; - return out; - } - - /** - * Voxelizes the chosen polygon and adds the resulting spans to the - * heightfield. - *

      The inverse arguments are included for optimization. (No need to - * recalculate the values for every call.)

      - *

      The heightfield will make the final decision on whether to apply - * the flags provided in the arguments. See the - * {@link SolidHeightfield#addData(int, int, int, int, int) heightfield - * add operation} for details

      - * @param polyIndex The polygon to voxelize. - * @param vertices The vertices of the source geometry in the form - * (x, y, z). - * @param indices The indices of the source geometry in the form - * (vertA, vertB, vertC), wrapped clockwise. - * @param polyFlags The flags to apply to all new spans within the - * heightfield. - * @param inverseCellSize Inverse cell size. (1/cellSize) - * @param inverseCellHeight Inverse cell height. (1/cellheight) - * @param inoutField The heightfield to add new spans to. - */ - private static void voxelizeTriangle(int polyIndex - , float[] vertices - , int[] indices - , int polyFlags - , float inverseCellSize - , float inverseCellHeight - , SolidHeightfield inoutField) - { - - /* - * Design notes: - * - * There is significant processing going on here that is not - * required since this is a private operation and the input is tightly - * controlled. For example: We know that the heightfield is sized to - * hold the source geometry, so bounds checks aren't really needed. - * - * But, with the possible exception of object creation, the extra - * cost is not big. So I'm leaving the algorithm as it is just in - * case it is converted to a public operation at a later date. - */ - - // Pointer to the polygon. - final int pPoly = polyIndex*3; - - // Polygon vertices. - final float[] triVerts = { - vertices[indices[pPoly]*3] // VertA - , vertices[indices[pPoly]*3+1] - , vertices[indices[pPoly]*3+2] - , vertices[indices[pPoly+1]*3] // VertB - , vertices[indices[pPoly+1]*3+1] - , vertices[indices[pPoly+1]*3+2] - , vertices[indices[pPoly+2]*3] // VertC - , vertices[indices[pPoly+2]*3+1] - , vertices[indices[pPoly+2]*3+2] - }; - - // Determine the bounding box of the polygon. - - // Initialize bounds to the first triangle vertex. - final float[] triBoundsMin = { triVerts[0], triVerts[1], triVerts[2] }; - final float[] triBoundsMax = { triVerts[0], triVerts[1], triVerts[2] }; - - // Loop through all vertices to determine the actual bounding box. - for (int vertPointer = 3; vertPointer < 9; vertPointer += 3) - { - triBoundsMin[0] = Math.min(triBoundsMin[0], - triVerts[vertPointer]); - triBoundsMin[1] = Math.min(triBoundsMin[1], - triVerts[vertPointer + 1]); - triBoundsMin[2] = Math.min(triBoundsMin[2], - triVerts[vertPointer + 2]); - triBoundsMax[0] = Math.max(triBoundsMax[0], - triVerts[vertPointer]); - triBoundsMax[1] = Math.max(triBoundsMax[1], - triVerts[vertPointer + 1]); - triBoundsMax[2] = Math.max(triBoundsMax[2], - triVerts[vertPointer + 2]); - } - - // If the triangle does not overlap the heightfield, then skip it. - if (!inoutField.overlaps(triBoundsMin, triBoundsMax)) - return; - - /* - * Determine footprint of triangle bounding box on the heightfield's - * grid. - * - * Notes: - * - * The heightfield is an integer based grid with its origin at the - * heightfield's minimum bounds. I.e. Grid coordinate - * (0, 0) => (heightField.minbounds.x, heightField.minbounds.z) - * - * The heightfield width/depth values map to the (x, z) plane of the - * triangle, not the (x, y) plane. - */ - - // First, convert the triangle bounds to field grid coordinates. - int triWidthMin = (int)((triBoundsMin[0] - inoutField.boundsMin()[0]) - * inverseCellSize); - int triDepthMin = (int)((triBoundsMin[2] - inoutField.boundsMin()[2]) - * inverseCellSize); - int triWidthMax = (int)((triBoundsMax[0] - inoutField.boundsMin()[0]) - * inverseCellSize); - int triDepthMax = (int)((triBoundsMax[2] - inoutField.boundsMin()[2]) - * inverseCellSize); - - // Snap the grid coordinates to the grid bounds. - triWidthMin = clamp(triWidthMin, 0, inoutField.width() - 1); - triDepthMin = clamp(triDepthMin, 0, inoutField.depth() - 1); - triWidthMax = clamp(triWidthMax, 0, inoutField.width() - 1); - triDepthMax = clamp(triDepthMax, 0, inoutField.depth() - 1); - - /* - * "in" will contain the final data. - * "out" and "inrow" are used for intermediate data. - * "in" is initially seeded with the triangle vertices. - * The arrays are sized to be 3 * 7. This allows for the storage of - * the maximum vertex count for a triangle clipped into a square (6) - * with an extra triple. - * (Don't know the purpose of the extra triple.) - */ - final float in[] = new float[21]; - final float out[] = new float[21]; - final float inrow[] = new float[21]; - - // The height of the heightfield. - final float fieldHeight = - inoutField.boundsMax()[1] - inoutField.boundsMin()[1]; - - /* - * Loop through all grid locations overlapped by the polygon. - * (xz-plane only). - * - * Clip the triangle into all grid cells it touches. - * - * Any early exit from either of the loops means that the triangle - * does not overlap the grid column, or is outside the height - * bounds of the field. - * - * All detailed clip data is discarded in the end. The only information - * preserved is the height information. - * - * Dev Note: I don't understand the mathematical algorithm used here. - * So I've marked it as magic. But by tracing the process on paper - * I've determined that the algorithm is finding all intersection - * points between the grid column and the triangle face. - * - * For visualization, see the @see in the class' javadoc. - */ - for (int depthIndex = triDepthMin - ; depthIndex <= triDepthMax - ; ++depthIndex) - { - - // Seed with the triangle vertices. - System.arraycopy(triVerts, 0, in, 0, triVerts.length); - - // Do some magic. - // Count of cell intersection vertices found. - int intermediateVertCount = 3; - final float rowWorldZ = inoutField.boundsMin()[2] - + (depthIndex * inoutField.cellSize()); - intermediateVertCount = clipPoly(in - , intermediateVertCount - , out - , 0 - , 1 - , -rowWorldZ); - if (intermediateVertCount < 3) - continue; - intermediateVertCount = clipPoly(out, intermediateVertCount - , inrow - , 0 - , -1 - , rowWorldZ + inoutField.cellSize()); - if (intermediateVertCount < 3) - continue; - - for (int widthIndex = triWidthMin - ; widthIndex <= triWidthMax - ; ++widthIndex) - { - - // Do some more magic. - int vertCount = intermediateVertCount; - final float colWorldX = inoutField.boundsMin()[0] - + (widthIndex * inoutField.cellSize()); - vertCount = clipPoly(inrow, vertCount, out, 1, 0, -colWorldX); - if (vertCount < 3) - continue; - vertCount = clipPoly(out - , vertCount - , in - , -1 - , 0 - , colWorldX + inoutField.cellSize()); - if (vertCount < 3) - continue; - - // If got here, then "in" contains the definition for a poly - // representing the portion - // of the input triangle that overlaps the grid location. - - // Find the height (y-axis) range for this grid location. - float heightMin = in[1]; - float heightMax = in[1]; - for (int i = 1; i < vertCount; ++i) - { - heightMin = Math.min(heightMin, in[i*3+1]); - heightMax = Math.max(heightMax, in[i*3+1]); - } - // Convert to height above the "floor" of the heightfield. - heightMin -= inoutField.boundsMin()[1]; - heightMax -= inoutField.boundsMin()[1]; - if (heightMax < 0.0f || heightMin > fieldHeight) - // The height of the potential span is entirely outside - // the bounds of the heightfield. - continue; - // Clamp to the heightfield bounding box. - if (heightMin < 0.0f) - heightMin = inoutField.boundsMin()[1]; - if (heightMax > fieldHeight) - heightMax = inoutField.boundsMax()[1]; - - // Convert the min/max to height grid index. - int heightIndexMin = clamp( - (int)Math.floor(heightMin * inverseCellHeight) - , 0 - , Short.MAX_VALUE); - int heightIndexMax = clamp( - (int)Math.ceil(heightMax * inverseCellHeight) - , 0 - , Short.MAX_VALUE); - - // Add the span to the heightfield. - inoutField.addData(widthIndex - , depthIndex - , heightIndexMin - , heightIndexMax - , polyFlags); - } - } - - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SpanFlags.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SpanFlags.java deleted file mode 100644 index f54997d6..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/SpanFlags.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Defines the standard flags used for height field spans. - */ -public final class SpanFlags -{ - /** - * The span's upper surface (top or maximum) is considered to be - * traversable. Spans without this flag are considered to be obstructions - * that cannot be walked upon. - */ - public static final byte WALKABLE = 1; - - private SpanFlags() { } -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/TriangleMesh.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/TriangleMesh.java deleted file mode 100644 index ac09788b..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/TriangleMesh.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.nmgen; - -/** - * Represents the a triangle mesh created by the navigation mesh generation - * process. - *

      WARNING: The core data within this class is unprotected.

      - *

      - * - * - *

      - */ -public final class TriangleMesh -{ - - /* - * Recast Reference: rcPolyMeshDetail in Recast.h - */ - - /** - * Vertices for the triangle mesh in the forma (x, y, z) - */ - public float[] vertices = null; - - /** - * Triangles in the mesh in the forma (vertAIndex, vertBIndex, vertCIndex) - * where the vertices are wrapped clockwise. - */ - public int[] indices = null; - - /** - * The region to which each triangle belongs. - *

      Index corresponds to the indices array index.

      - */ - public int[] triangleRegions = null; - - /** - * Gets the region ID associated with a triangle - * @param index The index of the triangle. - * @return The region ID of the triangle. Or -1 if the index is invalid. - */ - public int getTriangleRegion(int index) - { - if (index < 0 || index >= triangleRegions.length) - return -1; - return triangleRegions[index]; - } - - /** - * Gets the vertices for a particular triangle in the form - * (vertAx, vertAy, vertAz, vertBx, vertBy, vertBz, vertCx, vertCy, vertCz) - * @param index The index of the triangle to retrieve. - * @return The vertices in the specified triangle. Or null if the index is - * invalid. - */ - public float[] getTriangleVerts(int index) - { - - int pTriangle = index*3; - if (index < 0 || pTriangle >= indices.length) - return null; - - float[] result = new float[9]; - - for (int i = 0; i < 3; i++) - { - int pVert = indices[pTriangle+i]*3; - result[i*3] = vertices[pVert]; - result[i*3+1] = vertices[pVert+1]; - result[i*3+2] = vertices[pVert+2]; - } - - return result; - } - - /** - * The number of triangles in the mesh. - * @return The number of triangles in the mesh. - */ - public int triangleCount() - { - return (triangleRegions == null ? 0 : triangleRegions.length); - } - - /** - * The number of vertices in the mesh. - * @return The number of vertices in the mesh. - */ - public int vertCount() - { - return (vertices == null ? 0 : vertices.length / 3); - } - -} diff --git a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/package-info.java b/critterai/legacy/nmgen-study/src/org/critterai/nmgen/package-info.java deleted file mode 100644 index 9f61d0e3..00000000 --- a/critterai/legacy/nmgen-study/src/org/critterai/nmgen/package-info.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** -Provides data structures and algorithms useful for generating navigation meshes -which represent the traversable surface area of an arbitrary source triangle -mesh. - */ -package org.critterai.nmgen; diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/AllTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/AllTests.java deleted file mode 100644 index 73d68214..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/AllTests.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.critterai.nmgen; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * Unit tests for all classes in the org.critterai.nav package. - */ -@RunWith(Suite.class) -@SuiteClasses( {GeometryTests.class - , OpenHeightSpanTests.class - , EncompassedNullRegionTests.class - , NullRegionOuterCornerTipTests.class - , NullRegionShortWrapTests.class - , RemoveIntersectingSegmentTests.class - , RemoveVerticalSegmentTests.class} ) -public final class AllTests { } diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/ContourUtil.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/ContourUtil.java deleted file mode 100644 index 0d753694..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/ContourUtil.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.critterai.nmgen; - -import java.util.ArrayList; - -/** - * Provides utilities useful for Contour tests. - */ -public final class ContourUtil -{ - private ContourUtil() { } - - /** - * Shifts the vertices one position higher in the list and - * inserts the last vertex into the first position. - * @param list The contour to shift. (Expecting a stride of 4.) - */ - public static void shiftContour(ArrayList list) - { - int size = list.size(); - - int entry0 = list.get(size-4); - int entry1 = list.get(size-3); - int entry2 = list.get(size-2); - int entry3 = list.get(size-1); - - for (int p = size - 5; p >= 0; p--) - { - list.set(p+4, list.get(p)); - } - - list.set(0, entry0); - list.set(1, entry1); - list.set(2, entry2); - list.set(3, entry3); - - } - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/EncompassedNullRegionTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/EncompassedNullRegionTests.java deleted file mode 100644 index c87bb491..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/EncompassedNullRegionTests.java +++ /dev/null @@ -1,508 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; -import static org.critterai.nmgen.OpenHeightFieldUtil.*; - -import org.critterai.nmgen.OpenHeightfield.OpenHeightFieldIterator; -import org.junit.Test; - -/** - * Tests the ability of {@link CleanNullRegionBorders} to detect - * and fix null regions that are fully encompassed by a single - * non-null region. - *

      This is a partial test of {@link CleanNullRegionBorders} - * functionality.

      - */ -public class EncompassedNullRegionTests -{ - - /* - * Design notes: - * - * These tests make assumptions on the way the OpenHeightField - * iterates. Specifically that it is a width first search. - * - * The "all span" searches inherently validate the detection of - * outer encompassing null regions. - */ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. Search restricted to null spans. (A) - */ - @Test - public void testEncompassedNullARestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionA(); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 2); - assertTrue(field.getData(0, 3).regionID() == 2); - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == 2); - assertTrue(field.getData(1, 3).regionID() == NULL_REGION); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(2, 0).regionID() == 2); - assertTrue(field.getData(2, 1).regionID() == 2); - assertTrue(field.getData(2, 2).regionID() == NULL_REGION); - assertTrue(field.getData(2, 3).regionID() == NULL_REGION); - assertTrue(field.getData(2, 4).regionID() == 2); - assertTrue(field.getData(3, 0).regionID() == 1); - assertTrue(field.getData(3, 1).regionID() == NULL_REGION); - assertTrue(field.getData(3, 2).regionID() == NULL_REGION); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 1); - assertTrue(field.getData(4, 1).regionID() == 1); - assertTrue(field.getData(4, 2).regionID() == 1); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - } - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. Search all spans. (A) - */ - @Test - public void testEncompassedNullA() - { - - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionA(); - - algo.apply(field); - - // field.printRegionField(); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 1); - assertTrue(field.getData(0, 3).regionID() == 1); - assertTrue(field.getData(0, 4).regionID() == 1); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == 1); - assertTrue(field.getData(1, 3).regionID() == NULL_REGION); - assertTrue(field.getData(1, 4).regionID() == 1); - assertTrue(field.getData(2, 0).regionID() == 2); - assertTrue(field.getData(2, 1).regionID() == 2); - assertTrue(field.getData(2, 2).regionID() == NULL_REGION); - assertTrue(field.getData(2, 3).regionID() == NULL_REGION); - assertTrue(field.getData(2, 4).regionID() == 1); - assertTrue(field.getData(3, 0).regionID() == 2); - assertTrue(field.getData(3, 1).regionID() == NULL_REGION); - assertTrue(field.getData(3, 2).regionID() == NULL_REGION); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == 2); - assertTrue(field.getData(4, 2).regionID() == 1); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search restricted to null spans. (A) - */ - @Test - public void testExternalNullRegionARestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search all spans. (A) - */ - @Test - public void testExternalNullRegionA() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search restricted to null spans. (A) - */ - @Test - public void testMultiRegionARestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - // On an inner corner. - field.getData(1, 2).setRegionID(2); - control.getData(1, 2).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search all spans. (A) - */ - @Test - public void testMultiRegionA() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionA(); - OpenHeightfield control = getEncompassedNullRegionA(); - - // On an inner corner. - field.getData(1, 2).setRegionID(2); - control.getData(1, 2).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. - * Search restricted to null spans. (B) - */ - @Test - public void testEncompassedNullBRestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionB(); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 2); - assertTrue(field.getData(0, 3).regionID() == 2); - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == NULL_REGION); - assertTrue(field.getData(1, 3).regionID() == 2); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(2, 0).regionID() == 1); - assertTrue(field.getData(2, 1).regionID() == NULL_REGION); - assertTrue(field.getData(2, 2) == null); - assertTrue(field.getData(2, 3).regionID() == 1); - assertTrue(field.getData(2, 4).regionID() == 1); - assertTrue(field.getData(3, 0).regionID() == 1); - assertTrue(field.getData(3, 1).regionID() == 1); - assertTrue(field.getData(3, 2) == null); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 1); - assertTrue(field.getData(4, 1).regionID() == NULL_REGION); - assertTrue(field.getData(4, 2) == null); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - assertTrue(field.getData(5, 0).regionID() == 1); - assertTrue(field.getData(5, 1).regionID() == 1); - assertTrue(field.getData(5, 2).regionID() == NULL_REGION); - assertTrue(field.getData(5, 3).regionID() == 1); - assertTrue(field.getData(5, 4).regionID() == 1); - assertTrue(field.getData(6, 0).regionID() == 1); - assertTrue(field.getData(6, 1).regionID() == 1); - assertTrue(field.getData(6, 2).regionID() == 1); - assertTrue(field.getData(6, 3).regionID() == 1); - assertTrue(field.getData(6, 4).regionID() == 1); - } - - /** - * Checks for proper region re-assignment for a fully - * encompassed null region. - * Search all spans. (B) - */ - @Test - public void testEncompassedNullB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionB(); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 1); - assertTrue(field.getData(0, 3).regionID() == 1); - assertTrue(field.getData(0, 4).regionID() == 1); - assertTrue(field.getData(1, 0).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 2).regionID() == NULL_REGION); - assertTrue(field.getData(1, 3).regionID() == 1); - assertTrue(field.getData(1, 4).regionID() == 1); - assertTrue(field.getData(2, 0).regionID() == 2); - assertTrue(field.getData(2, 1).regionID() == NULL_REGION); - assertTrue(field.getData(2, 2) == null); - assertTrue(field.getData(2, 3).regionID() == 1); - assertTrue(field.getData(2, 4).regionID() == 1); - assertTrue(field.getData(3, 0).regionID() == 2); - assertTrue(field.getData(3, 1).regionID() == 2); - assertTrue(field.getData(3, 2) == null); - assertTrue(field.getData(3, 3).regionID() == NULL_REGION); - assertTrue(field.getData(3, 4).regionID() == 1); - assertTrue(field.getData(4, 0).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == NULL_REGION); - assertTrue(field.getData(4, 2) == null); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(4, 4).regionID() == 1); - assertTrue(field.getData(5, 0).regionID() == 2); - assertTrue(field.getData(5, 1).regionID() == 2); - assertTrue(field.getData(5, 2).regionID() == NULL_REGION); - assertTrue(field.getData(5, 3).regionID() == 1); - assertTrue(field.getData(5, 4).regionID() == 1); - assertTrue(field.getData(6, 0).regionID() == 2); - assertTrue(field.getData(6, 1).regionID() == 2); - assertTrue(field.getData(6, 2).regionID() == 1); - assertTrue(field.getData(6, 3).regionID() == 1); - assertTrue(field.getData(6, 4).regionID() == 1); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search restricted to null spans. - * (B) - */ - @Test - public void testIntertedBRestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that encompasses - * a single region. Search all spans. - * (B) - */ - @Test - public void testIntertedB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - invertRegion(field); - invertRegion(control); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search restricted to null regions. (B) - */ - @Test - public void testMultiRegionBRestricted() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - // One an outer corner. - field.getData(5, 3).setRegionID(2); - control.getData(5, 3).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * Tests proper detection of a null region that is - * encompassed by more than one non-null region. - * Search all spans. (B) - */ - @Test - public void testMultiRegionB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(false); - OpenHeightfield field = getEncompassedNullRegionB(); - OpenHeightfield control = getEncompassedNullRegionB(); - - // One an outer corner. - field.getData(5, 3).setRegionID(2); - control.getData(5, 3).setRegionID(2); - field.setRegionCount(3); - control.setRegionCount(3); - - algo.apply(field); - - assertTrue(isSameRegionLayout(field, control)); - } - - /** - * A null region fully encompassed by a single region. (RegionID = 1) - */ - private static OpenHeightfield getEncompassedNullRegionA() - { - /* - * W - * 0 1 2 3 4 - * --------- - * 4 | a a a a a - * 3 | a x x x a x - null region span - * D 2 | a a x x a a - region 1 span - * 1 | a a a x a All linked. - * 0 | a a a a a - * - */ - - float[] gridBoundsMin = { -1, -2, -3 }; - float[] gridBoundsMax = { 11, 12, 13 }; - - OpenHeightfield field = new OpenHeightfield(gridBoundsMin - , gridBoundsMax - , 0.2f - , 0.1f); - - for (int w = 0; w < 5; w++) - { - for (int d = 0; d < 5; d++) - { - OpenHeightSpan span = new OpenHeightSpan(w, d + 1); - span.setRegionID(1); - field.addData(w, d, span); - } - } - linkAllBaseSpans(field); - - field.getData(1, 3).setRegionID(NULL_REGION); - field.getData(2, 3).setRegionID(NULL_REGION); - field.getData(3, 3).setRegionID(NULL_REGION); - field.getData(2, 2).setRegionID(NULL_REGION); - field.getData(3, 2).setRegionID(NULL_REGION); - field.getData(3, 1).setRegionID(NULL_REGION); - - field.setRegionCount(2); - - return field; - } - - /** - * A null region fully encompassed by a single region. (RegionID = 1) - */ - private static OpenHeightfield getEncompassedNullRegionB() - { - /* - * W - * 0 1 2 3 4 5 6 7 - * --------------- - * 4 | a a a a a a a a - * 3 | a a a x a a a a x - null region span - * D 2 | a x v v v x a a v - null region, no span. - * 1 | a a x a x a a a a - region 1 span - * 0 | a a a a a a a a All linked. - * - */ - - float[] gridBoundsMin = { -1, -2, -3 }; - float[] gridBoundsMax = { 11, 12, 13 }; - - OpenHeightfield field = new OpenHeightfield(gridBoundsMin - , gridBoundsMax - , 0.2f - , 0.1f); - - for (int w = 0; w < 8; w++) - { - for (int d = 0; d < 5; d++) - { - if (w == 2 && d == 2 - || w == 3 && d == 2 - || w == 4 && d == 2) - continue; - OpenHeightSpan span = new OpenHeightSpan(w, d + 1); - span.setRegionID(1); - field.addData(w, d, span); - } - } - linkAllBaseSpans(field); - - field.getData(1, 2).setRegionID(NULL_REGION); - field.getData(2, 1).setRegionID(NULL_REGION); - field.getData(3, 3).setRegionID(NULL_REGION); - field.getData(4, 1).setRegionID(NULL_REGION); - field.getData(5, 2).setRegionID(NULL_REGION); - - field.setRegionCount(2); - - return field; - } - - /** - * Changes all {@link OpenHeightSpan#NULL_REGION} spans - * to "1" and all spans in region "1" to {@link OpenHeightSpan#NULL_REGION}. - */ - private static void invertRegion(OpenHeightfield field) - { - OpenHeightFieldIterator iter = field.dataIterator(); - - while (iter.hasNext()) - { - OpenHeightSpan span = iter.next(); - if (span.regionID() == NULL_REGION) - span.setRegionID(1); - else - span.setRegionID(NULL_REGION); - } - - } - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/GeometryTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/GeometryTests.java deleted file mode 100644 index ad8b2809..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/GeometryTests.java +++ /dev/null @@ -1,89 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; -import static org.critterai.nmgen.Geometry.*; -import org.junit.Test; - -/** - * Tests functionality in the Geomtry class. - */ -public final class GeometryTests -{ - - private static final float TOLERANCE = 0.0001f; - - @Test - public void testPointSegmentDistance3DFloatBasic() - { - final float ax = -4; - final float ay = 1; - final float az = 2; - - final float bx = 2; - final float by = 1; - final float bz = 2; - - float px = 0; - float py = 1; - float pz = 2; - - float actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(0.0f, actual, TOLERANCE)); - - px = 0; - py = 2; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(1.0f, actual, TOLERANCE)); - - px = 0; - py = 0; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(1.0f, actual, TOLERANCE)); - - px = 4; - py = 1; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(4.0f, actual, TOLERANCE)); - - px = -6; - py = 1; - pz = 2; - - actual = getPointSegmentDistanceSq(px, py, pz - , ax, ay, az - , bx, by, bz); - assertTrue(sloppyEquals(4.0f, actual, TOLERANCE)); - - } - - /** - * Determines whether the values are within the specified tolerance - * of each other. - *

      The values are considered equal if the following condition is met: - * (b >= a - tolerance && b <= a + tolerance)

      - * @param a The a-value to compare the b-value against. - * @param b The b-value to compare against the a-value. - * @param tolerence The tolerance to use for the comparison. - * @return TRUE if the values are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float a, float b, float tolerence) - { - return !(b < a - tolerence || b > a + tolerence); - } - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/NullRegionOuterCornerTipTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/NullRegionOuterCornerTipTests.java deleted file mode 100644 index 05a5c03e..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/NullRegionOuterCornerTipTests.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; -import static org.critterai.nmgen.OpenHeightFieldUtil.*; -import org.junit.Test; - -/** - * Test the detection and resolution of a special case - * where a region only touches a null region at the tip - * of an outer corner. This can result in failure to detect - * a contour connection to the null region. - * - * Governing pattern: - * - * b a - * a x - */ -public class NullRegionOuterCornerTipTests -{ - - /** - * Tests a outer corner tip scenario: - * - * b b a a - * b b a a - * a a x x - * a a x x - */ - @Test - public void testQuadrantA() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(0, 4).setRegionID(2); - field.getData(0, 5).setRegionID(2); - field.getData(1, 4).setRegionID(2); - field.getData(1, 5).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(0, 5).regionID() == 2); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(1, 5).regionID() == 2); - assertTrue(field.getData(0, 3).regionID() == 1); - assertTrue(field.getData(2, 5).regionID() == 1); - - assertTrue((field.getData(1, 3).regionID() == 1 - && field.getData(2, 4).regionID() == 2) - || (field.getData(1, 3).regionID() == 2 - && field.getData(2, 4).regionID() == 1)); - } - - /** - * Tests a outer corner tip scenario: - * - * a b b b - * a a b a - * x x a a - * x x a a - */ - @Test - public void testQuadrantB() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(3, 5).setRegionID(2); - field.getData(4, 4).setRegionID(2); - field.getData(4, 5).setRegionID(2); - field.getData(5, 5).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(3, 5).regionID() == 2); - assertTrue(field.getData(4, 4).regionID() == 2); - assertTrue(field.getData(4, 5).regionID() == 2); - assertTrue(field.getData(5, 5).regionID() == 2); - assertTrue(field.getData(5, 4).regionID() == 1); - assertTrue(field.getData(4, 3).regionID() == 1); - assertTrue(field.getData(5, 3).regionID() == 1); - assertTrue(field.getData(3, 4).regionID() == 2); - } - - /** - * Tests a outer corner tip scenario: - * - * x x a a - * x x a b - * a a b b - * a b b b - */ - @Test - public void testQuadrantC() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(3, 0).setRegionID(2); - field.getData(4, 0).setRegionID(2); - field.getData(4, 1).setRegionID(2); - field.getData(5, 0).setRegionID(2); - field.getData(5, 1).setRegionID(2); - field.getData(5, 2).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(3, 0).regionID() == 2); - assertTrue(field.getData(4, 0).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == 2); - assertTrue(field.getData(5, 0).regionID() == 2); - assertTrue(field.getData(5, 1).regionID() == 2); - assertTrue(field.getData(5, 2).regionID() == 2); - - assertTrue((field.getData(3, 1).regionID() == 1 - && field.getData(4, 2).regionID() == 2) - || (field.getData(3, 1).regionID() == 2 - && field.getData(4, 2).regionID() == 1)); - } - - /** - * Tests a outer corner tip scenario: - * - * a a x x - * b a x x - * b b a a - * b a a a - */ - @Test - public void testQuadrantD() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(0, 0).setRegionID(2); - field.getData(0, 1).setRegionID(2); - field.getData(0, 2).setRegionID(2); - field.getData(1, 1).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 0).regionID() == 2); - assertTrue(field.getData(0, 1).regionID() == 2); - assertTrue(field.getData(0, 2).regionID() == 2); - assertTrue(field.getData(1, 1).regionID() == 2); - assertTrue(field.getData(1, 0).regionID() == 1); - assertTrue(field.getData(2, 0).regionID() == 1); - assertTrue(field.getData(2, 1).regionID() == 1); - assertTrue(field.getData(1, 2).regionID() == 2); - } - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/NullRegionShortWrapTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/NullRegionShortWrapTests.java deleted file mode 100644 index 8728a17d..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/NullRegionShortWrapTests.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.assertTrue; -import static org.critterai.nmgen.OpenHeightFieldUtil.*; - -import org.junit.Test; - -/** - * Test the detection and resolution of a special case - * where a region wraps an outer corner of a null region - * This can result in self-intersecting polygons during polygon - * generation. - * - * Governing pattern: - * - * a a - * a x - */ -public class NullRegionShortWrapTests -{ - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - @Test - public void testNoPreferenceSelection() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(0, 4).setRegionID(2); - field.getData(0, 5).setRegionID(2); - field.getData(1, 3).setRegionID(2); - field.getData(1, 4).setRegionID(2); - field.getData(1, 5).setRegionID(2); - field.getData(2, 4).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - // Only checking in vicinity of expected change. - - assertTrue(field.regionCount() == 3); - - assertTrue(field.getData(0, 4).regionID() == 2); - assertTrue(field.getData(0, 5).regionID() == 2); - assertTrue(field.getData(1, 4).regionID() == 2); - assertTrue(field.getData(1, 5).regionID() == 2); - - assertTrue((field.getData(1, 3).regionID() == 1 - && field.getData(2, 4).regionID() == 2) - || (field.getData(1, 3).regionID() == 2 - && field.getData(2, 4).regionID() == 1)); - - } - - @Test - public void testNoAlternative() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(3, 4).setRegionID(2); - field.getData(3, 5).setRegionID(NULL_REGION); - field.getData(4, 3).setRegionID(2); - field.getData(4, 4).setRegionID(2); - field.getData(5, 3).setRegionID(2); - field.getData(5, 4).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - // No change expected. - assertTrue(field.getData(3, 4).regionID() == 2); - assertTrue(field.getData(3, 5).regionID() == NULL_REGION); - assertTrue(field.getData(4, 3).regionID() == 2); - assertTrue(field.getData(4, 4).regionID() == 2); - assertTrue(field.getData(5, 3).regionID() == 2); - assertTrue(field.getData(5, 4).regionID() == 2); - - } - - @Test - public void testNoBreakAllowed() - { - CleanNullRegionBorders algo = new CleanNullRegionBorders(true); - OpenHeightfield field = getEncompassedNullRegionPatch(); - - field.getData(2, 1).setRegionID(2); - field.getData(3, 1).setRegionID(2); - field.getData(4, 1).setRegionID(2); - field.getData(4, 2).setRegionID(2); - field.getData(4, 3).setRegionID(2); - field.setRegionCount(3); - - algo.apply(field); - - assertTrue(field.regionCount() == 3); - - // No change expected. - assertTrue(field.getData(2, 1).regionID() == 2); - assertTrue(field.getData(3, 1).regionID() == 2); - assertTrue(field.getData(4, 1).regionID() == 2); - assertTrue(field.getData(4, 2).regionID() == 2); - assertTrue(field.getData(4, 3).regionID() == 2); - } - - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/OpenHeightFieldUtil.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/OpenHeightFieldUtil.java deleted file mode 100644 index ced6ffb5..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/OpenHeightFieldUtil.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.critterai.nmgen; - -/** - * Utilities useful for tests involving the open height field. - */ -public final class OpenHeightFieldUtil -{ - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - - private OpenHeightFieldUtil() { } - - /** - * Validates that the base spans in both regions are all in - * the same layout and region. - */ - public static boolean isSameRegionLayout(OpenHeightfield fieldA - , OpenHeightfield fieldB) - { - if (fieldA.regionCount() != fieldB.regionCount()) - return false; - if (fieldA.width() != fieldB.width() - || fieldA.depth() != fieldB.depth()) - return false; - - for (int w = 0; w < fieldA.width(); w++) - { - for (int d = 0; d < fieldA.depth(); d++) - { - OpenHeightSpan spanA = fieldA.getData(w, d); - OpenHeightSpan spanB = fieldB.getData(w, d); - if (spanA == null && spanB != null - || spanB == null && spanA != null) - return false; - if (spanA != null && spanA.regionID() != spanB.regionID()) - return false; - } - } - return true; - } - - /** - * Performs neighbor links of all base spans within a field. - * No checks are performed on validity neighbors. - */ - public static void linkAllBaseSpans(OpenHeightfield field) - { - for (int w = 0; w < field.width(); w++) - { - for (int d = 0; d < field.depth(); d++) - { - OpenHeightSpan span = field.getData(w, d); - if (span == null) - continue; - for (int dir = 0; dir < 4; dir++) - { - int woff = w + OpenHeightfield.getDirOffsetWidth(dir); - int doff = d + OpenHeightfield.getDirOffsetDepth(dir); - if (woff < 0 || woff >= field.width() - || doff < 0 || doff >= field.depth()) - continue; - OpenHeightSpan nSpan = field.getData(woff, doff); - if (nSpan != null) - span.setNeighbor(dir, nSpan); - } - } - } - } - - /** - * A square single level patch with a null region fully encompassed - * by a single region. (RegionID = 1) - * Only the region information and neighbor links are implemented. - * - * W - * 0 1 2 3 4 5 - * ----------- - * 5 | a a a a a a - * 4 | a a a a a a - * 3 | a a x x a a x - null region span - * D 2 | a a x x a a a - region 1 span - * 1 | a a a a a a All linked. - * 0 | a a a a a a - * - */ - public static OpenHeightfield getEncompassedNullRegionPatch() - { - - float[] gridBoundsMin = { 0, 0, 0 }; - float[] gridBoundsMax = { 10, 10, 10 }; - - OpenHeightfield field = new OpenHeightfield(gridBoundsMin - , gridBoundsMax - , 1 - , 1); - - for (int w = 0; w < 6; w++) - { - for (int d = 0; d < 6; d++) - { - OpenHeightSpan span = new OpenHeightSpan(w, d + 1); - span.setRegionID(1); - field.addData(w, d, span); - } - } - linkAllBaseSpans(field); - - field.getData(2, 2).setRegionID(NULL_REGION); - field.getData(2, 3).setRegionID(NULL_REGION); - field.getData(3, 2).setRegionID(NULL_REGION); - field.getData(3, 3).setRegionID(NULL_REGION); - - field.setRegionCount(2); - - return field; - } - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/OpenHeightSpanTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/OpenHeightSpanTests.java deleted file mode 100644 index 4a1630da..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/OpenHeightSpanTests.java +++ /dev/null @@ -1,285 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.*; - -import org.junit.Before; -import org.junit.Test; - -/** - * Tests related to the OpenHeightSpan class. - */ -public class OpenHeightSpanTests -{ - - private static final int ROOT_REGION = 1; - private static final int AXIS_NEGIHBOR0_REGION = 100; - private static final int AXIS_NEGIHBOR1_REGION = 101; - private static final int AXIS_NEGIHBOR2_REGION = 102; - private static final int AXIS_NEGIHBOR3_REGION = 103; - private static final int DIAG_NEGIHBOR4_REGION = 104; - private static final int DIAG_NEGIHBOR5_REGION = 105; - private static final int DIAG_NEGIHBOR6_REGION = 106; - private static final int DIAG_NEGIHBOR7_REGION = 107; - - private static final int NULL_REGION = OpenHeightSpan.NULL_REGION; - private static final int UNUSED_REGION = 9972; - - private final OpenHeightSpan mRootSpan = new OpenHeightSpan(4, 9); - private final OpenHeightSpan mAxisNeighbor0 = new OpenHeightSpan(5, 10); - private final OpenHeightSpan mAxisNeighbor1 = new OpenHeightSpan(5, 11); - private final OpenHeightSpan mAxisNeighbor2 = new OpenHeightSpan(5, 12); - private final OpenHeightSpan mAxisNeighbor3 = new OpenHeightSpan(5, 13); - private final OpenHeightSpan mDiagNeighbor4 = new OpenHeightSpan(6, 14); - private final OpenHeightSpan mDiagNeighbor5 = new OpenHeightSpan(6, 15); - private final OpenHeightSpan mDiagNeighbor6 = new OpenHeightSpan(6, 16); - private final OpenHeightSpan mDiagNeighbor7 = new OpenHeightSpan(6, 17); - - private final int[] mMap = new int[10]; - - @Before - public void setUp() throws Exception - { - mRootSpan.setRegionID(ROOT_REGION); - mAxisNeighbor0.setRegionID(AXIS_NEGIHBOR0_REGION); - mAxisNeighbor1.setRegionID(AXIS_NEGIHBOR1_REGION); - mAxisNeighbor2.setRegionID(AXIS_NEGIHBOR2_REGION); - mAxisNeighbor3.setRegionID(AXIS_NEGIHBOR3_REGION); - mDiagNeighbor4.setRegionID(DIAG_NEGIHBOR4_REGION); - mDiagNeighbor5.setRegionID(DIAG_NEGIHBOR5_REGION); - mDiagNeighbor6.setRegionID(DIAG_NEGIHBOR6_REGION); - mDiagNeighbor7.setRegionID(DIAG_NEGIHBOR7_REGION); - - mRootSpan.setNeighbor(0, mAxisNeighbor0); - mRootSpan.setNeighbor(1, mAxisNeighbor1); - mRootSpan.setNeighbor(2, mAxisNeighbor2); - mRootSpan.setNeighbor(3, mAxisNeighbor3); - - mAxisNeighbor0.setNeighbor(1, mDiagNeighbor4); - mAxisNeighbor0.setNeighbor(2, mRootSpan); - mAxisNeighbor0.setNeighbor(3, mDiagNeighbor7); - - mAxisNeighbor1.setNeighbor(0, mDiagNeighbor4); - mAxisNeighbor1.setNeighbor(2, mDiagNeighbor5); - mAxisNeighbor1.setNeighbor(3, mRootSpan); - - mAxisNeighbor2.setNeighbor(0, mRootSpan); - mAxisNeighbor2.setNeighbor(1, mDiagNeighbor5); - mAxisNeighbor2.setNeighbor(3, mDiagNeighbor6); - - mAxisNeighbor3.setNeighbor(0, mDiagNeighbor7); - mAxisNeighbor3.setNeighbor(1, mRootSpan); - mAxisNeighbor3.setNeighbor(2, mDiagNeighbor6); - - mDiagNeighbor4.setNeighbor(2, mAxisNeighbor1); - mDiagNeighbor4.setNeighbor(3, mAxisNeighbor0); - - mDiagNeighbor5.setNeighbor(1, mAxisNeighbor1); - mDiagNeighbor5.setNeighbor(3, mAxisNeighbor2); - - mDiagNeighbor6.setNeighbor(0, mAxisNeighbor3); - mDiagNeighbor6.setNeighbor(2, mAxisNeighbor2); - - mDiagNeighbor7.setNeighbor(1, mAxisNeighbor0); - mDiagNeighbor7.setNeighbor(2, mAxisNeighbor3); - - // Corrupt the map. - for (int i = 0; i < 10; i++) - mMap[i] = UNUSED_REGION; - - } - - @Test - public void testGetDetailedRegionMapBase() - { - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN0() - { - mRootSpan.setNeighbor(0, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == NULL_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN1() - { - mRootSpan.setNeighbor(1, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == NULL_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN2() - { - mRootSpan.setNeighbor(2, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == NULL_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN3() - { - mRootSpan.setNeighbor(3, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == NULL_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN4() - { - mAxisNeighbor0.setNeighbor(1, null); - mAxisNeighbor1.setNeighbor(0, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == NULL_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN5() - { - mAxisNeighbor1.setNeighbor(2, null); - mAxisNeighbor2.setNeighbor(1, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == NULL_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN6() - { - mAxisNeighbor2.setNeighbor(3, null); - mAxisNeighbor3.setNeighbor(2, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == NULL_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachN7() - { - mAxisNeighbor3.setNeighbor(0, null); - mAxisNeighbor0.setNeighbor(3, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == NULL_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - - @Test - public void testGetDetailedRegionMapDetachPartial() - { - mAxisNeighbor0.setNeighbor(1, null); - mAxisNeighbor0.setNeighbor(3, null); - mRootSpan.getDetailedRegionMap(mMap, 1); - - assertTrue(mMap[1] == AXIS_NEGIHBOR0_REGION); - assertTrue(mMap[2] == AXIS_NEGIHBOR1_REGION); - assertTrue(mMap[3] == AXIS_NEGIHBOR2_REGION); - assertTrue(mMap[4] == AXIS_NEGIHBOR3_REGION); - assertTrue(mMap[5] == DIAG_NEGIHBOR4_REGION); - assertTrue(mMap[6] == DIAG_NEGIHBOR5_REGION); - assertTrue(mMap[7] == DIAG_NEGIHBOR6_REGION); - assertTrue(mMap[8] == DIAG_NEGIHBOR7_REGION); - - assertTrue(mMap[0] == UNUSED_REGION); - assertTrue(mMap[9] == UNUSED_REGION); - } - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/RemoveIntersectingSegmentTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/RemoveIntersectingSegmentTests.java deleted file mode 100644 index b5040a29..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/RemoveIntersectingSegmentTests.java +++ /dev/null @@ -1,475 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; - -import org.junit.Test; -import org.junit.Before; - -/** - * Test related to the ContourSetBuilder.removeIntersectingSegments() - * operation. - */ -public class RemoveIntersectingSegmentTests -{ - - /* - * Design Notes: - * - * The intersecting quads don't test realistic scenarios. But - * they are useful for testing basic operation of the algorithm - * before the more complex realistic scenarios. - */ - - private static final int REGION_A = 1; - private static final int REGION_B = 2; - private static final int REGION_C = 3; - private static final int REGION_S = 52; - - private final ArrayList mBaseQuad = new ArrayList(16); - - private final ArrayList mIntersectionQuadA = - new ArrayList(12); - - private final ArrayList mIntersectionQuadB = - new ArrayList(12); - - @Before - public void setup() - { - - /* - * - * 1 - 2 - * | | - * 0 - 3 - */ - - mBaseQuad.add(1); - mBaseQuad.add(5); - mBaseQuad.add(2); - mBaseQuad.add(0); - - mBaseQuad.add(1); - mBaseQuad.add(5); - mBaseQuad.add(3); - mBaseQuad.add(0); - - mBaseQuad.add(2); - mBaseQuad.add(5); - mBaseQuad.add(3); - mBaseQuad.add(0); - - mBaseQuad.add(2); - mBaseQuad.add(5); - mBaseQuad.add(2); - mBaseQuad.add(0); - - /* - * - * 3 1 - * | x | - * 0 2 - */ - - mIntersectionQuadA.add(1); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(0); - - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(3); - mIntersectionQuadA.add(0); - - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(2); - mIntersectionQuadA.add(0); - - mIntersectionQuadA.add(1); - mIntersectionQuadA.add(5); - mIntersectionQuadA.add(3); - mIntersectionQuadA.add(0); - - /* - * - * 1 3 - * | x | - * 0 2 - */ - - mIntersectionQuadB.add(1); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(2); - mIntersectionQuadB.add(0); - - mIntersectionQuadB.add(1); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(0); - - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(2); - mIntersectionQuadB.add(0); - - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(5); - mIntersectionQuadB.add(3); - mIntersectionQuadB.add(0); - - } - - @Test - public void testBasicQuadOffset0() - { - // No change expected. - mBaseQuad.set(1*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testBasicQuadOffset1() - { - // No change expected. - mBaseQuad.set(2*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testBasicQuadOffset2() - { - // No change expected. - mBaseQuad.set(3*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testBasicQuadOffset3() - { - // No change expected. - mBaseQuad.set(0*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mBaseQuad); - assertTrue(mBaseQuad.size() == 16); - } - - @Test - public void testDisallowedRemovalAll() - { - // No change expected. - - // Make both of the the intersecting segments - // a region portal. - mIntersectionQuadA.set(1*4+3, REGION_A); - mIntersectionQuadA.set(3*4+3, REGION_B); - ContourSetBuilder.removeIntersectingSegments(REGION_S - , mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - - } - - @Test - public void testDisallowedRemovalIndirect() - { - // No change expected. - - // The null edge can't be removed because - // one of its vertices is on a portal edge. - mIntersectionQuadA.set(1*4+3, REGION_A); // <- Tested edge. - mIntersectionQuadA.set(0*4+3, REGION_B); // <- Want's to remove. Can't - ContourSetBuilder.removeIntersectingSegments(REGION_S - , mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - } - - @Test - public void testIntersectingQuadAOffset0() - { - - mIntersectionQuadA.set(1*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 12); - - assertTrue(mIntersectionQuadA.get(0) == 1); - assertTrue(mIntersectionQuadA.get(2) == 2); - - assertTrue(mIntersectionQuadA.get(4) == 2); - assertTrue(mIntersectionQuadA.get(6) == 3); - - assertTrue(mIntersectionQuadA.get(8) == 2); - assertTrue(mIntersectionQuadA.get(10) == 2); - } - - @Test - public void testIntersectingQuadAOffset1() - { - // Expect no change to the quad. - mIntersectionQuadA.set(2*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - } - - @Test - public void testIntersectingQuadAOffset2() - { - mIntersectionQuadA.set(3*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - - assertTrue(mIntersectionQuadA.size() == 12); - - assertTrue(mIntersectionQuadA.get(0) == 1); - assertTrue(mIntersectionQuadA.get(2) == 2); - - assertTrue(mIntersectionQuadA.get(4) == 2); - assertTrue(mIntersectionQuadA.get(6) == 2); - - assertTrue(mIntersectionQuadA.get(8) == 1); - assertTrue(mIntersectionQuadA.get(10) == 3); - } - - @Test - public void testIntersectingQuadAOffset3() - { - // Expect no change to the quad. - mIntersectionQuadA.set(0*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadA); - assertTrue(mIntersectionQuadA.size() == 16); - } - - @Test - public void testIntersectingQuadBOffset0() - { - // Expect no change to the quad. - mIntersectionQuadB.set(1*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 16); - } - - @Test - public void testIntersectingQuadBOffset1() - { - mIntersectionQuadB.set(2*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 12); - - assertTrue(mIntersectionQuadB.get(0) == 1); - assertTrue(mIntersectionQuadB.get(2) == 3); - - assertTrue(mIntersectionQuadB.get(4) == 3); - assertTrue(mIntersectionQuadB.get(6) == 2); - - assertTrue(mIntersectionQuadB.get(8) == 3); - assertTrue(mIntersectionQuadB.get(10) == 3); - } - - @Test - public void testIntersectingQuadBOffset2() - { - // Expect no change to the quad. - mIntersectionQuadB.set(3*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 16); - } - - @Test - public void testIntersectingQuadBOffset3() - { - mIntersectionQuadB.set(0*4+3, REGION_A); - ContourSetBuilder.removeIntersectingSegments(REGION_S, mIntersectionQuadB); - assertTrue(mIntersectionQuadB.size() == 12); - - assertTrue(mIntersectionQuadB.get(0) == 1); - assertTrue(mIntersectionQuadB.get(2) == 2); - - assertTrue(mIntersectionQuadB.get(4) == 1); - assertTrue(mIntersectionQuadB.get(6) == 3); - - assertTrue(mIntersectionQuadB.get(8) == 3); - assertTrue(mIntersectionQuadB.get(10) == 3); - } - - @Test - public void testMultiIntersectA() - { - - ArrayList sourceContour = getMultiIntersectA(); - - for (int sourceOffset = 0; sourceOffset < 10; sourceOffset++) - { - ArrayList contour = new ArrayList(); - contour.addAll(sourceContour); - - ContourSetBuilder.removeIntersectingSegments(REGION_S, contour); - - validateMAIAdjustment(sourceOffset, contour); - - ContourUtil.shiftContour(sourceContour); - } - } - - /** - * Returns the vertex index to use for a MultiIntersectA - * contour after its invalid vertices have been removed, - * taking into account various adjustments. - * @param vertIndex The index to adjust. - * @param sourceOffset The number of shifts performed - * on the source contour. - * @return The index of the vertex in the new contour. - */ - private int getMIAAdjustedIndex(int vertIndex - , int sourceOffset) - { - - final int sourceVertCount = 10; - - int iVert = (vertIndex + sourceOffset) % sourceVertCount; - int iBadVert01 = (3 + sourceOffset) % sourceVertCount; - int iBadVert02 = (4 + sourceOffset) % sourceVertCount; - int iBadVert03 = (5 + sourceOffset) % sourceVertCount; - - int offset = 0; - if (iBadVert01 < iVert) - offset--; - if (iBadVert02 < iVert) - offset--; - if (iBadVert03 < iVert) - offset--; - - return (iVert + offset); - } - - private ArrayList getMultiIntersectA() - { - // When testing against segment 0 -> 1, expect - // vertices 3, 4, and 5 to be removed. - - ArrayList contour = new ArrayList(10*4); - - contour.add(2); - contour.add(5); - contour.add(1); - contour.add(REGION_B); - - contour.add(2); - contour.add(5); - contour.add(10); - contour.add(REGION_A); - - contour.add(3); - contour.add(5); - contour.add(9); - contour.add(0); - - contour.add(2); - contour.add(5); - contour.add(8); - contour.add(0); - - contour.add(1); - contour.add(5); - contour.add(8); - contour.add(0); - - contour.add(1); - contour.add(5); - contour.add(7); - contour.add(0); - - contour.add(4); - contour.add(5); - contour.add(7); - contour.add(0); - - contour.add(6); - contour.add(5); - contour.add(5); - contour.add(REGION_C); - - contour.add(4); - contour.add(5); - contour.add(5); - contour.add(0); - - contour.add(4); - contour.add(5); - contour.add(3); - contour.add(0); - - return contour; - } - - /** - * Checks to make sure a MultiIntersectA contour has been properly - * cleaned up. - * @param sourceOffset The number of shifts performed - * on the source contour. - * @param resultContour The contour after invalid vertices have been - * removed. - * @param startVertIndex The index of the start vertex with the source - * offset already taken into account. - * @param endVertIndex The index of the end vertex with the source - * offset already taken into account. - * @param offset The offset returned by the contour cleanup operation. - */ - private void validateMAIAdjustment(int sourceOffset - , ArrayList resultContour) - { - - final int sourceVertCount = 10; - - // Expect three vertices were removed. - int expectedVertCount = sourceVertCount - 3; - assertTrue("Loop: " + sourceOffset - , resultContour.size() == expectedVertCount * 4); - - int iVert = getMIAAdjustedIndex(0, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 2); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 1); - - iVert = getMIAAdjustedIndex(1, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 2); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 10); - - iVert = getMIAAdjustedIndex(2, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 3); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 9); - - // Removed vertices: 3, 4, 5 - - iVert = getMIAAdjustedIndex(6, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 4); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 7); - - iVert = getMIAAdjustedIndex(7, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 6); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 5); - - iVert = getMIAAdjustedIndex(8, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 4); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 5); - - iVert = getMIAAdjustedIndex(9, sourceOffset); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+0) == 4); - assertTrue("Loop: " + sourceOffset - , resultContour.get(iVert*4+2) == 3); - } - -} diff --git a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/RemoveVerticalSegmentTests.java b/critterai/legacy/nmgen-study/test/org/critterai/nmgen/RemoveVerticalSegmentTests.java deleted file mode 100644 index 1345d44a..00000000 --- a/critterai/legacy/nmgen-study/test/org/critterai/nmgen/RemoveVerticalSegmentTests.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.critterai.nmgen; - -import static org.junit.Assert.assertTrue; - -import java.util.ArrayList; - -import org.junit.Test; -import org.junit.Before; - -/** - * Tests related to the ContourSetBuilder.removeVerticalSegments() - * operation. - */ -public class RemoveVerticalSegmentTests -{ - /* - * Design notes: - * - * These tests are simplified to assume that the second - * vertex in a vertical segment is removed. - */ - private static final int REGION_S = 58; - - private final ArrayList mBadQuad = new ArrayList(16); - - @Before - public void setup() - { - - /* - * Base Quad - * - * 1/2 - 3 - * | | - * 0 - 4/5 - */ - - mBadQuad.add(1); - mBadQuad.add(5); - mBadQuad.add(2); - mBadQuad.add(0); - - mBadQuad.add(1); - mBadQuad.add(5); - mBadQuad.add(3); - mBadQuad.add(0); - - mBadQuad.add(1); - mBadQuad.add(6); - mBadQuad.add(3); - mBadQuad.add(0); - - mBadQuad.add(2); - mBadQuad.add(5); - mBadQuad.add(3); - mBadQuad.add(0); - - mBadQuad.add(2); - mBadQuad.add(5); - mBadQuad.add(2); - mBadQuad.add(0); - - mBadQuad.add(2); - mBadQuad.add(4); - mBadQuad.add(2); - mBadQuad.add(0); - } - - @Test - public void testQuadOffset0() - { - - ContourSetBuilder.removeVerticalSegments(REGION_S, mBadQuad); - assertTrue(mBadQuad.size() == 16); - - assertTrue(mBadQuad.get(0) == 1); - assertTrue(mBadQuad.get(2) == 2); - - assertTrue(mBadQuad.get(4) == 1); - assertTrue(mBadQuad.get(6) == 3); - - assertTrue(mBadQuad.get(8) == 2); - assertTrue(mBadQuad.get(10) == 3); - - assertTrue(mBadQuad.get(12) == 2); - assertTrue(mBadQuad.get(14) == 2); - } - - @Test - public void testQuadOffset1() - { - // This test assumes that the second vertex is removed. - - ContourUtil.shiftContour(mBadQuad); - ContourSetBuilder.removeVerticalSegments(REGION_S, mBadQuad); - assertTrue(mBadQuad.size() == 16); - - assertTrue(mBadQuad.get(0) == 1); - assertTrue(mBadQuad.get(2) == 2); - - assertTrue(mBadQuad.get(4) == 1); - assertTrue(mBadQuad.get(6) == 3); - - assertTrue(mBadQuad.get(8) == 2); - assertTrue(mBadQuad.get(10) == 3); - - assertTrue(mBadQuad.get(12) == 2); - assertTrue(mBadQuad.get(14) == 2); - } - - @Test - public void testQuadOffset2() - { - // This test assumes that the second vertex is removed. - - ContourUtil.shiftContour(mBadQuad); - ContourUtil.shiftContour(mBadQuad); - ContourSetBuilder.removeVerticalSegments(REGION_S, mBadQuad); - assertTrue(mBadQuad.size() == 16); - - assertTrue(mBadQuad.get(0) == 2); - assertTrue(mBadQuad.get(2) == 2); - - assertTrue(mBadQuad.get(4) == 1); - assertTrue(mBadQuad.get(6) == 2); - - assertTrue(mBadQuad.get(8) == 1); - assertTrue(mBadQuad.get(10) == 3); - - assertTrue(mBadQuad.get(12) == 2); - assertTrue(mBadQuad.get(14) == 3); - } - -} diff --git a/critterai/legacy/util-java/build.properties b/critterai/legacy/util-java/build.properties deleted file mode 100644 index 47d1cf8c..00000000 --- a/critterai/legacy/util-java/build.properties +++ /dev/null @@ -1,17 +0,0 @@ -version=snapshot -project.name=cai-util -project.fullname=${project.name}-${version} - -lib.dir=../../lib/java -misc.resources.dir=../../misc - -src.dir=src -local.misc.dir=misc -test.src.dir=test -dist.scm.dir=${lib.dir} - -build.dir=build -classes.dir=${build.dir}/classes -test.classes.dir=${build.dir}/test -dist.dir=${build.dir}/dist -doc.dir=${build.dir}/docs \ No newline at end of file diff --git a/critterai/legacy/util-java/build.xml b/critterai/legacy/util-java/build.xml deleted file mode 100644 index cbe7cbfe..00000000 --- a/critterai/legacy/util-java/build.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - - Builds the CritterAI utility library. - Override the version property with -Dversion. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      - - Project Home - and - - Source Code - -

      -

      - Copyright 2010 Stephen Pratt. All rights reserved. Use is subject to - - license terms. -

      -
      - - ]]> -
      -
      -
      - - - - - -
      \ No newline at end of file diff --git a/critterai/legacy/util-java/misc/overview.html b/critterai/legacy/util-java/misc/overview.html deleted file mode 100644 index e835262c..00000000 --- a/critterai/legacy/util-java/misc/overview.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - -CritterAI Utility Library - - - - -

      The CritterAI Utilities library provides support functionality for various CritterAI projects.

      -

      Project Home
      -
      Project Source
      -License

      - - diff --git a/critterai/legacy/util-java/src/org/critterai/math/MathUtil.java b/critterai/legacy/util-java/src/org/critterai/math/MathUtil.java deleted file mode 100644 index 1723e3c7..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/MathUtil.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -/** - * Provides various math related utility operations. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, no divide by zero checks, etc.

      - *

      Static operations are thread safe.

      - */ -public class MathUtil -{ - - /** - * A standard epsilon value. (Minimum positive value greater than zero.) - */ - public static final float EPSILON_STD = 0.00001f; - - /** - * A standard tolerance value. - */ - public static final float TOLERANCE_STD = 0.0001f; - - private MathUtil() { } - - /** - * Determines whether the values are within the specified tolerance - * of each other. - *

      The values are considered equal if the following condition is met: - * (b >= a - tolerance && b <= a + tolerance)

      - * @param a The a-value to compare the b-value against. - * @param b The b-value to compare against the a-value. - * @param tolerence The tolerance to use for the comparison. - * @return TRUE if the values are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float a, float b, float tolerence) - { - return !(b < a - tolerence || b > a + tolerence); - } - - /** - * Clamps the value to a positive non-zero value. - * @param value The value to clamp. - * @return The value clamped to a minimum of {@link Float#MIN_VALUE}. - */ - public static float clampToPositiveNonZero(float value) - { - return Math.max(Float.MIN_VALUE, value); - } - - /** - * Clamps the value to the specified range. The clamp is inclusive - * such that minimum <= result <= maximum. - * @param value The value to clamp. - * @param minimum The minimum allowed value. - * @param maximum The maximum allowed value. - * @return A value clamped to the specified range. - */ - public static float clamp(float value, float minimum, float maximum) - { - return (value < minimum ? minimum : (value > maximum ? maximum : value)); - } - - /** - * Clamps the value to the specified range. The clamp is inclusive - * such that minimum <= result <= maximum. - * @param value The value to clamp. - * @param minimum The minimum allowed value. - * @param maximum The maximum allowed value. - * @return A value clamped to the specified range. - */ - public static int clamp(int value, int minimum, int maximum) - { - return (value < minimum ? minimum : (value > maximum ? maximum : value)); - } - - /** - * Clamps the value to the specified range. The clamp is inclusive - * such that minimum <= result <= maximum. - * @param value The value to clamp. - * @param minimum The minimum allowed value. - * @param maximum The maximum allowed value. - * @return A value clamped to the specified range. - */ - public static short clamp(short value, short minimum, short maximum) - { - return (value < minimum ? minimum : (value > maximum ? maximum : value)); - } - - /** - * Returns the maximum value in the list of values. - * @param values The values to search. - * @return The maximum value in the list of values. - */ - public static float max(float ...values) - { - float result = values[0]; - for (int i = 1; i < values.length; i++) - result = Math.max(result, values[i]); - return result; - } - - /** - * Returns the minimum value in the list of values. - * @param values The values to search. - * @return The minimum value in the list of values. - */ - public static float min(float ...values) - { - float result = values[0]; - for (int i = 1; i < values.length; i++) - result = Math.min(result, values[i]); - return result; - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/Vector2.java b/critterai/legacy/util-java/src/org/critterai/math/Vector2.java deleted file mode 100644 index ad0ce6ce..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/Vector2.java +++ /dev/null @@ -1,885 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.MathUtil.EPSILON_STD; - -/** - * Represents a mutable 2-dimensional vector. - *

      Contains various static operations applicable to 2D vectors.

      - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, no divide by zero checks, etc.

      - *

      All operations support the use of the same object reference in multiple arguments. - * For example: Vector2.multiply(myVector, 5, myVector) will function - * the same as myVector.multiply(5)

      - *

      Instances of this class are not thread safe. Static operations are thread safe.

      - */ -public class Vector2 -{ - - /** - * The x-value for the vector (x, y). - */ - public float x; - - /** - * The y-value for the vector (x, y). - */ - public float y; - - /** - * Constructor for the vector (0.0, 0.0). (Default) - */ - public Vector2() - { - x = 0.0f; - y = 0.0f; - } - - /** - * Constructor. - * @param x The x-value for the vector (x, y). - * @param y The y-value for the vector (x, y). - */ - public Vector2(float x, float y) - { - this.x = x; - this.y = y; - } - - /** - * Adds the provided vector to this vector. - *

      The values of this vector are mutated.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector2 add(float x, float y) - { - this.x += x; - this.y += y; - return this; - } - - /** - * Adds the provided vector to this vector. - *

      The values of this vector are mutated.

      - * @param v The vector to add to this vector. - * @return A reference to this vector. - */ - public Vector2 add(Vector2 v) - { - return add(v.x, v.y); - } - - /** - * Divides this vector by the provided value. - *

      The values of this vector are mutated.

      - * @param byValue The value to divide the elements of this vector by. - * @return A reference to this vector. - */ - public Vector2 divide(float byValue) - { - this.x /= byValue; - this.y /= byValue; - return this; - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return The dot product of this vector and the provided vector. - * @see Wikipedia- Dot Product - */ - public float dot(float x, float y) - { - return (this.x * x) + (this.y * y); - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param v The vector. - * @return The dot product of this vector and the provided vector. - * @see Wikipedia- Dot Product - */ - public float dot(Vector2 v) - { - return (this.x * v.x) + (this.y * v.y); - } - - /** - * Determines whether or not this vector is equal to the provided vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(float x, float y) - { - - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(x) - || Float.floatToIntBits(this.y) != Float.floatToIntBits(y)) - return false; - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof Vector2)) - return false; - Vector2 other = (Vector2) obj; - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.getX())) - return false; - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.getY())) - return false; - return true; - } - - /** - * Determines whether or not this vector is equal to the provided vector. - *

      This operation is slightly faster than the {@link #equals(Object)} form.

      - * @param v The vector to compare to. (A value of null will result in a runtime error.) - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(Vector2 v) - { - return equals(v.x, v.y); - } - - /** - * The x-value for this vector. - * @return The x-value for the vector (x, y). - */ - public float getX() { return x; } - - /** - * The y-value for this vector. - * @return The y-value for the vector (x, y). - */ - public float getY() { return y; } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() - { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(x); - result = prime * result + Float.floatToIntBits(y); - return result; - } - - /** - * Returns TRUE if the length of the provided vector is zero. - * @return TRUE if the length of the provided vector is zero. Otherwise FALSE. - */ - public boolean isZeroLength() - { - return (x == 0 && y == 0); - } - - /** - * Returns the square of the vector's length. (length * length) - * @return The square of the vector's length. - */ - public float lengthSq() - { - return (x * x) + (y * y); - } - - /** - * Multiplies (scales) this vector by the provided value. - *

      The values of this vector are mutated.

      - * @param byValue The value to multiply the elements of this vector by. - * @return A reference to this vector. - */ - public Vector2 multiply(float byValue) - { - this.x *= byValue; - this.y *= byValue; - return this; - } - - /** - * Normalizes this vector such that its length is one. - *

      The values of this vector are mutated.

      - *

      WARNING: This is a costly operation.

      - * @return A reference to this vector. - */ - public Vector2 normalize() - { - float length = (float)Math.sqrt((x * x) + (y * y)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - - return this; - } - - /** - * Reverses the direction of the vector. - * @return A reference to this vector. - */ - public Vector2 reverse() - { - x = -x; - y = -y; - return this; - } - - /** - * Rotates the vector counter-clockwise by the specified angle. - *

      The values of this vector are mutated.

      - *

      This is a non-trivial operation.

      - * @param angle Angle of counter-clockwise rotation. (In Radians.) - * @return A reference to this vector. - */ - public Vector2 rotate(float angle) - { - float ca = (float)Math.cos(angle); - float sa = (float)Math.sin(angle); - float tx = (x * ca) - (y * sa); - y = (x * sa) + (y * ca); - x = tx; - return this; - } - - /** - * Scales the vector to the provided length. - *

      The values of this vector are mutated.

      - *

      WARNING: This is a costly operation.

      - * @param length The length to scale the vector to. - * @return A reference to this vector. - */ - public Vector2 scaleTo(float length) - { - if (length == 0 || isZeroLength()) - { - x = 0; - y = 0; - return this; - } - return multiply(length / (float)(Math.sqrt((x * x) + (y * y)))); - } - - /** - * Sets the values of this vector. - * @param x The x-value for the vector (x, y). - * @param y The y-value for the vector (x, y). - * @return A reference to this vector. - */ - public Vector2 set(float x, float y) - { - this.x = x; - this.y = y; - return this; - } - - /** - * Sets the values of this vector to match the provided vector. - * @param v The vector to match this vector to. - * @return A reference to this vector. - */ - public Vector2 set(Vector2 v) - { - this.x = v.x; - this.y = v.y; - return this; - } - - /** - * Sets the x-value of this vector. - * @param value The new the x-value for the vector (x, y). - */ - public void setX(float value) { x = value; } - - /** - * Sets the y-value for the vector (x, y). - * @param value The new the y-value for the vector (x, y). - */ - public void setY(float value) { y = value; } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of this vector. - *

      The vectors are considered equal if the following condition is met: - * (vx >= x - tolerance && vx <= x + tolerance) - * && (vy >= y - tolerance && vy <= y + tolerance)

      - * @param vx The x-value for the vector (vx, vy). - * @param vy The y-value for the vector (vx, vy). - * @param tolerance The tolerance to use for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(float vx, float vy, float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < x - tolerance || vx > x + tolerance) - return false; - if (vy < y - tolerance || vy > y + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of this vector. - *

      The vectors are considered equal if the following condition is met: - * (v.x >= x - tolerance && v.x <= x + tolerance) - * && (v.y >= y - tolerance && v.y <= y + tolerance)

      - * @param v The vector to compare against. - * @param tolerance The tolerance for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(Vector2 v, float tolerance) - { - return sloppyEquals(v.x, v.y, tolerance); - } - - /** - * Subtracts the provided vector from this vector. (this - providedVector) - *

      The values of this vector are mutated.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector2 subtract(float x, float y) - { - this.x -= x; - this.y -= y; - return this; - } - - /** - * Subtracts the provided vector from this vector. (this - v) - *

      The values of this vector are mutated.

      - * @param v The vector to subtract from this vector. - * @return A reference to this vector. - */ - public Vector2 subtract(Vector2 v) - { - return subtract(v.x, v.y); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { return "(" + x + ", " + y + ")"; } - - /** - * Truncates the length of this vector to the provided value. - *

      The values of this vector are mutated.

      - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param maxLength The maximum allowed length of the resulting vector. - * @return A reference to this vector. - */ - public Vector2 truncateLength(float maxLength) - { - if (isZeroLength()) - return this; - if (maxLength == 0) - { - set(0, 0); - return this; - } - float mlsq = maxLength * maxLength; - float csq = (x * x) + (y * y); - if (csq > mlsq) - multiply((float)(maxLength / Math.sqrt(csq))); - return this; - } - - /** - * Adds the vectors (ux, uy) and (vx, vy). - * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(float ux, float uy, float vx, float vy, Vector2 out) - { - out.set(ux + vx, uy + vy); - return out; - } - - /** - * Adds the value to both elements of the vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param value The value to add to both of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(float x, float y, float value, Vector2 out) - { - out.set(x + value, y + value); - return out; - } - - /** - * Adds the value to both elements of the vector. - * @param v The vector to add the value to. - * @param value The value to add to both of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(Vector2 v, float value, Vector2 out) - { - return add(v.x, v.y, value, out); - } - - /** - * Adds the two provided vectors. - * @param u Vector to add. - * @param v Vector to add. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 add(Vector2 u, Vector2 v, Vector2 out) - { - return add(u.x, u.y, v.x, v.y, out); - } - - /** - * Divides both elements of the vector by the provided value. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 divide(float x, float y, float byValue, Vector2 out) - { - out.set(x / byValue, y / byValue); - return out; - } - - /** - * Divides both elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 divide(Vector2 v, float byValue, Vector2 out) - { - return divide(v.x, v.y, byValue, out); - } - - /** - * Returns the dot products of the provided vectors. - *

      If you need to the dot product of two vector objects, use {@link #dot(Vector2)}.

      - * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @return The dot product of the provided vectors. - * @see Wikipedia- Dot Product - */ - public static float dot(float ux, float uy, float vx, float vy) - { - return (ux * vx) + (uy * vy); - } - - /** - * Derives the normalized direction vector for the vector pointing from point A (ax, ay) to - * point B (bx, by). - *

      WARNING: The out array size and validity of the outIndex are not checked.

      - *

      WARNING: This is a costly operation.

      - * @param ax The x-value for the starting point A (ax, ay). - * @param ay The y-value for the starting point A (ax, ay). - * @param bx The x-value for the end point B (bx, by). - * @param by The y-value for the end point B (bx, by). - * @param out The array to load the result into in the form (x, y). - * @param outIndex The vector index to load the result into. (Stride = 2. So insertion location - * will be outIndex*2.) - * @return A reference to the out argument. - */ - public static float[] getDirectionAB(float ax, float ay - , float bx, float by - , float[] out - , int outIndex) - { - // Subtract. - float x = bx - ax; - float y = by - ay; - - // Normalize. - float length = (float)Math.sqrt((x * x) + (y * y)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - - out[outIndex*2] = x; - out[outIndex*2+1] = y; - - return out; - } - - /** - * Derives the normalized direction vector for the vector pointing from point A (ax, ay) to - * point B (bx, by). - *

      WARNING: This is a costly operation.

      - * @param ax The x-value for the starting point A (ax, ay). - * @param ay The y-value for the starting point A (ax, ay). - * @param bx The x-value for the end point B (bx, by). - * @param by The y-value for the end point B (bx, by). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 getDirectionAB(float ax, float ay - , float bx, float by - , Vector2 out) - { - // Subtract. - out.x = bx - ax; - out.y = by - ay; - - // Normalize. - float length = (float)Math.sqrt((out.x * out.x) + (out.y * out.y)); - if (length <= EPSILON_STD) - length = 1; - - out.x /= length; - out.y /= length; - - if (Math.abs(out.x) < EPSILON_STD) - out.x = 0; - if (Math.abs(out.y) < EPSILON_STD) - out.y = 0; - - return out; - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param ax The x-value of the point (ax, ay). - * @param ay The y-value of the point (ax, ay). - * @param bx The x-value of the point (bx, by). - * @param by The y-value of the point (bx, by). - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(float ax, float ay, float bx, float by) - { - float dx = ax - bx; - float dy = ay - by; - return (dx * dx + dy * dy); - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param a Point A - * @param b Point B - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(Vector2 a, Vector2 b) - { - return getDistanceSq(a.x, a.y, b.x, b.y); - } - - /** - * Returns the square of the length of the vector. (length * length) - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return The square of the length of the vector. - */ - public static float getLengthSq(float x, float y) - { - return (x * x + y * y); - } - - /** - * Multiplies both elements of the vector by the provided value. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 multiply(float x, float y, float byValue, Vector2 out) - { - out.set(x * byValue, y * byValue); - return out; - } - - /** - * Multiplies both elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 multiply(Vector2 v, float byValue, Vector2 out) - { - return multiply(v.x, v.y, byValue, out); - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

      WARNING: This is a costly operation.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 normalize(float x, float y, Vector2 out) - { - float length = (float)Math.sqrt(getLengthSq(x, y)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - - out.set(x, y); - - return out; - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

      WARNING: This is a costly operation.

      - * @param v The vector to normalize. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 normalize(Vector2 v, Vector2 out) - { - return normalize(v.x, v.y, out); - } - - /** - * Rotates the vector counter-clockwise by the specified angle. - *

      This is a non-trivial operation.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param angle Angle of counter-clockwise rotation. (In Radians.) - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 rotate(float x, float y, float angle, Vector2 out) - { - float ca = (float)Math.cos(angle); - float sa = (float)Math.sin(angle); - out.set((x * ca) - (y * sa), (x * sa) + (y * ca)); - return out; - } - - /** - * Rotates the vector counter-clockwise by the specified angle. - *

      This is a non-trivial operation.

      - * @param v The vector to rotate. - * @param angle Angle of counter-clockwise rotation. (In Radians.) - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 rotate(Vector2 v, float angle, Vector2 out) - { - return rotate(v.x, v.y, angle, out); - } - - /** - * Scales the vector to the provided length. - *

      WARNING: This is a costly operation.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 scaleTo(float x, float y, float length, Vector2 out) - { - if (length == 0 || (x == 0 && y == 0)) - { - out.set(0, 0); - return out; - } - return multiply(x, y - , (length / (float)(Math.sqrt(getLengthSq(x, y)))), out); - } - - /** - * Scales the vector to the provided length. - *

      WARNING: This is a costly operation.

      - * @param v The vector to scale. - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 scaleTo(Vector2 v, float length, Vector2 out) - { - return scaleTo(v.x, v.y, length, out); - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance. - *

      The vectors are considered equal if the following condition is met: - * (vx >= ux - tolerance && vx <= ux + tolerance) - * && (vy >= uy - tolerance && vy <= uy + tolerance)

      - * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float ux, float uy, float vx, float vy, float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < ux - tolerance || vx > ux + tolerance) - return false; - if (vy < uy - tolerance || vy > uy + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance. - *

      The vectors are considered equal if the following condition is met: - * (v.x >= u.x - tolerance && v.x <= u.x + tolerance) - * && (v.y >= u.y - tolerance && v.y <= u.y + tolerance)

      - * @param u Vector v - * @param v Vector u - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(Vector2 u, Vector2 v, float tolerance) - { - return sloppyEquals(u.x, u.y, v.x, v.y, tolerance); - } - - /** - * Subtracts vector (vx, vy) from vector (ux, uy) - * @param ux The x-value of the vector (ux, uy). - * @param uy The y-value of the vector (ux, uy). - * @param vx The x-value of the vector (vx, vy). - * @param vy The y-value of the vector (vx, vy). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 subtract(float ux, float uy, float vx, float vy, Vector2 out) - { - out.set(ux - vx, uy - vy); - return out; - } - - /** - * Subtracts two vectors. (u - v) - * @param u Vector to be subtracted from. - * @param v Vector to subtract. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 subtract(Vector2 u, Vector2 v, Vector2 out) - { - return subtract(u.x, u.y, v.x, v.y, out); - } - - /** - * Truncates the length of the vector to the provided value. - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 truncateLength(float x, float y, float maxLength, Vector2 out) - { - if (maxLength == 0 || (x == 0 && y == 0)) - { - out.set(0, 0); - return out; - } - float mlsq = maxLength * maxLength; - float csq = getLengthSq(x, y); - if (csq <= mlsq) - { - out.set(x, y); - return out; - } - return multiply(x, y, (float)(maxLength / Math.sqrt(csq)), out); - } - - /** - * Truncates the length of the vector to the provided value. - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param v The vector to truncate. - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 truncateLength(Vector2 v, float maxLength, Vector2 out) - { - return truncateLength(v.x, v.y, maxLength, out); - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/Vector3.java b/critterai/legacy/util-java/src/org/critterai/math/Vector3.java deleted file mode 100644 index c4574432..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/Vector3.java +++ /dev/null @@ -1,1157 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.MathUtil.EPSILON_STD; - -/** - * Represents a mutable 3-dimensional vector. - *

      Contains various static operations applicable to 3D vectors.

      - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, no divide by zero checks, etc.

      - *

      All operations support the use of the same object reference in multiple arguments. - * For example: Vector3.normalize(vectorArray, 1, vectorArray, 1) will normalize the vector at - * position 1 in the vectorArray.

      - *

      Instances of this class are not thread safe. Static operations are thread safe.

      - */ -public class Vector3 -{ - - /** - * The x-value for the vector (x, y, z). - */ - public float x; - - /** - * The y-value for the vector (x, y, z). - */ - public float y; - - - /** - * The z-value for the vector (x, y, z). - */ - public float z; - - /** - * Constructor for the vector (0, 0, 0). (Default) - */ - public Vector3() - { - x = 0.0f; - y = 0.0f; - z = 0.0f; - } - - /** - * Constructor. - * @param x The x-value for the vector (x, y, z). - * @param y The y-value for the vector (x, y, z). - * @param z The z-value for the vector (x, y, z). - */ - public Vector3(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - } - - /** - * Constructs a vector from an array entry. - * @param vectorArray An array of vectors in the form (x, y, z). - * @param index The index of the vector entry to use. The expected stride is three. - * So the extraction point will be index*3. - * @throws IllegalArgumentException If the array size or index is invalid. - */ - public Vector3(float[] vectorArray, int index) - throws IllegalArgumentException - { - if (vectorArray == null || index*3+2 >= vectorArray.length) - throw new IllegalArgumentException("Invalid array or index."); - x = vectorArray[index*3]; - y = vectorArray[index*3+1]; - z = vectorArray[index*3+2]; - } - - /** - * Adds the provided vector to this vector. - *

      The values of this vector are mutated.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @param z The z-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector3 add(float x, float y, float z) - { - this.x += x; - this.y += y; - this.z += z; - return this; - } - - /** - * Adds the provided vector to this vector. - *

      The values of this vector are mutated.

      - * @param v The vector to add to this vector. - * @return A reference to this vector. - */ - public Vector3 add(Vector3 v) - { - return add(v.x, v.y, v.z); - } - - /** - * Divides this vector by the provided value. - *

      The values of this vector are mutated.

      - * @param byValue The value to divide the elements of this vector by. - * @return A reference to this vector. - */ - public Vector3 divide(float byValue) - { - this.x /= byValue; - this.y /= byValue; - this.z /= byValue; - return this; - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param x The x-value for the vector (x, y, z). - * @param y The y-value for the vector (x, y, z). - * @param z The z-value for the vector (x, y, z). - * @return The dot product of this vector and the provided vector. - */ - public float dot(float x, float y, float z) - { - return (this.x * x) + (this.y * y) + (this.z * z); - } - - /** - * Returns the dot product of this vector and the provided vector. - * @param v The vector. - * @return The dot product of this vector and the provided vector. - */ - public float dot(Vector3 v) - { - return dot(v.x, v.y, v.z); - } - - /** - * Determines whether or not this vector is equal to the provided vector. - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(float x, float y, float z) - { - - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(x) - || Float.floatToIntBits(this.y) != Float.floatToIntBits(y) - || Float.floatToIntBits(this.z) != Float.floatToIntBits(z)) - return false; - return true; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof Vector3)) return false; - Vector3 other = (Vector3) obj; - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.getX())) - return false; - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.getY())) - return false; - if (Float.floatToIntBits(z) != Float.floatToIntBits(other.getZ())) - return false; - return true; - } - - /** - * Determines whether or not this vector is equal to the provided vector. - *

      This operation is slightly faster than the {@link #equals(Object)} form.

      - * @param v The vector to compare to. (A value of null will result in a runtime error.) - * @return Returns TRUE if this vector is equal to the provided vector. Otherwise FALSE. - */ - public boolean equals(Vector3 v) - { - return equals(v.x, v.y, v.z); - } - - /** - * Inserts the content of this vector into the specified array. - *

      Warning: No argument validations are performed.

      - * @param out The array to insert the vector into. - * @param outIndex The insertion point. The expected stride is 3. So the insertion - * point will be outIndex*3. - * @return A reference to the out argument. - */ - public float[] get(float[] out, int outIndex) - { - out[outIndex*3] = x; - out[outIndex*3+1] = y; - out[outIndex*3+2] = z; - return out; - } - - /** - * The x-value for this vector. - * @return The x-value for this vector. - */ - public float getX() { return x; } - - /** - * The y-value for this vector. - * @return The y-value for this vector. - */ - public float getY() { return y; } - - /** - * The z-value for this vector. - * @return The z-value for this vector. - */ - public float getZ() { return z; } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + Float.floatToIntBits(x); - result = prime * result + Float.floatToIntBits(y); - result = prime * result + Float.floatToIntBits(z); - return result; - } - - /** - * Returns TRUE if the length of this vector is zero. - * @return TRUE if the length of this vector is zero. Otherwise FALSE. - */ - public boolean isZeroLength() - { - return (x == 0 && y == 0 && z == 0); - } - - /** - * Returns the square of this vector's length. (length * length) - * @return The square of this vector's length. - */ - public float lengthSq() - { - return (x * x) + (y * y) + (z * z); - } - - /** - * Multiplies (scales) this vector by the provided value. - *

      The values of this vector are mutated.

      - * @param byValue The value to multiply the elements of this vector by. - * @return A reference to this vector. - */ - public Vector3 multiply(float byValue) - { - this.x *= byValue; - this.y *= byValue; - this.z *= byValue; - return this; - } - - /** - * Normalizes this vector such that its length is one. - *

      The values of this vector are mutated.

      - *

      WARNING: This is a costly operation

      - * @return A reference to this vector. - */ - public Vector3 normalize() - { - float length = (float)Math.sqrt((x * x) + (y * y) + (z * z)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - z /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - if (Math.abs(z) < EPSILON_STD) - z = 0; - - return this; - } - - /** - * Scales this vector to the provided length. - *

      The values of this vector are mutated.

      - *

      WARNING: This is a costly operation.

      - * @param length The length to scale the vector to. - * @return A reference to this vector. - */ - public Vector3 scaleTo(float length) - { - if (length == 0 || isZeroLength()) - { - x = 0; - y = 0; - z = 0; - return this; - } - return multiply(length / (float)(Math.sqrt((x * x) + (y * y) + (z * z)))); - } - - /** - * Sets the values for this vector. - * @param x The x-value for this vector. - * @param y The y-value for this vector. - * @param z The z-value for this vector. - * @return A reference to this vector. - */ - public Vector3 set(float x, float y, float z) - { - this.x = x; - this.y = y; - this.z = z; - return this; - } - - /** - * Sets the values for this vector to match the provided vector. - * @param v The vector to match this vector to. - * @return A reference to this vector. - */ - public Vector3 set(Vector3 v) - { - x = v.x; - y = v.y; - z = v.z; - return this; - } - - /** - * Sets the x-value for this vector. - * @param value The new x-value for this vector. - */ - public void setX(float value) { x = value; } - - /** - * Sets the y-value for this vector. - * @param value The new y-value for this vector. - */ - public void setY(float value) { y = value; } - - /** - * Sets the z-value for this vector. - * @param value The new z-value for this vector. - */ - public void setZ(float value) { z = value; } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of the elements of this vector. - *

      The vectors are considered equal if the following condition is met: - * (vx >= x - tolerance && vx <= x + tolerance) - * && (vy >= y - tolerance && vy <= y + tolerance) - * && (vz >= z - tolerance && vz <= z + tolerance)

      - * @param vx The x-value for the vector (vx, vy, vz). - * @param vy The y-value for the vector (vx, vy, vz). - * @param vz The z-value for the vector (vx, vy, vz). - * @param tolerance The tolerance for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(float vx, float vy, float vz, float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < x - tolerance || vx > x + tolerance) - return false; - if (vy < y - tolerance || vy > y + tolerance) - return false; - if (vz < z - tolerance || vz > z + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vector are equal within - * the specified tolerance of the elements of this vector. - *

      The vectors are considered equal if the following condition is met: - * (vx >= x - tolerance && vx <= x + tolerance) - * && (vy >= y - tolerance && vy <= y + tolerance) - * && (vz >= z - tolerance && vz <= z + tolerance)

      - * @param v The vector to compare against. - * @param tolerance The tolerance for the comparison. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public boolean sloppyEquals(Vector3 v, float tolerance) - { - return sloppyEquals(v.x, v.y, v.z, tolerance); - } - - /** - * Subtracts the provided vector from this vector. (this - providedVector) - *

      The values of this vector are mutated.

      - * @param x The x-value of the vector (x, y). - * @param y The y-value of the vector (x, y). - * @return A reference to this vector. - */ - public Vector3 subtract(float x, float y, float z) - { - this.x -= x; - this.y -= y; - this.z -= z; - return this; - } - - /** - * Subtracts the provided vector from this vector. (this - v) - *

      The values of this vector are mutated.

      - * @param v The vector to subtract from this vector. - * @return A reference to this vector. - */ - public Vector3 subtract(Vector3 v) - { - return subtract(v.x, v.y, v.z); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { return "(" + x + ", " + y + ", " + z + ")"; } - - /** - * Truncates the length of the vector to the provided value. - *

      The values of this vector are mutated.

      - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param maxLength The maximum allowed length of the resulting vector. - * @return A reference to this vector. - */ - public Vector3 truncateLength(float maxLength) - { - if (isZeroLength()) - return this; - if (maxLength == 0) - { - set(0, 0, 0); - return this; - } - float mlsq = maxLength * maxLength; - float csq = (x * x) + (y * y) + (z * z); - if (csq > mlsq) - multiply((float)(maxLength / Math.sqrt(csq))); - return this; - } - - /** - * Adds the vectors (ux, uy, uz) and (vx, vy, vz). - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(float ux, float uy, float uz - , float vx, float vy, float vz - , Vector3 out) - { - out.set(ux + vx, uy + vy, uz + vz); - return out; - } - - /** - * Adds the value to all elements of the vector. - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param value The value to add to each of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(float x, float y, float z, float value, Vector3 out) - { - out.set(x + value, y + value, z + value); - return out; - } - - /** - * Adds the value to all elements of the vector. - * @param v The vector to add the value to. - * @param value The value to add to each of the vector elements. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(Vector3 v, float value, Vector3 out) - { - return add(v.x, v.y, v.z, value, out); - } - - /** - * Adds the two provided vectors. - * @param u Vector u - * @param v Vector v - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 add(Vector3 u, Vector3 v, Vector3 out) - { - return add(u.x, u.y, u.z, v.x, v.y, v.z, out); - } - - /** - * Performs a vector "righthanded" cross product. (u x v) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - *

      WARNING: No argument validations are peformed.

      - * @param vx The x-value of the vector (ux, uy, uz). - * @param vy The y-value of the vector (ux, uy, uz). - * @param vz The z-value of the vector (ux, uy, uz). - * @param ux The x-value of the vector (vx, vy, vz). - * @param uy The y-value of the vector (vx, vy, vz). - * @param uz The z-value of the vector (vx, vy, vz). - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result. The expected stride is three, so the - * insertion point will be outIndex*3. - * @return A reference to the out array. - */ - public static float[] cross( - float ux, float uy, float uz - , float vx, float vy, float vz - , float[] out - , int outIndex) - { - out[outIndex*3] = uy * vz - uz * vy; - out[outIndex*3+1] = -ux * vz + uz * vx; - out[outIndex*3+2] = ux * vy - uy * vx; - return out; - } - - /** - * Performs a vector "righthanded" cross product. (u x v) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 cross( - float ux, float uy, float uz - , float vx, float vy, float vz - , Vector3 out) - { - out.x = uy * vz - uz * vy; - out.y = -ux * vz + uz * vx; - out.z = ux * vy - uy * vx; - return out; - } - - /** - * Performs a vector "righthanded" cross product. (vectorA x vectorB) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - *

      WARNING: No argument validations are performed.

      - *

      All arrays are expected to have a stride of three. So vectors in an array - * are located at index*3.

      - * @param vectorsA An array of vectors in the form (x, y, z). - * @param vectorAIndex The index of vectorA within the vectorsA array. - * @param vectorsB An array of vectors in the form (x, y, z). - * @param vectorBIndex The index of vectorB within the vectorsB array. - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index in the out array to insert the result into. - * @return A reference to the out array. - */ - public static float[] cross(float[] vectorsA - , int vectorAIndex - , float[] vectorsB - , int vectorBIndex - , float[] out - , int outIndex) - { - return cross(vectorsA[vectorAIndex*3] - , vectorsA[vectorAIndex*3+1] - , vectorsA[vectorAIndex*3+2] - , vectorsB[vectorBIndex*3] - , vectorsB[vectorBIndex*3+1] - , vectorsB[vectorBIndex*3+2] - , out - , outIndex); - } - - /** - * Performs a vector "righthanded" cross product. (u x v) - * The resulting vector will be perpendicular to the plane - * containing the two provided vectors. - *

      Special Case: The result will be zero if the two - * vectors are parallel

      - * @param u Vector U - * @param v Vector V - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 cross(Vector3 u, Vector3 v, Vector3 out) - { - return cross(u.x, u.y, u.z - , v.x, v.y, v.z - , out); - } - - /** - * Divides all elements of the vector by the provided value. - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 divide(float x, float y, float z, float byValue, Vector3 out) - { - out.set(x / byValue, y / byValue, z / byValue); - return out; - } - - /** - * Divides all elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to divide the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 divide(Vector3 v, float byValue, Vector3 out) - { - return divide(v.x, v.y, v.z, byValue, out); - } - - /** - * Returns the dot product of the provided vectors. - *

      If you need to dot two vector objects, use {@link #dot(Vector3)}. - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @return The dot product of the provided vectors. - */ - public static float dot(float ux, float uy, float uz - , float vx, float vy, float vz) - { - return (ux * vx) + (uy * vy) + (uz * vz); - } - - /** - * Inserts the provided vectors into the out array. - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outStartIndex The vector index in the out array to start the insertion at. - * The expected stride is three, so insertion will start at outStartIndex*3. - * @param vectors The vectors to insert into the out array. There can be no nulls - * in this list. - * @return A reference to the out array. - */ - public static float[] flatten(float[] out, int outStartIndex, Vector3... vectors) - { - - outStartIndex *= 3; // Convert to pointer. - for (Vector3 v : vectors) - { - out[outStartIndex] = v.x; - out[outStartIndex+1] = v.y; - out[outStartIndex+2] = v.z; - outStartIndex += 3; - } - return out; - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param ax The x-value of the point (ax, ay, az). - * @param ay The y-value of the point (ax, ay, az). - * @param az The z-value of the point (ax, ay, az). - * @param bx The x-value of the point (bx, by, bz). - * @param by The y-value of the point (bx, by, bz). - * @param bz The z-value of the point (bx, by, bz). - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(float ax, float ay, float az - , float bx, float by, float bz) - { - float dx = ax - bx; - float dy = ay - by; - float dz = az - bz; - return (dx * dx + dy * dy + dz * dz); - } - - /** - * Returns the square of the distance between the two provided points. (distance * distance) - * @param a Point A - * @param b Point B - * @return The square of the distance between the two provided points. - */ - public static float getDistanceSq(Vector3 a, Vector3 b) - { - return getDistanceSq(a.x, a.y, a.z, b.x, b.y, b.z); - } - - /** - * Returns the square of the length of the vector. (length * length) - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @return The square of the length of the vector. - */ - public static float getLengthSq(float x, float y, float z) - { - return (x * x + y * y + z * z); - } - - /** - * Gets the square of the length of a vector entry in an array. - *

      WARNINg: No validations are peformed on the out array or outIndex.

      - * @param vectors An array of vectors in the form (x, y, z) - * @param vectorIndex The index of the vector to get the length of. Stride expected is three, so - * the vector is expected to be located at vectorIndex*3. - * @return The square of the length of the vector entry in the array. - */ - public static float getLengthSq(float[] vectors, int vectorIndex) - { - return (vectors[vectorIndex*3] * vectors[vectorIndex*3]) - + (vectors[vectorIndex*3+1] * vectors[vectorIndex*3+1]) - + (vectors[vectorIndex*3+2] * vectors[vectorIndex*3+2]); - } - - /** - * Multiplies all elements of the vector by the provided value. - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 multiply(float x, float y, float z, float byValue, Vector3 out) - { - out.set(x * byValue, y * byValue, z * byValue); - return out; - } - - /** - * Multiplies all elements of the vector by the provided value. - * @param v The vector. - * @param byValue The value to multiply the vector by. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 multiply(Vector3 v, float byValue, Vector3 out) - { - return multiply(v.x, v.y, v.z, byValue, out); - } - - /** - * Normalizes the vector and stores the result - * at the specified location within the out array. - *

      WARNINg: No argument validations are peformed.

      - *

      WARNING: This is a costly operation

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result at. The stride is three, so - * the insertion point in out will be outIndex*3. - * @return A reference to the out array. - */ - public static float[] normalize(float x, float y, float z - , float[] out - , int outIndex) - { - float length = (float)Math.sqrt((x * x) + (y * y) + (z * z)); - if (length <= EPSILON_STD) - length = 1; - - int pOut = outIndex*3; - - out[pOut] = x / length; - out[pOut+1] = y / length; - out[pOut+2] = z / length; - - if (Math.abs(out[pOut]) < EPSILON_STD) - out[pOut] = 0; - if (Math.abs(out[pOut+1]) < EPSILON_STD) - out[pOut+1] = 0; - if (Math.abs(out[pOut+2]) < EPSILON_STD) - out[pOut+2] = 0; - - return out; - - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

      WARNING: This is a costly operation

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 normalize(float x, float y, float z, Vector3 out) - { - float length = (float)Math.sqrt(getLengthSq(x, y, z)); - if (length <= EPSILON_STD) - length = 1; - - x /= length; - y /= length; - z /= length; - - if (Math.abs(x) < EPSILON_STD) - x = 0; - if (Math.abs(y) < EPSILON_STD) - y = 0; - if (Math.abs(z) < EPSILON_STD) - z = 0; - - out.set(x, y, z); - - return out; - } - - /** - * Normalizes the vector from the vectors array and stores the result - * at the specified location within the out array. - *

      WARNING: No argument validations are peformed.

      - *

      All arrays are expected to have a stride of three. So vectors in the array - * are located at index*3. - *

      WARNING: This is a costly operation

      - * @param vectors An array of vectors in the form (x, y, z). - * @param vectorIndex The vector index of the vector to be normalized. - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result at. - * @return A reference to the out array. - */ - public static float[] normalize(float[] vectors - , int vectorIndex - , float[] out - , int outIndex) - { - - float length = (float)Math.sqrt(getLengthSq(vectors, vectorIndex)); - if (length <= EPSILON_STD) - length = 1; - - int pOut = outIndex*3; - - out[pOut] = vectors[vectorIndex*3] / length; - out[pOut+1] = vectors[vectorIndex*3+1] / length; - out[pOut+2] = vectors[vectorIndex*3+2] / length; - - if (Math.abs(out[pOut]) < EPSILON_STD) - out[pOut] = 0; - if (Math.abs(out[pOut+1]) < EPSILON_STD) - out[pOut+1] = 0; - if (Math.abs(out[pOut+2]) < EPSILON_STD) - out[pOut+2] = 0; - - return out; - } - - /** - * Normalizes the provided vector such that its length is equal to one. - *

      WARNING: This is a costly operation

      - * @param v The vector to normalize. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 normalize(Vector3 v, Vector3 out) - { - return normalize(v.x, v.y, v.z, out); - } - - /** - * Scales the vector to the provided length. - *

      WARNING: This is a costly operation.

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 scaleTo(float x, float y, float z, float length, Vector3 out) - { - if (length == 0 || (x == 0 && y == 0 && z == 0)) - { - out.set(0, 0, 0); - return out; - } - return multiply(x, y, z - , (length / (float)(Math.sqrt(getLengthSq(x, y, z)))), out); - } - - /** - * Scales the vector to the provided length. - *

      WARNING: This is a costly operation.

      - * @param v The vector to scale. - * @param length The length to scale the vector to. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 scaleTo(Vector3 v, float length, Vector3 out) - { - return scaleTo(v.x, v.y, v.z, length, out); - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance of each other. - *

      The vectors are considered equal if the following condition is met: - * (vx >= ux - tolerance && vx <= ux + tolerance) - * && (vy >= uy - tolerance && vy <= uy + tolerance) - * && (vz >= uz - tolerance && vz <= uz + tolerance)

      - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(float ux, float uy, float uz - , float vx, float vy, float vz - , float tolerance) - { - tolerance = Math.max(0, tolerance); - if (vx < ux - tolerance || vx > ux + tolerance) - return false; - if (vy < uy - tolerance || vy > uy + tolerance) - return false; - if (vz < uz - tolerance || vz > uz + tolerance) - return false; - return true; - } - - /** - * Determines whether or not the elements of the provided vectors are equal within - * the specified tolerance of each other. - * (v.x >= u.x - tolerance && v.x <= u.x + tolerance) - * && (v.y >= u.y - tolerance && v.y <= u.y + tolerance) - * && (v.z >= u.z - tolerance && v.z <= u.z + tolerance)

      - * @param u Vector u - * @param v Vector v - * @param tolerance The tolerance for the test. - * @return TRUE if the the associated elements of each vector are within the specified tolerance - * of each other. Otherwise FALSE. - */ - public static boolean sloppyEquals(Vector3 u, Vector3 v, float tolerance) - { - return sloppyEquals(u.x, u.y, u.z, v.x, v.y, v.z, tolerance); - } - - /** - * Subtracts vector (vx, vy, vz) from vector (ux, uy, uz) and stores - * the result in the specified location within the out array. (u - v) - *

      WARNING: No argument validations are peformed.

      - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector array to store the result in, in the form (x, y, z). - * @param outIndex The vector index to store the result at. The expected stride is three, - * so the insertion point in out will be outIndex*3. - * @return A reference to the out array. - */ - public static float[] subtract( - float ux, float uy, float uz - , float vx, float vy, float vz - , float[] out - , int outIndex) - { - out[outIndex*3] = ux - vx; - out[outIndex*3+1] = uy - vy; - out[outIndex*3+2] = uz - vz; - return out; - } - - /** - * Subtracts vector (vx, vy, vz) from vector (ux, uy, uz). (u - v) - * @param ux The x-value of the vector (ux, uy, uz). - * @param uy The y-value of the vector (ux, uy, uz). - * @param uz The z-value of the vector (ux, uy, uz). - * @param vx The x-value of the vector (vx, vy, vz). - * @param vy The y-value of the vector (vx, vy, vz). - * @param vz The z-value of the vector (vx, vy, vz). - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 subtract(float ux, float uy, float uz - , float vx, float vy, float vz - , Vector3 out) - { - out.set(ux - vx, uy - vy, uz - vz); - return out; - } - - /** - * Subtracts vectorB from vectorA. (vectorA - vectorB) - *

      WARNING: No argument validations are peformed.

      - *

      All arrays are expected to have a stride of three. So vectors in the array - * are located at index*3. - * @param vectorsA An array of vectors in the form (x, y, z). - * @param vectorAIndex The index of vectorA within the vectorsA array. - * @param vectorsB An array of vectors in the form (x, y, z). - * @param vectorBIndex The index of vectorB within the vectorsB array. - * @param out The vector array to store the result in. - * @param outIndex The vector index in the out array to insert the result at. - * @return A reference to the out array. - */ - public static float[] subtract(float[] vectorsA - , int vectorAIndex - , float[] vectorsB - , int vectorBIndex - , float[] out - , int outIndex) - { - out[outIndex*3] = vectorsA[vectorAIndex*3] - vectorsB[vectorBIndex*3]; - out[outIndex*3+1] = vectorsA[vectorAIndex*3+1] - vectorsB[vectorBIndex*3+1]; - out[outIndex*3+2] = vectorsA[vectorAIndex*3+2] - vectorsB[vectorBIndex*3+2]; - return out; - } - - /** - * Subtracts the two vectors. (u - v) - * @param u Vector to be subtracted from. - * @param v Vector to subtract. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 subtract(Vector3 u, Vector3 v, Vector3 out) - { - return subtract(u.x, u.y, u.z, v.x, v.y, v.z, out); - } - - /** - * Traslates point A toward point B by the specified factor of the - * distance between them. - *

      Examples:

      - *

      If the factor is 0.0, then the result will equal A.
      - * If the factor is 0.5, then the result will be the midpoint between A and B.
      - * If the factor is 1.0, then the result will equal B.

      - * @param ax The x-value of the point (ax, ay, az). - * @param ay The y-value of the point (ax, ay, az). - * @param az The z-value of the point (ax, ay, az). - * @param bx The x-value of the point (bx, by, bz). - * @param by The y-value of the point (bx, by, bz). - * @param bz The z-value of the point (bx, by, bz). - * @param factor The factor which governs the distance the point is translated - * from A toward B. - * @param out The vector to store the result in. - * @return A reference to the out argument. - */ - public static Vector3 translateToward(float ax, float ay, float az - , float bx, float by, float bz - , float factor - , Vector3 out) - { - Vector3.subtract(bx, by, bz, ax, ay, az, out); - out.multiply(factor); - return out.add(ax, ay, az); - } - - /** - * Truncates the length of the vector to the provided value. - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param x The x-value of the vector (x, y, z). - * @param y The y-value of the vector (x, y, z). - * @param z The z-value of the vector (x, y, z). - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 truncateLength(float x, float y, float z - , float maxLength - , Vector3 out) - { - if (maxLength == 0 || (x == 0 && y == 0 && z == 0)) - { - out.set(0, 0, 0); - return out; - } - float mlsq = maxLength * maxLength; - float csq = getLengthSq(x, y, z); - if (csq <= mlsq) - { - out.set(x, y, z); - return out; - } - return multiply(x, y, z, (float)(maxLength / Math.sqrt(csq)), out); - } - - /** - * Truncates the length of the vector to the provided value. - *

      If the vector's length is longer than the provided value the length - * of the vector is scaled back to the provided maximum length.

      - *

      If the vector's length is shorter than the provided value, the vector - * is not changed.

      - *

      WARNING: This is a potentially costly operation.

      - * @param v The vector to truncate. - * @param maxLength The maximum allowed length of the resulting vector. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector3 truncateLength(Vector3 v, float maxLength, Vector3 out) - { - return truncateLength(v.x, v.y, v.z, maxLength, out); - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/Line2.java b/critterai/legacy/util-java/src/org/critterai/math/geom/Line2.java deleted file mode 100644 index b5ed66ec..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/Line2.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.critterai.math.MathUtil; -import org.critterai.math.Vector2; - -/** - * Provides operations related to 2-dimensional lines and line segments. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, divide by zero checks only when needed by the algorithm, etc.

      - *

      Static operations are thread safe.

      - */ -public final class Line2 -{ - - private Line2() { } - - /** - * Indicates whether or not line AB intersects line BC. - * @param ax The x-value for point A on line AB. - * @param ay The y-value for point A on line AB. - * @param bx The x-value for point B on line AB. - * @param by The y-value for point B on line AB. - * @param cx The x-value for point C on line CD. - * @param cy The y-value for point C on line CD. - * @param dx The x-value for point D on line CD. - * @param dy The y-value for point D on line CD. - * @return TRUE if the two lines are either collinear or intersect at one point. - * Otherwise FALSE. - */ - public static boolean linesIntersect(int ax, int ay - , int bx, int by - , int cx, int cy - , int dx, int dy) - { - int numerator = ((ay - cy) * (dx - cx)) - ((ax - cx) * (dy - cy)); - int denominator = ((bx - ax) * (dy - cy)) - ((by - ay) * (dx - cx)); - if (denominator == 0 && numerator != 0) - // Lines are parallel. - return false; - // Lines are collinear or intersect at a single point. - return true; - } - - /** - * Indicates whether or not line AB intersects line BC. - * @param ax The x-value for point A on line AB. - * @param ay The y-value for point A on line AB. - * @param bx The x-value for point B on line AB. - * @param by The y-value for point B on line AB. - * @param cx The x-value for point C on line CD. - * @param cy The y-value for point C on line CD. - * @param dx The x-value for point D on line CD. - * @param dy The y-value for point D on line CD. - * @return TRUE if the two lines are either collinear or intersect at one point. - * Otherwise FALSE. - */ - public static boolean linesIntersect(float ax, float ay - , float bx, float by - , float cx, float cy - , float dx, float dy) - { - float numerator = ((ay - cy) * (dx - cx)) - ((ax - cx) * (dy - cy)); - float denominator = ((bx - ax) * (dy - cy)) - ((by - ay) * (dx - cx)); - if (denominator == 0 && numerator != 0) - // Lines are parallel. - return false; - // Lines are collinear or intersect at a single point. - return true; - } - - /** - * Returns the distance squared from point P to line segment AB. - * @param px The x-value of point P. - * @param py The y-value of point P. - * @param ax The x-value of point A of line segment AB. - * @param ay The y-value of point A of line segment AB. - * @param bx The x-value of point B of line segment AB. - * @param by The y-value of point B of line segment AB. - * @return The distance squared from point B to line segment AB. - */ - public static float getPointSegmentDistanceSq(float px, float py - , float ax, float ay - , float bx, float by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line AB that is - * closest to P and then calculate the distance between P and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = deltaABx * deltaABx + deltaABy * deltaABy; - - if (segmentABLengthSq < MathUtil.EPSILON_STD) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = (deltaAPx * deltaABx + deltaAPy * deltaABy) / segmentABLengthSq; - - if (u < 0) - // Closest point on line AB is outside outside segment AB and closer to A. - // So return distanceSq from P to A. - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - else if (u > 1) - // Closest point on line AB is outside segment AB and closer to B. - // So return distanceSq from P to B. - return (px - bx)*(px - bx) + (py - by)*(py - by); - - // Closest point on lineAB is inside segment AB. So find the exact point on AB - // and calculate the distanceSq from it to P. - - // The calculation in parenthesis is the location of the point on the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - /** - * Returns the distance squared from point P to line AB. - * @param px The x-value of point P. - * @param py The y-value of point P. - * @param ax The x-value of point A of line AB. - * @param ay The y-value of point A of line AB. - * @param bx The x-value of point B of line AB. - * @param by The y-value of point B of line AB. - * @return The distance squared from point B to line AB. - */ - public static float getPointLineDistanceSq(float px, float py, float ax, float ay, float bx, float by) - { - - /* - * Reference: http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/ - * - * The goal of the algorithm is to find the point on line AB that is - * closest to P and then calculate the distance between P and that point. - */ - - final float deltaABx = bx - ax; - final float deltaABy = by - ay; - final float deltaAPx = px - ax; - final float deltaAPy = py - ay; - - final float segmentABLengthSq = deltaABx * deltaABx + deltaABy * deltaABy; - - if (segmentABLengthSq < MathUtil.EPSILON_STD) - // AB is not a line segment. So just return - // distanceSq from P to A - return deltaAPx * deltaAPx + deltaAPy * deltaAPy; - - final float u = (deltaAPx * deltaABx + deltaAPy * deltaABy) / segmentABLengthSq; - - // The calculation in parenthesis is the location of the point on the line segment. - final float deltaX = (ax + u * deltaABx) - px; - final float deltaY = (ay + u * deltaABy) - py; - - return deltaX*deltaX + deltaY*deltaY; - } - - /** - * Returns the normalized vector that is perpendicular to line AB, or a zero - * length vector if points A and B do not form a line. - *

      The direction of the vector will be to the right when viewed from point A to point B - * along the line.

      - *

      WARNING: This is an expensive operation.

      - * @param ax The x-value of point A on line AB. - * @param ay The y-value of point A on line AB. - * @param bx The x-value of point B on line AB. - * @param by The y-value of point B on line AB. - * @param out The vector to load the result into. - * @return A reference to the out argument. - */ - public static Vector2 getNormalAB(float ax, float ay - , float bx, float by - , Vector2 out) - { - if (ax == bx && ay == by) - { - // Points do not form a line. - out.set(0, 0); - } - else - { - Vector2.getDirectionAB(ax, ay, bx, by, out); - out.set(out.y, -out.x); - } - return out; - } - - /** - * Determines the relationship between lines AB and CD. - *

      While this check is technically inclusive of the segment end points, floating point - * errors can result in end point intersection being missed. If this matters, - * a {@link Vector2#sloppyEquals(float, float, float)} or similar test of the intersection point can - * be performed to check for this issue.

      - * @param ax The x-value for point A on line AB. - * @param ay The y-value for point A on line AB. - * @param bx The x-value for point B on line AB. - * @param by The y-value for point B on line AB. - * @param cx The x-value for point C on line CD. - * @param cy The y-value for point C on line CD. - * @param dx The x-value for point D on line CD. - * @param dy The y-value for point D on line CD. - * @param outIntersectionPoint If provided and the lines intersect at - * a single point, the vector will be updated with the point of intersection. - * (This argument may be null.) - * @return The relationship between lines AB and CD. - */ - public static LineRelType getRelationship(float ax, float ay - , float bx, float by - , float cx, float cy - , float dx, float dy - , Vector2 outIntersectionPoint) - { - - float deltaAxBx = bx - ax; - float deltaAyBy = by - ay; - - float deltaCxDx = dx - cx; - float deltaCyDy = dy - cy; - - float deltaCyAy = ay - cy; - float deltaCxAx = ax - cx; - - float numerator = (deltaCyAy * deltaCxDx) - (deltaCxAx * deltaCyDy); - float denominator = (deltaAxBx * deltaCyDy) - (deltaAyBy * deltaCxDx); - - // Exit early if the lines do not intersect at a single point. - if (denominator == 0) - { - if (numerator == 0) - return LineRelType.COLLINEAR; - return LineRelType.PARALLEL; - } - - // Lines definitely intersect at a single point. - - float factorAB = numerator / denominator; - float factorCD = ((deltaCyAy * deltaAxBx) - (deltaCxAx * deltaAyBy)) / denominator; - - if (outIntersectionPoint != null) - outIntersectionPoint.set(ax + (factorAB * deltaAxBx) - , ay + (factorAB * deltaAyBy)); - - // Determine the type of intersection - if ((factorAB >= 0.0f) && (factorAB <= 1.0f) && (factorCD >= 0.0f) && (factorCD <= 1.0f)) - { - return LineRelType.SEGMENTS_INTERSECT; - } - else if ((factorCD >= 0.0f) && (factorCD <= 1.0f)) - { - return LineRelType.ALINE_CROSSES_BSEG; - } - else if ((factorAB >= 0.0f) && (factorAB <= 1.0f)) - { - return LineRelType.BLINE_CROSSES_ASEG; - } - - return LineRelType.LINES_INTERSECT; - - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/LineRelType.java b/critterai/legacy/util-java/src/org/critterai/math/geom/LineRelType.java deleted file mode 100644 index 5ac03744..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/LineRelType.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -/** - * Specifies the relationship between two lines. - */ -public enum LineRelType -{ - - /** - * Lines are parallel and overlap each other. (Share all points.) - */ - COLLINEAR, - - /** - * Lines intersect, but their segments do not. - */ - LINES_INTERSECT, - - /** - * Line segments intersect each other. - */ - SEGMENTS_INTERSECT, - - /** - * Line segment B is crossed by line A. - */ - ALINE_CROSSES_BSEG, - - /** - * Line segment A is crossed by line B. - */ - BLINE_CROSSES_ASEG, - - /** - * Lines are parallel and do NOT overlap each other. (Share no points.) - */ - PARALLEL, - - /** - * Lines do not intersect, but are not parallel. - * (Share no points. Only applicable to 3-dimensional lines.) - */ - SKEW -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/PointLineRelType.java b/critterai/legacy/util-java/src/org/critterai/math/geom/PointLineRelType.java deleted file mode 100644 index 928392cb..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/PointLineRelType.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -/** - * Specifies the position relationship between a point and a line. - */ -public enum PointLineRelType -{ - /** - * The point is on, or very near, the line - */ - ON_LINE, - - /** - * The test point is to the left when looking from point A toward B on the line. - */ - LEFT_SIDE, - - /** - * The test point is to the right when looking from point A toward B on the line. - */ - RIGHT_SIDE -} \ No newline at end of file diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/Polygon3.java b/critterai/legacy/util-java/src/org/critterai/math/geom/Polygon3.java deleted file mode 100644 index 4a83d046..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/Polygon3.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.critterai.math.MathUtil; -import org.critterai.math.Vector3; - - -/** - * Provides operations related to polygons defined in 3-dimensional space with - * coplanar vertices. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No null checks, divide by zero checks only when needed by the algorithm, etc.

      - *

      Static operations are thread safe.

      - */ -public class Polygon3 -{ - - private Polygon3() { } - - /** - * Determines whether a polygon is convex. - *

      Behavior is undefined if vertices are not coplanar.

      - *

      If the area of the triangle formed by the first three vertices of the polygon is too small - * to detect on both the (x, z) and (x, y) planes, then this operation may improperly return - * FALSE.

      - * @param verts An array of vertices which contains a representation of polygons with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * Wrap direction does not matter. - * @param startVertIndex The index of the first vertex in the polygon. - * @param vertCount The number of vertices in the polygon. - * @return TRUE if the polygon is convex. Otherwise FALSE. - */ - public static boolean isConvex(float[] verts, int startVertIndex, int vertCount) - { - - if (vertCount < 3) - return false; - if (vertCount == 3) - // It is a triangle, so it must be convex. - return true; - - // At this point we know that the polygon has at least 4 sides. - - /* - * Process will be to step through the sides, 3 vertices at a time. - * As long the signed area for the triangles formed by each set of - * vertices is the same (negative or positive), then the polygon is convex. - * - * Using a shortcut by projecting onto the (x, z) or (x, y) plane for all calculations. - * For a proper polygon, if the 2D projection is convex, the 3D polygon is convex. - * - * There is one special case: A polygon that is vertical. I.e. 2D on the (x, z) plane. - * This is detected during the first test. - */ - - int offset = 2; // Start by projecting to the (x, z) plane. - - int pStartVert = startVertIndex*3; - - float initDirection = Triangle2.getSignedAreaX2(verts[pStartVert] - , verts[pStartVert+2] - , verts[pStartVert+3] - , verts[pStartVert+5] - , verts[pStartVert+6] - , verts[pStartVert+8]); - - if (initDirection > -2 * MathUtil.EPSILON_STD - && initDirection < 2 * MathUtil.EPSILON_STD) - { - // The polygon is on or very close to the vertical plane. Switch to projecting on the (x, y) plane. - offset = 1; - initDirection = Triangle2.getSignedAreaX2(verts[pStartVert] - , verts[pStartVert+1] - , verts[pStartVert+3] - , verts[pStartVert+4] - , verts[pStartVert+6] - , verts[pStartVert+7]); - // Dev note: This is meant to be a strict zero test. - if (initDirection == 0) - // Some sort of problem. Should very rarely ever get here. - return false; - } - - int vertLength = (startVertIndex+vertCount)*3; - for (int vertAPointer = pStartVert+3; vertAPointer < vertLength; vertAPointer += 3) - { - int vertBPointer = vertAPointer+3; - if (vertBPointer >= vertLength) - // Wrap it back to the start. - vertBPointer = pStartVert; - int vertCPointer = vertBPointer+3; - if (vertCPointer >= vertLength) - // Wrap it back to the start. - vertCPointer = pStartVert; - float direction = Triangle2.getSignedAreaX2( - verts[vertAPointer] - , verts[vertAPointer+offset] - , verts[vertBPointer] - , verts[vertBPointer+offset] - , verts[vertCPointer] - , verts[vertCPointer+offset]); - if (!(initDirection < 0 && direction < 0) && !(initDirection > 0 && direction > 0)) - // The sign of the current direction is not the same as the sign of the - // initial direction. Can't be convex. - return false; - } - - return true; - - } - - /** - * Returns the centroid of a convex polygon. - *

      Behavior is undefined if the polygon is not convex.

      - *

      Behavior is undefined if the vector being overwritten in the out array - * is a vertex in the polygon. (Can only happen if the verts and out arrays - * are the same object.)

      - * @param verts An array of vertices which contains a representation of a polygon with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * Wrap direction does not matter. - * @param startVertIndex The index of the first vertex in the polygon. - * @param vertCount The number of vertices in the polygon. - * @param out The array to store the result in. - * @param outVectorIndex The vector index in the out array to store the result in. (The stride - * is expected to be three. So the insertion point will be outVectorIndex*3.) - * @return A reference to the out argument. - * @see Centroid - */ - public static float[] getCentroid(float[] verts - , int startVertIndex - , int vertCount - , float[] out - , int outVectorIndex) - { - // Reference: http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - int vertLength = (startVertIndex+vertCount)*3; - int pOut = outVectorIndex*3; - out[pOut] = 0; - out[pOut+1] = 0; - out[pOut+2] = 0; - for (int pVert = startVertIndex*3; pVert < vertLength; pVert += 3) - { - out[pOut] += verts[pVert]; - out[pOut+1] += verts[pVert+1]; - out[pOut+2] += verts[pVert+2]; - } - - out[pOut] /= vertCount; - out[pOut+1] /= vertCount; - out[pOut+2] /= vertCount; - - return out; - } - - /** - * Returns the centroid of a polygon. - * @param verts An array of vertices which contains a representation of a polygon with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * Wrap direction does not matter. - *

      Behavior is undefined if the polygon is not convex.

      - * @param startVertIndex The index of the first vertex in the polygon. - * @param vertCount The number of vertices in the polygon. - * @param out The vector to store the result in. - * @return A reference to the out argument. - * @see Centroid - */ - public static Vector3 getCentroid(float[] verts - , int startVertIndex - , int vertCount - , Vector3 out) - { - // Reference: http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - out.set(0, 0, 0); - int vertLength = (startVertIndex+vertCount)*3; - for (int pVert = startVertIndex*3; pVert < vertLength; pVert += 3) - { - out.x += verts[pVert]; - out.y += verts[pVert+1]; - out.z += verts[pVert+2]; - } - - out.x /= vertCount; - out.y /= vertCount; - out.z /= vertCount; - - return out; - - } - - /** - * Returns the centroid of a polygon. - * @param out The vector to store the result in. - * @param verts An list of vertices which represent a polygon with an - * arbitrary number of sides in the form (x1, y1, z1, x2, y2, z2, ..., xn, yn, zn). - * @return A reference to the out argument. - * @see Centroid - */ - public static Vector3 getCentroid(Vector3 out, float...verts) - { - // Reference: http://en.wikipedia.org/wiki/Centroid#Of_a_finite_set_of_points - - out.set(0, 0, 0); - - int vertCount = 0; - for (int pVert =0; pVert < verts.length; pVert += 3) - { - out.x += verts[pVert]; - out.y += verts[pVert+1]; - out.z += verts[pVert+2]; - vertCount++; - } - - out.x /= vertCount; - out.y /= vertCount; - out.z /= vertCount; - - return out; - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/Rectangle2.java b/critterai/legacy/util-java/src/org/critterai/math/geom/Rectangle2.java deleted file mode 100644 index 8c0caa47..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/Rectangle2.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - - -/** - * Provides operations related to 2-dimensional rectangles. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No checks are performed to ensure that maximums are greater than minimums.

      - *

      Static operations are thread safe.

      - */ -public class Rectangle2 -{ - - private Rectangle2() { } - - /** - * Indicates whether or not a point is contained within an axis-aligned rectangle. - * The test is inclusive of the edges of the rectangle. I.e. If the point lies - * on the edge of the rectangle, then it is contained by the rectangle. - * @param minX The minimum x-axis bounds of the rectangle. - * @param minY The minimum y-axis bounds of the rectangle. - * @param maxX The maximum x-axis bounds of the rectangle. - * @param maxY The maximum y-axis bounds of the rectangle. - * @param x The x-value of the point (x, y) to test. - * @param y The y-value of the point (x, y) to test. - * @return TRUE if the point lies within the rectangle. Otherwise FALSE. - */ - public static boolean contains(float minX, float minY, float maxX, float maxY, float x, float y) - { - return !(x < minX || y < minY || x > maxX || y > maxY); - } - - /** - * Indicates whether or not an axis-alighed rectangle (B) is contained within another - * axis-aligned rectangle (A). - * The test is inclusive of the edges of the rectangles. - * @param minXA The minimum x-axis bounds of rectangle A. - * @param minYA The minimum y-axis bounds of rectangle A. - * @param maxXA The maximum x-axis bounds of rectangle A. - * @param maxYA The maximum y-axis bounds of rectangle A. - * @param minXB The minimum x-axis bounds of rectangle B. - * @param minYB The minimum y-axis bounds of rectangle B. - * @param maxXB The maximum x-axis bounds of rectangle B. - * @param maxYB The maximum y-axis bounds of rectangle B. - * @return TRUE if rectangle B is fully contained by rectangle A. Otherwise FALSE. - */ - public static boolean contains(float minXA, float minYA, float maxXA, float maxYA - , float minXB, float minYB, float maxXB, float maxYB) - { - return (minXB >= minXA && minYB >= minYA && maxXB <= maxXA && maxYB <= maxYA); - } - - /** - * Indicates whether or not two axis-aligned rectangles intersect. - * The test is inclusive of the edges of the rectangles. - * @param minAX The minimum x-axis bounds of rectangle A. - * @param minAY The minimum y-axis bounds of rectangle A. - * @param maxAX The maximum x-axis bounds of rectangle A. - * @param maxAY The maximum y-axis bounds of rectangle A. - * @param minBX The minimum x-axis bounds of rectangle B. - * @param minBY The minimum y-axis bounds of rectangle B. - * @param maxBX The maximum x-axis bounds of rectangle B. - * @param maxBY The maximum y-axis bounds of rectangle B. - * @return TRUE if the two rectangles intersect in any manner. Otherwise FALSE. - */ - public static boolean intersectsAABB(float minAX, float minAY, float maxAX, float maxAY - , float minBX, float minBY, float maxBX, float maxBY) - { - return !(maxBX < minAX || maxAX < minBX || maxBY < minAY || maxAY < minBY ); - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/Triangle2.java b/critterai/legacy/util-java/src/org/critterai/math/geom/Triangle2.java deleted file mode 100644 index b7a8d0ef..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/Triangle2.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.critterai.math.Vector2.dot; - -/** - * Provides operations related to 2-dimensional triangles. - *

      This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No checks are performed to ensure the arguments represent a valid triangle.

      - *

      Static operations are thread safe.

      - */ -public class Triangle2 -{ - - /** - * Returns TRUE if the point (px, py) is contained by the triangle. - *

      The test is inclusive. So points on the vertices or edges - * of the triangle are considered to be contained by the triangle.

      - * @param px The x-value for the point to test. (px, py) - * @param py The y-value for the poitn to test. (px, py) - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @return TRUE if the point (x, y) is contained by the triangle ABC. - */ - public static boolean contains(float px, float py - , float ax, float ay - , float bx, float by - , float cx, float cy) - { - float dirABx = bx - ax; - float dirABy = by - ay; - float dirACx = cx - ax; - float dirACy = cy - ay; - float dirAPx = px - ax; - float dirAPy = py - ay; - - float dotABAB = dot(dirABx, dirABy, dirABx, dirABy); - float dotACAB = dot(dirACx, dirACy, dirABx, dirABy); - float dotACAC = dot(dirACx, dirACy, dirACx, dirACy); - float dotACAP = dot(dirACx,dirACy, dirAPx, dirAPy); - float dotABAP = dot(dirABx, dirABy, dirAPx, dirAPy); - - float invDenom = 1 / (dotACAC * dotABAB - dotACAB * dotACAB); - float u = (dotABAB * dotACAP - dotACAB * dotABAP) * invDenom; - float v = (dotACAC * dotABAP - dotACAB * dotACAP) * invDenom; - - // Altered this slightly from the reference so that points on the vertices and edges - // are considered to be inside the triangle. - return (u >= 0) && (v >= 0) && (u + v <= 1); - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle ABC. - *

      A positive value indicates:

      - *
        - *
      • Counterclockwise wrapping of the vertices.
      • - *
      • Vertex B lies to the right of line AC, looking from A toward C.
      • - *
      - *

      A negative value indicates:

      - *
        - *
      • Clockwise wrapping of the vertices.
      • - *
      • Vertex B lies to the left of line AC, looking from A toward C.
      • - *
      - *

      A value of zero indicates that all points are collinear or represent the same point.

      - *

      This is a low cost operation.

      - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @return The absolute value of the returned value is two times the area of the - * triangle ABC. - */ - public static float getSignedAreaX2(float ax, float ay, float bx, float by, float cx, float cy) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - // http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - - /** - * The absolute value of the returned value is two times the area of the - * triangle ABC. - *

      A positive value indicates:

      - *
        - *
      • Counterclockwise wrapping of the vertices.
      • - *
      • Vertex B lies to the right of line AC, looking from A toward C.
      • - *
      - *

      A negative value indicates:

      - *
        - *
      • Clockwise wrapping of the vertices.
      • - *
      • Vertex B lies to the left of line AC, looking from A toward C.
      • - *
          - *

          A value of zero indicates that all points are collinear or represent the same point.

          - *

          This is a low cost operation.

          - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @return The absolute value of the returned value is two times the area of the - * triangle ABC. - */ - public static int getSignedAreaX2(int ax, int ay, int bx, int by, int cx, int cy) - { - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - // http://mathworld.wolfram.com/TriangleArea.html (Search for "signed".) - return (bx - ax) * (cy - ay) - (cx - ax) * (by - ay); - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/Triangle3.java b/critterai/legacy/util-java/src/org/critterai/math/geom/Triangle3.java deleted file mode 100644 index 5b677c05..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/Triangle3.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.critterai.math.Vector3; - -/** - * Provides operations related to triangles in 3-dimensional space. - *

          This class is optimized for speed. To support this priority, no argument validation is - * performed. E.g. No checks are performed to ensure the arguments represent a valid triangle, - * no null checks of arguments, etc.

          - *

          Static operations are thread safe.

          - */ -public final class Triangle3 -{ - - /** - * Returns the area of the triangle ABC. - *

          WARNING: This is an costly operation. If the value is only needed for comparison with other - * triangles, then use - * {@link #getAreaComp(float, float, float, float, float, float, float, float, float) getAreaComp()} - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param az The z-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param bz The z-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @param cz The z-value for vertex C in triangle ABC - * @return The area of the triangle ABC. - */ - public static float getArea( - float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz) - { - return (float)(Math.sqrt(getAreaComp(ax, ay, az, bx, by, bz, cx, cy, cz)) / 2); - } - - /** - * Returns a value suitable for comparing the relative size of two triangles. - * E.g. Is triangleA larger than triangleB. - *

          The value returned by this operation can be converted to area as follows: - * Area = Math.sqrt(value)/2

          - *

          Useful for quickly comparing the size of triangles.

          - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param az The z-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param bz The z-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @param cz The z-value for vertex C in triangle ABC - * @return A value suitable for comparing the relative size of two triangles. - */ - public static float getAreaComp( - float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz) - { - - // References: - // http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm#Modern%20Triangles - - // Get directional vectors. - // A -> B - float ux = bx - ax; - float uy = by - ay; - float uz = bz - az; - // A -> C - float vx = cx - ax; - float vy = cy - ay; - float vz = cz - az; - - // Cross product. - float nx = uy * vz - uz * vy; - float ny = -ux * vz + uz * vx; - float nz = ux * vy - uy * vx; - - return Vector3.getLengthSq(nx, ny, nz); - - } - - /** - * Returns the normal for the triangle. (The vector perpendicular to - * the triangle's plane.) The direction of the normal is determined by - * the right-handed rule. - *

          WARNING: This is a costly operation.

          - * @param ax The x-value for vertex A in triangle ABC - * @param ay The y-value for vertex A in triangle ABC - * @param az The z-value for vertex A in triangle ABC - * @param bx The x-value for vertex B in triangle ABC - * @param by The y-value for vertex B in triangle ABC - * @param bz The z-value for vertex B in triangle ABC - * @param cx The x-value for vertex C in triangle ABC - * @param cy The y-value for vertex C in triangle ABC - * @param cz The z-value for vertex C in triangle ABC - * @param out The vector to store the result in. - * @return A reference to the out argument. - */ - public static Vector3 getNormal(float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz - , Vector3 out) - { - - // Reference: http://en.wikipedia.org/wiki/Surface_normal#Calculating_a_surface_normal - // N = (B - A) x (C - A) with the final result normalized. - - Vector3.cross(bx - ax - , by - ay - , bz - az - , cx - ax - , cy - ay - , cz - az - , out); - out.normalize(); - - return out; - - } - - /** - * Returns the normal for the triangle. (The vector perpendicular to - * the triangle's plane.) The direction of the normal is determined by - * the right-handed rule. - *

          WARNING: This is a costly operation.

          - * @param vertices An array of vertices which contains a representation of triangles in the - * form (ax, ay, az, bx, by, bz, cx, cy, cz). The wrap direction is expected to be - * clockwise. - * @param startVertIndex The index of the first vertex in the triangle. - * @param out The vector to store the result in. - * @return A reference to the out argument. - */ - public static Vector3 getNormal(float[] vertices, int startVertIndex, Vector3 out) - { - - int pStartVert = startVertIndex*3; - return getNormal(vertices[pStartVert], vertices[pStartVert+1], vertices[pStartVert+2] - , vertices[pStartVert+3], vertices[pStartVert+4], vertices[pStartVert+5] - , vertices[pStartVert+6], vertices[pStartVert+7], vertices[pStartVert+8] - , out); - } - -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/WrapDirection.java b/critterai/legacy/util-java/src/org/critterai/math/geom/WrapDirection.java deleted file mode 100644 index 41fa6d88..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/WrapDirection.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -/** - * Indicates the vertex wrap direction of a polygon. - *

          Static operations are thread safe.

          - */ -public enum WrapDirection -{ - /** - * Polygon vertex wrap direction is clockwise. - */ - CLOCKWISE, - - /** - * Polygon vertex wrap direction is counter-clockwise. - */ - COUNTERCLOCKWISE, - - /** - * The wrap direction hasn't been determined or could not be determined, depending - * on the use case. - */ - UNKNOWN; - - /** - * Returns the opposite of the provided direction. - * NULL and {@link #UNKNOWN} will always return {@link #UNKNOWN}. - * @param direction The direction to invert. - * @return The opposite of the provided direction. - */ - public static WrapDirection getInverted(WrapDirection direction) - { - if (direction == CLOCKWISE) - return COUNTERCLOCKWISE; - if (direction == COUNTERCLOCKWISE) - return CLOCKWISE; - return UNKNOWN; - } -} diff --git a/critterai/legacy/util-java/src/org/critterai/math/geom/package-info.java b/critterai/legacy/util-java/src/org/critterai/math/geom/package-info.java deleted file mode 100644 index 1356106e..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/geom/package-info.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * Provides various geometry related classes and operations. - *

          A high priority is given to performance. In order to achieve the performance goal, the - * following standards have been implemented:

          - *
            - *
          • There is no validation of arguments outside of constructors. - * For example, the - * {@link org.critterai.math.geom.Line2#getRelationship(float, float, float, float, float, float, float, float, org.critterai.math.Vector2)} - * operation does not validate that the {@link org.critterai.math.Vector2} argument is non-null. - * If the argument is null a runtime error will occur.
          • - *
          • All static operations that return an object require the object be passed in as an "out" argument. - * The out object is updated with the result and its reference returned. This reduces the construction - * costs by allowing clients of the class to re-use the out objects for multiple calls.

            - *
          • - *
          - */ -package org.critterai.math.geom; \ No newline at end of file diff --git a/critterai/legacy/util-java/src/org/critterai/math/package-info.java b/critterai/legacy/util-java/src/org/critterai/math/package-info.java deleted file mode 100644 index 3eb900e7..00000000 --- a/critterai/legacy/util-java/src/org/critterai/math/package-info.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -/** - * Provides various math related classes and operations. - *

          A high priority is given to performance. In order to achieve the performance goal, the - * following standards have been implemented:

          - *
            - *
          • There is no validation of arguments outside of constructors. - * For example, the {@link org.critterai.math.Vector2#add(float, float, float, Vector2)} - * operation does not validate that the {@link org.critterai.math.Vector2} argument is non-null. - * If the argument is null a runtime error will occur.
          • - *
          • All static operations that return an object require the object be passed in as an "out" argument. - * The out object is updated with the result and its reference returned. This reduces the construction - * costs by allowing clients of the class to re-use the out objects for multiple calls.

            - *
          • - *
          - */ -package org.critterai.math; \ No newline at end of file diff --git a/critterai/legacy/util-java/test/org/critterai/math/AllTests.java b/critterai/legacy/util-java/test/org/critterai/math/AllTests.java deleted file mode 100644 index 0a293d8f..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/AllTests.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * Unit tests for all classes in the org.critterai.math package. - */ -@RunWith(Suite.class) -@SuiteClasses( {MathUtilTests.class - , Vector2Tests.class - , Vector3Tests.class}) -public class AllTests { } diff --git a/critterai/legacy/util-java/test/org/critterai/math/MathUtilTests.java b/critterai/legacy/util-java/test/org/critterai/math/MathUtilTests.java deleted file mode 100644 index f986b948..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/MathUtilTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.junit.Assert.*; -import static org.critterai.math.MathUtil.*; - -import org.critterai.math.MathUtil; -import org.junit.Test; - -/** - * Unit tests for the {@link MathUtil} class. - */ -public class MathUtilTests { - - @Test - public void testSloppyEquals() - { - float tol = 0.1f; - assertTrue(sloppyEquals(5, 5.09f, tol)); - assertTrue(sloppyEquals(5, 4.91f, tol)); - assertTrue(sloppyEquals(5, 5.10f, tol)); - assertTrue(sloppyEquals(5, 4.90f, tol)); - assertFalse(sloppyEquals(5, 5.101f, tol)); - assertFalse(sloppyEquals(5, 4.899f, tol)); - } - - @Test - public void testClampToPositiveNonZero() - { - assertTrue(clampToPositiveNonZero(0.1f) == 0.1f); - assertTrue(clampToPositiveNonZero(Float.MIN_VALUE) == Float.MIN_VALUE); - assertTrue(clampToPositiveNonZero(0) == Float.MIN_VALUE); - assertTrue(clampToPositiveNonZero(-Float.MIN_VALUE) == Float.MIN_VALUE); - } - - @Test - public void testClampFloat() - { - assertTrue(clamp(5.0f, 4.99f, 5.01f) == 5.0f); - assertTrue(clamp(4.99f, 4.99f, 5.01f) == 4.99f); - assertTrue(clamp(4.9899f, 4.99f, 5.01f) == 4.99f); - assertTrue(clamp(5.01f, 4.99f, 5.01f) == 5.01f); - assertTrue(clamp(5.01001f, 4.99f, 5.01f) == 5.01f); - } - - @Test - public void testClampInt() - { - assertTrue(clamp(5, 4, 6) == 5); - assertTrue(clamp(4, 4, 6) == 4); - assertTrue(clamp(3, 4, 6) == 4); - assertTrue(clamp(6, 4, 6) == 6); - assertTrue(clamp(7, 4, 6) == 6); - } - - @Test - public void testClampShort() - { - assertTrue(clamp((short)5, (short)4, (short)6) == 5); - assertTrue(clamp((short)4, (short)4, (short)6) == 4); - assertTrue(clamp((short)3, (short)4, (short)6) == 4); - assertTrue(clamp((short)6, (short)4, (short)6) == 6); - assertTrue(clamp((short)7, (short)4, (short)6) == 6); - } - - @Test - public void testMax() - { - assertTrue(max(2) == 2); - assertTrue(max(-1, 0, 1, 2) == 2); - assertTrue(max(-1, 2, -1, 0) == 2); - } - - @Test - public void testMin() - { - assertTrue(min(2) == 2); - assertTrue(min(-1, 0, 1, 2) == -1); - assertTrue(min(2, 2, -1, 0) == -1); - } - -} diff --git a/critterai/legacy/util-java/test/org/critterai/math/Vector2Tests.java b/critterai/legacy/util-java/test/org/critterai/math/Vector2Tests.java deleted file mode 100644 index 5e7191c5..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/Vector2Tests.java +++ /dev/null @@ -1,713 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.Vector2.*; -import static org.junit.Assert.*; - -import static org.critterai.math.MathUtil.*; -import org.critterai.math.Vector2; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Vector2} class. - */ -public class Vector2Tests { - - public static final float AX = 1.5f; - public static final float AY = 8.0f; - public static final float BX = -17.112f; - public static final float BY = 77.5f; - - private Vector2 mA1; - private Vector2 mA2; - private Vector2 mB1; - private Vector2 mC1; - - @Before - public void setUp() - throws Exception - { - mA1 = new Vector2(AX, AY); - mA2 = new Vector2(AX, AY); - mB1 = new Vector2(BX, BY); - mC1 = new Vector2(AY, AX); - } - - @Test - public void testConstructorDefault() - { - Vector2 v = new Vector2(); - assertTrue(v.x == 0 && v.y == 0); - } - - @Test - public void testConstructorFloatFloat() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(v.x == AX && v.y == AY); - } - - @Test - public void testDotFloat() - { - float result = mA1.dot(BX, BY); - float expected = (AX * BX) + (AY * BY); - assertTrue(result == expected); - } - - @Test - public void testDotVector2() - { - float result = mA1.dot(mB1); - float expected = (AX * BX) + (AY * BY); - assertTrue(result == expected); - } - - @Test - public void testEqualsFloat() - { - assertTrue(mA1.equals(AX, AY)); - assertFalse(mA1.equals(AY, AX)); - } - - @Test - public void testEqualsObject() - { - assertTrue(mA1.equals((Object)mA2)); - assertFalse(mA1.equals((Object)mB1)); - assertFalse(mA1.equals((Object)mC1)); - } - - @Test - public void testEqualsVector2() - { - assertTrue(mA1.equals(mA2)); - assertFalse(mA1.equals(mB1)); - assertFalse(mA1.equals(mC1)); - } - - @Test - public void testFields() - { - assertTrue(mA1.x == AX); - assertTrue(mB1.x == BX); - assertTrue(mA1.y == AY); - assertTrue(mB1.y == BY); - } - - @Test - public void testGetX() - { - assertTrue(mA1.getX() == AX); - } - - @Test - public void testGetY() - { - assertTrue(mA1.getY() == AY); - } - - @Test - public void testHashCode() - { - assertTrue(mA1.hashCode() == mA2.hashCode()); - assertTrue(mA1.hashCode() != mB1.hashCode()); - assertTrue(mA1.hashCode() != mC1.hashCode()); - } - - @Test - public void testIsZeroLength() - { - assertTrue(new Vector2().isZeroLength()); - assertFalse(mA1.isZeroLength()); - } - - @Test - public void testLengthSq() - { - float len = (AX * AX) + (AY * AY); - assertTrue(mA1.lengthSq() == len); - } - - @Test - public void testMutatorAddFloat() - { - assertTrue(mA1.add(BX, BY) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - } - - @Test - public void testMutatorAddVector2() - { - assertTrue(mA1.add(mB1) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - } - - @Test - public void testMutatorDivide() - { - assertTrue(mA1.divide(5) == mA1); - assertTrue(mA1.x == AX / 5); - assertTrue(mA1.y == AY / 5); - } - - @Test - public void testMutatorMultiply() - { - assertTrue(mA1.multiply(5) == mA1); - assertTrue(mA1.x == AX * 5); - assertTrue(mA1.y == AY * 5); - } - - @Test - public void testMutatorNormalize() - { - float len = (float) Math.sqrt((AX * AX) + (AY * AY)); - float expectedX = AX / len; - float expectedY = AY / len; - - assertTrue(mA1.normalize() == mA1); - assertTrue(mA1.x == expectedX); - assertTrue(mA1.y == expectedY); - } - - @Test - public void testMutatorReverse() - { - assertTrue(mA1.reverse() == mA1); - assertTrue(mA1.x == -AX); - assertTrue(mA1.y == -AY); - } - - @Test - public void testMutatorRotate() - { - // Only a simple test. Rotate 90 degrees counter clockwise. - Vector2 u = new Vector2(1, 0); - assertTrue(u.rotate((float)(Math.PI / 2)) == u); - assertTrue(u.x > -0.001 - && u.x < 0.001 - && u.y > 0.999 - && u.y < 1.001); - } - - @Test - public void testMutatorScaleTo() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.scaleTo(15.0f) == mA1); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - mA1 = new Vector2(AX, AY).scaleTo(0); - assertTrue(mA1.x == 0 && mA1.y == 0); - } - - @Test - public void testMutatorSubtractFloat() - { - assertTrue(mA1.subtract(BX, BY) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - } - - @Test - public void testMutatorSubtractVector() - { - assertTrue(mA1.subtract(mB1) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - } - - @Test - public void testMutatorTruncateLength() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.truncateLength(15.0f) == mA1); - assertTrue(mA1.x == AX && mA1.y == AY); - - mA1 = new Vector2(AX, AY).truncateLength(5); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - mA1 = new Vector2(AX, AY).truncateLength(0); - assertTrue(mA1.x == 0 && mA1.y == 0); - } - - @Test - public void testMutatorXValue() - { - mA1.setX(BX); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == AY); - } - - @Test - public void testMutatorYValue() - { - mA1.setY(BY); - assertTrue(mA1.x == AX); - assertTrue(mA1.y == BY); - } - - @Test - public void testSetValueFloat() - { - assertTrue(mA1 == mA1.set(BX, BY)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - } - - @Test - public void testSetValueVector2() - { - assertTrue(mA1 == mA1.set(mB1)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - } - - @Test - public void testSloppyEqualsFloat() - { - assertTrue(mA1.sloppyEquals(AX, AY, 0.0f)); - - mA1 = new Vector2(AX + 0.019f, AY); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - - mA1 = new Vector2(AX - 0.019f, AY); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - - mA1 = new Vector2(AX, AY + 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - - mA1 = new Vector2(AX, AY - 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, 0.020f)); - } - - @Test - public void testSloppyEqualsVector2() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(v.sloppyEquals(mA1, 0.0f)); - - v = new Vector2(AX + 0.019f, AY); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector2(AX - 0.019f, AY); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector2(AX, AY + 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector2(AX, AY - 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - } - - @Test - public void testStaticAddValueFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(AX, AY, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - } - - @Test - public void testStaticAddValueVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - } - - @Test - public void testStaticDivideFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = divide(AX, AY, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - } - - @Test - public void testStaticDivideVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = divide(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - } - - @Test - public void testStaticDotFloat() - { - float expected = (AX * BX) + (AY * BY); - assertTrue(dot(AX, AY, BX, BY) == expected); - } - - @Test - public void testStaticGetDirectionABArray() - { - float sos = (float)Math.sqrt(0.5f); // 0.707 - float[] v = new float[2]; - float[] u = getDirectionAB(1, 1, 3, 3, v, 0); - assertTrue(u == v); - assertTrue(sloppyEquals(u[0], sos, 0.0001f) - && sloppyEquals(u[1], sos, 0.0001f)); - - v = new float[4]; // << - u = getDirectionAB(3, 3, 1, 1, v, 1); - assertTrue(u == v); - assertTrue(sloppyEquals(u[2], -sos, 0.0001f) - && sloppyEquals(u[3], -sos, 0.0001f)); - - u = getDirectionAB(1, 1, -1, 3, v, 0); - assertTrue(sloppyEquals(u[0], -sos, 0.0001f) - && sloppyEquals(u[1], sos, 0.0001f)); - - u = getDirectionAB(1, 1, 3, -1, v, 0); - assertTrue(sloppyEquals(u[0], sos, 0.0001f) - && sloppyEquals(u[1], -sos, 0.0001f)); - - } - - @Test - public void testStaticGetDirectionABVector() - { - float sos = (float)Math.sqrt(0.5f); // 0.707 - Vector2 v = new Vector2(); - Vector2 u = getDirectionAB(1, 1, 3, 3, v); - assertTrue(u == v); - assertTrue(sloppyEquals(u.x, sos, 0.0001f) - && sloppyEquals(u.y, sos, 0.0001f)); - - u = getDirectionAB(3, 3, 1, 1, v); - assertTrue(sloppyEquals(u.x, -sos, 0.0001f) - && sloppyEquals(u.y, -sos, 0.0001f)); - - u = getDirectionAB(1, 1, -1, 3, v); - assertTrue(sloppyEquals(u.x, -sos, 0.0001f) - && sloppyEquals(u.y, sos, 0.0001f)); - } - - - @Test - public void testStaticGetDistanceSqFloat() - { - float result = getDistanceSq(AX, AY, BX, BY); - float deltaX = BX - AX; - float deltaY = BY - AY; - float expected = (deltaX * deltaX) + (deltaY * deltaY); - assertTrue(result == expected); - } - - @Test - public void testStaticGetDistanceSqVector() - { - float result = getDistanceSq(mA1, mB1); - float deltaX = BX - AX; - float deltaY = BY - AY; - float expected = (deltaX * deltaX) + (deltaY * deltaY); - assertTrue(result == expected); - } - - @Test - public void testStaticGetLengthSq() - { - float len = (AX * AX) + (AY * AY); - assertTrue(getLengthSq(AX, AY) == len); - } - - @Test - public void testStaticMultiplyFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = multiply(AX, AY, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - } - - @Test - public void testStaticMultiplyVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = multiply(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - } - - @Test - public void testStaticNormalizeFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = normalize(AX, AY, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY)); - float x = AX / len; - float y = AY / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y); - } - - @Test - public void testStaticNormalizeVector() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = normalize(mA1, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY)); - float x = AX / len; - float y = AY / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y); - } - - @Test - public void testStaticRotateFloat() - { - // Only a simple test. Rotate 90 degrees counter clockwise. - Vector2 v = new Vector2(AX, AY); - Vector2 u = rotate(1, 0, (float)(Math.PI / 2), v); - assertTrue(u.x > -0.001 - && u.x < 0.001 - && u.y > 0.999 - && u.y < 1.001); - } - - @Test - public void testStaticRotateVector2() - { - // Only a simple test. Rotate 90 degrees counter clockwise. - Vector2 v = new Vector2(AX, AY); - Vector2 u = new Vector2(1, 0); - u = rotate(u, (float)(Math.PI / 2), v); - assertTrue(u == v); - assertTrue(u.x > -0.001 - && u.x < 0.001 - && u.y > 0.999 - && u.y < 1.001); - } - - @Test - public void testStaticScaleToFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = scaleTo(AX, AY, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(AX, AY, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticScaleToVector2() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = scaleTo(mA1, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticSloppyEqualsFloat() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - - v = new Vector2(AX + 0.019f, AY); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - - v = new Vector2(AX - 0.019f, AY); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - - v = new Vector2(AX, AY + 0.019f); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - - v = new Vector2(AX, AY - 0.019f); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.0f)); - assertFalse(sloppyEquals(AX, AY, v.x, v.y, 0.018f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.019f)); - assertTrue(sloppyEquals(AX, AY, v.x, v.y, 0.020f)); - } - - @Test - public void testStaticSloppyEqualsVector2() - { - Vector2 v = new Vector2(AX, AY); - assertTrue(sloppyEquals(mA1, v, 0.0f)); - - v = new Vector2(AX + 0.019f, AY); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector2(AX - 0.019f, AY); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector2(AX, AY + 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector2(AX, AY - 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - } - - @Test - public void testStaticSubtractFloats() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = subtract(AX, AY, BX, BY, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - } - - @Test - public void testStaticSubtractVectors() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = subtract(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - } - - @Test - public void testStaticTruncateLengthFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = truncateLength(AX, AY, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY); - - u = truncateLength(AX, AY, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(AX, AY, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticTruncateLengthVector2() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector2 v = new Vector2(AX, AY); - Vector2 u = truncateLength(mA1, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY); - - u = truncateLength(mA1, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0); - } - - @Test - public void testStaticVectorAddFloat() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(AX, AY, BX, BY, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - } - - @Test - public void testStaticVectorAddVector2() - { - Vector2 v = new Vector2(AX, AY); - Vector2 u = add(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - } - -} diff --git a/critterai/legacy/util-java/test/org/critterai/math/Vector3Tests.java b/critterai/legacy/util-java/test/org/critterai/math/Vector3Tests.java deleted file mode 100644 index 5f84d5e6..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/Vector3Tests.java +++ /dev/null @@ -1,925 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math; - -import static org.critterai.math.Vector3.*; - -import static org.junit.Assert.*; - -import org.critterai.math.Vector3; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Vector3} class. - */ -public class Vector3Tests { - - public static final float AX = 1.5f; - public static final float AY = 8.0f; - public static final float AZ = -3.2f; - public static final float BX = -17.112f; - public static final float BY = 77.5f; - public static final float BZ = 22.42f; - - private Vector3 mA1; - private Vector3 mB1; - - float[] mVectors; - - @Before - public void setUp() - throws Exception - { - mA1 = new Vector3(AX, AY, AZ); - mB1 = new Vector3(BX, BY, BZ); - mVectors = new float[6]; - mVectors[0] = AX; - mVectors[1] = AY; - mVectors[2] = AZ; - mVectors[3] = BX; - mVectors[4] = BY; - mVectors[5] = BZ; - } - - @Test - public void testConstructorArray() - { - Vector3 v = new Vector3(mVectors, 1); - assertTrue(v.x == BX); - assertTrue(v.y == BY); - assertTrue(v.z == BZ); - } - - @Test - public void testConstructorDefault() - { - Vector3 v = new Vector3(); - assertTrue(v.x == 0 && v.y == 0 && v.z == 0); - } - - @Test - public void testConstructorFloatFloatFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(v.x == AX && v.y == AY && v.z == AZ); - } - - @Test - public void testDotFloat() - { - float result = mA1.dot(BX, BY, BZ); - float expected = (AX * BX) + (AY * BY) + (AZ * BZ); - assertTrue(result == expected); - } - - @Test - public void testDotVector3() - { - float result = mA1.dot(mB1); - float expected = (AX * BX) + (AY * BY) + (AZ * BZ); - assertTrue(result == expected); - } - - @Test - public void testEqualsFloat() - { - assertTrue(mA1.equals(AX, AY, AZ)); - assertFalse(mA1.equals(AY, AX, AZ)); - assertFalse(mA1.equals(AZ, AX, AY)); - assertFalse(mA1.equals(AX, AZ, AY)); - } - - @Test - public void testEqualsObject() - { - assertTrue(mA1.equals((Object)new Vector3(AX, AY, AZ))); - assertFalse(mA1.equals((Object)mB1)); - assertFalse(mA1.equals((Object)new Vector3(AY, AX, AZ))); - assertFalse(mA1.equals((Object)new Vector3(AZ, AX, AY))); - assertFalse(mA1.equals((Object)new Vector3(AX, AZ, AY))); - } - - @Test - public void testEqualsVector3() - { - assertTrue(mA1.equals(new Vector3(AX, AY, AZ))); - assertFalse(mA1.equals(mB1)); - assertFalse(mA1.equals(new Vector3(AY, AX, AZ))); - assertFalse(mA1.equals(new Vector3(AZ, AX, AY))); - assertFalse(mA1.equals(new Vector3(AX, AZ, AY))); - } - - @Test - public void testFields() - { - assertTrue(mA1.x == AX); - assertTrue(mB1.x == BX); - assertTrue(mA1.y == AY); - assertTrue(mB1.y == BY); - assertTrue(mA1.z == AZ); - assertTrue(mB1.z == BZ); - } - - @Test - public void testFlatten() - { - float[] v = flatten(mVectors, 0, mB1, mA1); - assertTrue(v == mVectors); - assertTrue(v[0] == BX); - assertTrue(v[1] == BY); - assertTrue(v[2] == BZ); - assertTrue(v[3] == AX); - assertTrue(v[4] == AY); - assertTrue(v[5] == AZ); - v = flatten(mVectors, 1, mB1); - assertTrue(v[0] == BX); - assertTrue(v[1] == BY); - assertTrue(v[2] == BZ); - assertTrue(v[3] == BX); - assertTrue(v[4] == BY); - assertTrue(v[5] == BZ); - } - - @Test - public void testGet() - { - float[] va = mA1.get(mVectors, 1); - assertTrue(va == mVectors); - assertTrue(mVectors[0] == AX); - assertTrue(mVectors[1] == AY); - assertTrue(mVectors[2] == AZ); - assertTrue(mVectors[3] == AX); - assertTrue(mVectors[4] == AY); - assertTrue(mVectors[5] == AZ); - mB1.get(mVectors, 0); - assertTrue(mVectors[0] == BX); - assertTrue(mVectors[1] == BY); - assertTrue(mVectors[2] == BZ); - assertTrue(mVectors[3] == AX); - assertTrue(mVectors[4] == AY); - assertTrue(mVectors[5] == AZ); - } - - @Test - public void testGetX() - { - assertTrue(mA1.getX() == AX); - } - - @Test - public void testGetY() - { - assertTrue(mA1.getY() == AY); - } - - @Test - public void testGetZ() - { - assertTrue(mA1.getZ() == AZ); - } - - @Test - public void testHashCode() - { - assertTrue(mA1.hashCode() == new Vector3(AX, AY, AZ).hashCode()); - assertTrue(mA1.hashCode() != mB1.hashCode()); - assertTrue(mA1.hashCode() != new Vector3(AY, AX, AZ).hashCode()); - assertTrue(mA1.hashCode() != new Vector3(AZ, AX, AY).hashCode()); - assertTrue(mA1.hashCode() != new Vector3(AX, AZ, AY).hashCode()); - } - - @Test - public void testIsZeroLength() - { - assertTrue(new Vector3().isZeroLength()); - assertFalse(mA1.isZeroLength()); - } - - @Test - public void testLengthSq() - { - float len = (AX * AX) + (AY * AY) + (AZ * AZ); - assertTrue(mA1.lengthSq() == len); - } - - @Test - public void testMutatorAddFloat() - { - assertTrue(mA1.add(BX, BY, BZ) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - assertTrue(mA1.z == AZ + BZ); - } - - @Test - public void testMutatorAddVector3() - { - assertTrue(mA1.add(mB1) == mA1); - assertTrue(mA1.x == AX + BX); - assertTrue(mA1.y == AY + BY); - assertTrue(mA1.z == AZ + BZ); - } - - @Test - public void testMutatorDivide() - { - assertTrue(mA1.divide(5) == mA1); - assertTrue(mA1.x == AX / 5); - assertTrue(mA1.y == AY / 5); - assertTrue(mA1.z == AZ / 5); - } - - @Test - public void testMutatorMultiply() - { - assertTrue(mA1.multiply(5) == mA1); - assertTrue(mA1.x == AX * 5); - assertTrue(mA1.y == AY * 5); - assertTrue(mA1.z == AZ * 5); - } - - @Test - public void testMutatorNormalize() - { - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float expectedX = AX / len; - float expectedY = AY / len; - float expectedZ = AZ / len; - - assertTrue(mA1.normalize() == mA1); - assertTrue(mA1.x == expectedX); - assertTrue(mA1.y == expectedY); - assertTrue(mA1.z == expectedZ); - } - - @Test - public void testMutatorScaleTo() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.scaleTo(15.0f) == mA1); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - mA1 = new Vector3(AX, AY, AZ).scaleTo(0); - assertTrue(mA1.x == 0 && mA1.y == 0); - } - - @Test - public void testMutatorSubtractFloat() - { - assertTrue(mA1.subtract(BX, BY, BZ) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - assertTrue(mA1.z == AZ - BZ); - } - - @Test - public void testMutatorSubtractVector() - { - assertTrue(mA1.subtract(mB1) == mA1); - assertTrue(mA1.x == AX - BX); - assertTrue(mA1.y == AY - BY); - assertTrue(mA1.z == AZ - BZ); - } - - @Test - public void testMutatorTruncateLength() - { - // Can improve this test by checking for proper setting - // of both x and y. - assertTrue(mA1.truncateLength(15.0f) == mA1); - assertTrue(mA1.x == AX && mA1.y == AY && mA1.z == mA1.z); - - mA1 = new Vector3(AX, AY, AZ).truncateLength(5); - float len = (float)Math.sqrt(mA1.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - mA1 = new Vector3(AX, AY, AZ).truncateLength(0); - assertTrue(mA1.x == 0 && mA1.y == 0 && mA1.z == 0); - } - - @Test - public void testMutatorXValue() - { - mA1.setX(BX); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == AY); - assertTrue(mA1.z == AZ); - } - - @Test - public void testMutatorYValue() - { - mA1.setY(BY); - assertTrue(mA1.x == AX); - assertTrue(mA1.y == BY); - assertTrue(mA1.z == AZ); - } - - @Test - public void testMutatorZValue() - { - mA1.setZ(BZ); - assertTrue(mA1.x == AX); - assertTrue(mA1.y == AY); - assertTrue(mA1.z == BZ); - } - - @Test - public void testSetValueFloat() - { - assertTrue(mA1 == mA1.set(BX, BY, BZ)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - assertTrue(mA1.z == BZ); - - } - - @Test - public void testSetValueVector3() - { - assertTrue (mA1 == mA1.set(mB1)); - assertTrue(mA1.x == BX); - assertTrue(mA1.y == BY); - assertTrue(mA1.z == BZ); - } - - @Test - public void testSloppyEqualsFloat() - { - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - - mA1 = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - - mA1 = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.0f)); - assertFalse(mA1.sloppyEquals(AX, AY, AZ, 0.018f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.019f)); - assertTrue(mA1.sloppyEquals(AX, AY, AZ, 0.020f)); - } - - @Test - public void testSloppyEqualsVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(v.sloppyEquals(mA1, 0.0f)); - - v = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - - v = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(v.sloppyEquals(mA1, 0.0f)); - assertFalse(v.sloppyEquals(mA1, 0.018f)); - assertTrue(v.sloppyEquals(mA1, 0.019f)); - assertTrue(v.sloppyEquals(mA1, 0.020f)); - } - - @Test - public void testStaticAddFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(AX, AY, AZ, BX, BY, BZ, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - assertTrue(u.z == AZ + BZ); - } - - @Test - public void testStaticAddValueFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(AX, AY, AZ, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - assertTrue(u.z == AZ + BX); - } - - @Test - public void testStaticAddValueVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BX); - assertTrue(u.z == AZ + BX); - } - - @Test - public void testStaticAddVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = add(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX + BX); - assertTrue(u.y == AY + BY); - assertTrue(u.z == AZ + BZ); - } - - - @Test - public void testStaticCrossArrayArray() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - float[] v = cross(mVectors, 0, mVectors, 1, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticCrossFloat() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - Vector3 v = Vector3.cross(AX, AY, AZ, BX, BY, BZ, mA1); - assertTrue(v == mA1); - assertTrue(v.x == expectedX); - assertTrue(v.y == expectedY); - assertTrue(v.z == expectedZ); - } - - @Test - public void testStaticCrossFloatArray() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - float[] v = cross(AX, AY, AZ, BX, BY, BZ, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticCrossVector3() - { - float expectedX = AY*BZ - AZ*BY; - float expectedY = -AX*BZ + AZ*BX; - float expectedZ = AX*BY - AY*BX; - Vector3 v = cross(mA1, mB1, mA1); - assertTrue(v == mA1); - assertTrue(v.x == expectedX); - assertTrue(v.y == expectedY); - assertTrue(v.z == expectedZ); - } - - @Test - public void testStaticDivideFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = divide(AX, AY, AZ, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - assertTrue(u.z == AZ / BX); - } - - @Test - public void testStaticDivideVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = divide(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX / BX); - assertTrue(u.y == AY / BX); - } - - @Test - public void testStaticDotFloat() - { - float expected = (AX * BX) + (AY * BY) + (AZ * BZ); - assertTrue(dot(AX, AY, AZ, BX, BY, BZ) == expected); - } - - @Test - public void testStaticGetDistanceSqFloat() - { - float result = getDistanceSq(AX, AY, AZ, BX, BY, BZ); - float deltaX = BX - AX; - float deltaY = BY - AY; - float deltaZ = BZ - AZ; - float expected = (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ); - assertTrue(result == expected); - } - - @Test - public void testStaticGetDistanceSqVector() - { - float result = getDistanceSq(mA1, mB1); - float deltaX = BX - AX; - float deltaY = BY - AY; - float deltaZ = BZ - AZ; - float expected = (deltaX * deltaX) + (deltaY * deltaY) + (deltaZ * deltaZ); - assertTrue(result == expected); - } - - @Test - public void testStaticGetLengthSq() - { - float len = (AX * AX) + (AY * AY) + (AZ * AZ); - assertTrue(getLengthSq(AX, AY, AZ) == len); - } - - @Test - public void testStaticMultiplyFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = multiply(AX, AY, AZ, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - assertTrue(u.z == AZ * BX); - } - - @Test - public void testStaticMultiplyVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = multiply(mA1, BX, v); - assertTrue(u == v); - assertTrue(u.x == AX * BX); - assertTrue(u.y == AY * BX); - assertTrue(u.z == AZ * BX); - } - - @Test - public void testStaticNormalizeArrayArray() - { - float[] v = normalize(mVectors, 1, mVectors, 1); - float len = (float) Math.sqrt((BX * BX) + (BY * BY) + (BZ * BZ)); - float expectedX = BX / len; - float expectedY = BY / len; - float expectedZ = BZ / len; - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticNormalizeFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = normalize(AX, AY, AZ, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float x = AX / len; - float y = AY / len; - float z = AZ / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y && u.z == z); - } - - @Test - public void testStaticNormalizeFloatArrray() - { - float[] v = normalize(AX, AY, AZ, mVectors, 1); - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float expectedX = AX / len; - float expectedY = AY / len; - float expectedZ = AZ / len; - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == expectedX); - assertTrue(v[4] == expectedY); - assertTrue(v[5] == expectedZ); - } - - @Test - public void testStaticNormalizeVector() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = normalize(mA1, v); - float len = (float) Math.sqrt((AX * AX) + (AY * AY) + (AZ * AZ)); - float x = AX / len; - float y = AY / len; - float z = AZ / len; - assertTrue(u == v); - assertTrue(u.x == x && u.y == y && u.z == z); - } - - @Test - public void testStaticScaleToFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = scaleTo(AX, AY, AZ, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(AX, AY, AZ, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - - - - - - - - - - - - - - - - - @Test - public void testStaticScaleToVector3() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = scaleTo(mA1, 15.0f, v); - assertTrue(u == v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 14.999f && len < 15.001f); - - u = scaleTo(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - - @Test - public void testStaticSloppyEqualsFloat() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - - v = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - - v = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.0f)); - assertFalse(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.018f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.019f)); - assertTrue(sloppyEquals(AX, AY, AZ, v.x, v.y, v.z, 0.020f)); - } - - @Test - public void testStaticSloppyEqualsVector3() - { - Vector3 v = new Vector3(AX, AY, AZ); - assertTrue(sloppyEquals(mA1, v, 0.0f)); - - v = new Vector3(AX + 0.019f, AY, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX - 0.019f, AY, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY + 0.019f, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY - 0.019f, AZ); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY, AZ + 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - - v = new Vector3(AX, AY, AZ - 0.019f); - assertFalse(sloppyEquals(mA1, v, 0.0f)); - assertFalse(sloppyEquals(mA1, v, 0.018f)); - assertTrue(sloppyEquals(mA1, v, 0.019f)); - assertTrue(sloppyEquals(mA1, v, 0.020f)); - } - - @Test - public void testStaticSubtractArrayArray() - { - float[] v = subtract(mVectors, 1, mVectors, 1, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == 0); - assertTrue(v[4] == 0); - assertTrue(v[5] == 0); - } - - @Test - public void testStaticSubtractFloatArray() - { - float[] v = subtract(AX, AY, AZ, BX, BY, BZ, mVectors, 1); - assertTrue(v == mVectors); - assertTrue(v[0] == AX); - assertTrue(v[1] == AY); - assertTrue(v[2] == AZ); - assertTrue(v[3] == AX - BX); - assertTrue(v[4] == AY - BY); - assertTrue(v[5] == AZ - BZ); - } - - @Test - public void testStaticSubtractFloats() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = subtract(AX, AY, AZ, BX, BY, BZ, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - assertTrue(u.z == AZ - BZ); - } - - @Test - public void testStaticSubtractVectors() - { - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = subtract(mA1, mB1, v); - assertTrue(u == v); - assertTrue(u.x == AX - BX); - assertTrue(u.y == AY - BY); - assertTrue(u.z == AZ - BZ); - } - - @Test - public void testStaticTranslateTowardFloat() - { - final float factor = 0.62f; - final float x = AX + (BX - AX) * factor; - final float y = AY + (BY - AY) * factor; - final float z = AZ + (BZ - AZ) * factor; - Vector3 v = new Vector3(); - Vector3 u = translateToward(AX, AY, AZ, BX, BY, BZ, factor, v); - assertTrue(u == v); - assertTrue(u.x == x); - assertTrue(u.y == y); - assertTrue(u.z == z); - } - - @Test - public void testStaticTruncateLengthFloat() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = truncateLength(AX, AY, AZ, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY && u.z == AZ); - - u = truncateLength(AX, AY, AZ, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(AX, AY, AZ, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - - @Test - public void testStaticTruncateLengthVector3() - { - // Can improve this test by checking for proper setting - // of both x and y. - Vector3 v = new Vector3(AX, AY, AZ); - Vector3 u = truncateLength(mA1, 15.0f, v); - assertTrue(u == v); - assertTrue(u.x == AX && u.y == AY && u.z == AZ); - - u = truncateLength(mA1, 5.0f, v); - float len = (float)Math.sqrt(u.lengthSq()); - assertTrue(len > 4.999f && len < 5.001f); - - u = truncateLength(mA1, 0, v); - assertTrue(u.x == 0 && u.y == 0 && u.z == 0); - } - -} diff --git a/critterai/legacy/util-java/test/org/critterai/math/geom/AllTests.java b/critterai/legacy/util-java/test/org/critterai/math/geom/AllTests.java deleted file mode 100644 index 63f8b0fe..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/geom/AllTests.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.junit.runners.Suite.SuiteClasses; - -/** - * All unit tests for classes in the org.critterai.math.geom package. - */ -@RunWith(Suite.class) -@SuiteClasses( {Line2Tests.class - , Triangle2Test.class - , Rectangle2Tests.class - , Polygon3Tests.class - , Triangle3Tests.class} ) -public class AllTests { } diff --git a/critterai/legacy/util-java/test/org/critterai/math/geom/Line2Tests.java b/critterai/legacy/util-java/test/org/critterai/math/geom/Line2Tests.java deleted file mode 100644 index 6e3c56cf..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/geom/Line2Tests.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.*; -import static org.critterai.math.geom.Line2.*; - -import org.critterai.math.Vector2; -import org.critterai.math.geom.Line2; -import org.critterai.math.geom.LineRelType; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Line2} class. - */ -public class Line2Tests { - - private static final float AX = -5; - private static final float AY = 3; - private static final float BX = 1; - private static final float BY = 1; - private static final float CX = -3; - private static final float CY = 0; - private static final float DX = -1; - private static final float DY = 4; - private static final float EX = -2; - private static final float EY = 2; - private static final float FX = 4; - private static final float FY = 0; - private static final float GX = 0; - private static final float GY = 3; - private static final float HX = 2; - private static final float HY = -1; - private static final float JX = -4; - private static final float JY = 1; - private static final float KX = -4; - private static final float KY = -2; - - private static final int AXI = -5; - private static final int AYI = 3; - private static final int BXI = 1; - private static final int BYI = 1; - private static final int CXI = -3; - private static final int CYI = 0; - private static final int DXI = -1; - private static final int DYI = 4; - private static final int EXI = -2; - private static final int EYI = 2; - private static final int FXI = 4; - private static final int FYI = 0; - private static final int GXI = 0; - private static final int GYI = 3; - - @Before - public void setUp() throws Exception - { - } - - @Test - public void testLinesIntersectFloat() - { - // Standard. Cross within segments. - assertTrue(linesIntersect(AX, AY, BX, BY, CX, CY, DX, DY)); - assertTrue(linesIntersect(BX, BY, AX, AY, CX, CY, DX, DY)); - assertTrue(linesIntersect(BX, BY, AX, AY, DX, DY, CX, CY)); - assertTrue(linesIntersect(AX, AY, BX, BY, DX, DY, CX, CY)); - - // Standard. Cross outside segment. - assertTrue(linesIntersect(AX, AY, BX, BY, DX, DY, GX, GY)); - assertTrue(linesIntersect(BX, BY, AX, AY, DX, DY, GX, GY)); - assertTrue(linesIntersect(BX, BY, AX, AY, GX, GY, DX, DY)); - assertTrue(linesIntersect(AX, AY, BX, BY, GX, GY, DX, DY)); - - // Collinear - assertTrue(linesIntersect(AX, AY, BX, BY, EX, EY, FX, FY)); - assertTrue(linesIntersect(BX, BY, AX, AY, EX, EY, FX, FY)); - assertTrue(linesIntersect(BX, BY, AX, AY, FX, FY, EX, EY)); - assertTrue(linesIntersect(AX, AY, BX, BY, FX, FY, EX, EY)); - - // Parallel Diagonal - assertFalse(linesIntersect(AX, AY, BX, BY, EX-2, EY, FX-2, FY)); - assertFalse(linesIntersect(BX, BY, AX, AY, EX-2, EY, FX-2, FY)); - assertFalse(linesIntersect(BX, BY, AX, AY, FX-2, FY, EX-2, EY)); - assertFalse(linesIntersect(AX, AY, BX, BY, FX-2, FY, EX-2, EY)); - - // Parallel Vertical - assertFalse(linesIntersect(AX, 5, BX, 5, EX, 3, FX, 3)); - - // Parallel Horizontal - assertFalse(linesIntersect(5, AY, 5, BY, 2, CY, 2, DY)); - } - - @Test - public void testLinesIntersectInt() - { - // Standard. Cross within segments. - assertTrue(linesIntersect(AXI, AYI, BXI, BYI, CXI, CYI, DXI, DYI)); - - // Standard. Cross outside segment. - assertTrue(linesIntersect(AXI, AYI, BXI, BYI, DXI, DYI, GXI, GYI)); - - // Collinear - assertTrue(linesIntersect(AXI, AYI, BXI, BYI, EXI, EYI, FXI, FYI)); - - // Parallel Diagonal - assertFalse(linesIntersect(AXI, AYI, BXI, BYI, EXI-2, EYI, FXI-2, FYI)); - - // Parallel Vertical - assertFalse(linesIntersect(AXI, 5, BXI, 5, EXI, 3, FXI, 3)); - - // Parallel Horizontal - assertFalse(linesIntersect(5, AYI, 5, BYI, 2, CYI, 2, DYI)); - } - - @Test - public void testGetPointSegmentDistanceSqFloat() - { - // Closest to end point B. - float expected = Vector2.getDistanceSq(HX, HY, BX, BY); - assertTrue(getPointSegmentDistanceSq(HX, HY, EX, EY, BX, BY) == expected); - - // Closest to end point E. - expected = Vector2.getDistanceSq(JX, JY, EX, EY); - assertTrue(getPointSegmentDistanceSq(JX, JY, EX, EY, BX, BY) == expected); - - // Closest to mid-point of AB. (E) - expected = Vector2.getDistanceSq(-1, 5, EX, EY); - assertTrue(getPointSegmentDistanceSq(-1, 5, AX, AY, BX, BY) == expected); - expected = Vector2.getDistanceSq(-3, -1, EX, EY); - assertTrue(getPointSegmentDistanceSq(-3, -1, AX, AY, BX, BY) == expected); - } - - @Test - public void testGetPointLineDistanceSqFloat() - { - - float expected = Vector2.getDistanceSq(-3, -1, EX, EY); - float actual = getPointLineDistanceSq(-3, -1, AX, AY, BX, BY); - assertTrue(actual == expected); - expected = Vector2.getDistanceSq(-1, 5, EX, EY); - actual = getPointLineDistanceSq(-1, 5, AX, AY, BX, BY); - assertTrue(actual == expected); - expected = 0; - actual = getPointLineDistanceSq(FX, FY, AX, AY, BX, BY); - assertTrue(actual == expected); - - - } - - @Test - public void testGetNormalAB() - { - - // Diagonal - Vector2 v = new Vector2(); - Vector2 expected = new Vector2(-1, -3).normalize(); - assertTrue(v == getNormalAB(AX, AY, BX, BY, v)); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Reversed Diagonal - expected = new Vector2(1, 3).normalize(); - getNormalAB(BX, BY, AX, AY, v); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Vertical - expected = new Vector2(-1, 0); - getNormalAB(5, AY, 5, BY, v); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Horizontal - expected = new Vector2(0, -1); - getNormalAB(AX, 5, BX, 5, v); - assertTrue(v.sloppyEquals(expected, 0.0001f)); - - // Not a line. - getNormalAB(AX, AY, AX, AY, v); - assertTrue(v.equals(0, 0)); - - } - - @Test - public void testGetRelationship() - { - Vector2 v = new Vector2(); - assertTrue(LineRelType.SEGMENTS_INTERSECT - == getRelationship(AX, AY, BX, BY, CX, CY, DX, DY, v)); - assertTrue(v.sloppyEquals(EX, EY, 0.0001f)); - - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(AX, AY, EX, EY, GX, GY, HX, HY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - - // Line reversal checks. - v = new Vector2(); - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(EX, EY, AX, AY, GX, GY, HX, HY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - v = new Vector2(); - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(EX, EY, AX, AY, HX, HY, GX, GY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - v = new Vector2(); - assertTrue(LineRelType.ALINE_CROSSES_BSEG - == getRelationship(AX, AY, EX, EY, HX, HY, GX, GY, v)); - assertTrue(v.sloppyEquals(BX, BY, 0.0001f)); - - assertTrue(LineRelType.BLINE_CROSSES_ASEG - == getRelationship(AX, AY, BX, BY, KX, KY, CX, CY, v)); - assertTrue(v.sloppyEquals(EX, EY, 0.0001f)); - - v = new Vector2(); - assertTrue(LineRelType.LINES_INTERSECT - == getRelationship(KX, KY, CX, CY, FX, FY, BX, BY, v)); - assertTrue(v.sloppyEquals(EX, EY, 0.0001f)); - - // NULL version. - assertTrue(LineRelType.SEGMENTS_INTERSECT - == getRelationship(AX, AY, BX, BY, CX, CY, DX, DY, null)); - - v = new Vector2(JX, JY); - - assertTrue(LineRelType.PARALLEL - == getRelationship(AX, AY, BX, BY, EX-2, EY, FX-2, FY, null)); - assertTrue(v.equals(JX, JY)); - - // Collinear - No segment overlap. - assertTrue(LineRelType.COLLINEAR - == getRelationship(AX, AY, EX, EY, BX, BY, FX, FY, null)); - assertTrue(v.equals(JX, JY)); - - // Collinear - Segment overlap. - assertTrue(LineRelType.COLLINEAR - == getRelationship(AX, AY, BX, BY, EX, EY, FX, FY, null)); - assertTrue(v.equals(JX, JY)); - - - - } - -} diff --git a/critterai/legacy/util-java/test/org/critterai/math/geom/Polygon3Tests.java b/critterai/legacy/util-java/test/org/critterai/math/geom/Polygon3Tests.java deleted file mode 100644 index b73fabab..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/geom/Polygon3Tests.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.*; -import static org.critterai.math.geom.Polygon3.*; - -import org.critterai.math.Vector3; -import org.critterai.math.geom.Polygon3; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Polygon3} class. - */ -public class Polygon3Tests { - - private static final float AX = -2; - private static final float AY = -2; - private static final float AZ = 1; - private static final float BX = -1; - private static final float BY = 0; - private static final float BZ = 2; - private static final float CX = 0; - private static final float CY = 2; - private static final float CZ = 2; - private static final float DX = 1; - private static final float DY = 4; - private static final float DZ = 1; - private static final float EX = 1; - private static final float EY = 4; - private static final float EZ = 0; - private static final float FX = 0; - private static final float FY = 2; - private static final float FZ = -1; - private static final float GX = -1; - private static final float GY = 0; - private static final float GZ = -1; - private static final float HX = -2; - private static final float HY = -2; - private static final float HZ = 0; - private static final float JX = 2; - private static final float JY = 6; - private static final float JZ = 1; - private static final float KX = -4; - private static final float KY = 0; - private static final float KZ = 2; - - private static final float CENX = -0.5f; - private static final float CENY = 1.0f; - private static final float CENZ = 0.5f; - - private float[] mVerts; - - @Before - public void setUp() throws Exception - { - mVerts = new float[10*3]; - mVerts[0] = KX; // Padding - mVerts[1] = KY; - mVerts[2] = KZ; - mVerts[3] = AX; // Start of poly - mVerts[4] = AY; - mVerts[5] = AZ; - mVerts[6] = BX; - mVerts[7] = BY; - mVerts[8] = BZ; - mVerts[9] = CX; - mVerts[10] = CY; - mVerts[11] = CZ; - mVerts[12] = DX; - mVerts[13] = DY; - mVerts[14] = DZ; - mVerts[15] = EX; // J insertion point. - mVerts[16] = EY; - mVerts[17] = EZ; - mVerts[18] = FX; - mVerts[19] = FY; - mVerts[20] = FZ; - mVerts[21] = GX; - mVerts[22] = GY; - mVerts[23] = GZ; - mVerts[24] = HX; - mVerts[25] = HY; - mVerts[26] = HZ; // End of poly - mVerts[27] = KX; // Padding and centroid storage location. - mVerts[28] = KY; - mVerts[29] = KZ; - } - - @Test - public void testIsConvexStandardTrue() - { - assertTrue(isConvex(mVerts, 1, 8)); - } - - @Test - public void testIsConvexStandardFalse() - { - mVerts[15] = JX; - mVerts[16] = JY; - mVerts[17] = JZ; - assertFalse(isConvex(mVerts, 1, 8)); - } - - @Test - public void testIsConvexVerticalTrue() - { - for (int p = 1; p < mVerts.length; p += 3) - { - mVerts[p] = mVerts[p+1]; - mVerts[p+1] = -2; - } - assertTrue(isConvex(mVerts, 1, 8)); - } - - @Test - public void testIsConvexVerticalFalse() - { - mVerts[15] = JX; - mVerts[16] = JY; - mVerts[17] = JZ; - for (int p = 1; p < mVerts.length; p += 3) - { - mVerts[p] = mVerts[p+1]; - mVerts[p+1] = -2; - } - assertFalse(isConvex(mVerts, 1, 8)); - } - - @Test - public void testGetCentroidArray() - { - assertTrue(mVerts == getCentroid(mVerts, 1, 8, mVerts, 9)); - assertTrue(mVerts[27] == CENX); - assertTrue(mVerts[28] == CENY); - assertTrue(mVerts[29] == CENZ); - } - - @Test - public void testGetCentroidVector3() - { - Vector3 v = new Vector3(5, 5, 5); // Needs to be seeded with non-zero. - assertTrue(v == getCentroid(mVerts, 1, 8, v)); - assertTrue(v.x == CENX); - assertTrue(v.y == CENY); - assertTrue(v.z == CENZ); - } - - @Test - public void testGetCentroidFloatList() - { - Vector3 v = new Vector3(5, 5, 5); // Needs to be seeded with non-zero. - assertTrue(v == getCentroid(v - , AX, AY, AZ - , BX, BY, BZ - , CX, CY, CZ - , DX, DY, DZ - , EX, EY, EZ - , FX, FY, FZ - , GX, GY, GZ - , HX, HY, HZ)); - assertTrue(v.x == CENX); - assertTrue(v.y == CENY); - assertTrue(v.z == CENZ); - } - -} diff --git a/critterai/legacy/util-java/test/org/critterai/math/geom/Rectangle2Tests.java b/critterai/legacy/util-java/test/org/critterai/math/geom/Rectangle2Tests.java deleted file mode 100644 index 58507c26..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/geom/Rectangle2Tests.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.critterai.math.geom.Rectangle2.contains; -import static org.critterai.math.geom.Rectangle2.intersectsAABB; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.critterai.math.MathUtil; -import org.critterai.math.geom.Rectangle2; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Rectangle2} class. - */ -public class Rectangle2Tests { - - private static final float XMIN = -3; - private static final float YMIN = 2; - private static final float XMAX = 2; - private static final float YMAX = 6; - - private static final float TOLERANCE = MathUtil.TOLERANCE_STD; - private static final float OFFSET = 1.5f; - - @Before - public void setUp() - throws Exception - { - - } - - @Test - public void testContainsPoint() - { - - // Wall tests. - - // On x min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN, YMIN + OFFSET)); - // On y min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMIN)); - // On x max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX , YMIN + OFFSET)); - // On y max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMAX)); - - // Inside x min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + TOLERANCE, YMIN + OFFSET)); - // Inside y min bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMIN + TOLERANCE)); - // Inside x max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX - TOLERANCE , YMIN + OFFSET)); - // Inside y max bounds. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMAX - TOLERANCE)); - - // Outside x min bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN - TOLERANCE, YMIN + OFFSET)); - // Outside y min bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMIN - TOLERANCE)); - // Outside x max bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX + TOLERANCE , YMIN + OFFSET)); - // Outside y max bounds. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN + OFFSET, YMAX + TOLERANCE)); - - // Corner tests. - - // On minX/minY corner - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN, YMIN)); - // On minX/maxY corner - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN, YMAX)); - // On maxX/maxY corner. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX , YMAX)); - // On maxX/minY corner. - assertTrue(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX, YMIN)); - - // Outside minX/minY corner - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN - TOLERANCE, YMIN - TOLERANCE)); - // Outside minX/maxY corner - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMIN - TOLERANCE, YMAX + TOLERANCE)); - // Outside maxX/maxY corner. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX + TOLERANCE , YMAX + TOLERANCE)); - // Outside maxX/minY corner. - assertFalse(contains(XMIN, YMIN - , XMAX, YMAX - , XMAX + TOLERANCE, YMIN - TOLERANCE)); - - } - - @Test - public void testContainsAABB() - { - - // A == B - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN, XMAX, YMAX)); - // B contains A - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - TOLERANCE, YMIN - TOLERANCE, XMAX + TOLERANCE, YMAX + TOLERANCE)); - // B slightly smaller than A. - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + TOLERANCE, YMIN + TOLERANCE, XMAX - TOLERANCE, YMAX - TOLERANCE)); - - // X-axis wall tests - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN + OFFSET, XMAX - TOLERANCE, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN + OFFSET, XMAX + TOLERANCE, YMAX - OFFSET)); - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + TOLERANCE, YMIN + OFFSET, XMAX, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - TOLERANCE, YMIN + OFFSET, XMAX, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN + OFFSET, XMIN + TOLERANCE, YMAX - OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMIN + OFFSET, XMAX + OFFSET, YMAX - OFFSET)); - - // Y-axis wall tests - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN, XMAX - OFFSET, YMAX - TOLERANCE)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN, XMAX - OFFSET, YMAX + TOLERANCE)); - assertTrue(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN + TOLERANCE, XMAX - OFFSET, YMAX)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN - TOLERANCE, XMAX - OFFSET, YMAX)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN - OFFSET, XMAX - OFFSET, YMIN + TOLERANCE)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMAX + TOLERANCE, XMAX - OFFSET, YMAX + OFFSET)); - - // Corner tests - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN - OFFSET, XMIN + TOLERANCE, YMIN + TOLERANCE)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMAX - TOLERANCE, XMIN + TOLERANCE, YMAX + OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMAX - TOLERANCE, YMAX - TOLERANCE, XMAX + OFFSET, YMAX + OFFSET)); - assertFalse(contains(XMIN, YMIN, XMAX, YMAX - , XMAX - TOLERANCE, YMIN - OFFSET, XMAX + OFFSET, YMIN + TOLERANCE)); - - } - - // Leave this test in place until the associated code is permanently - // removed from the rectangle class. -// @Test -// public void testContainsStd() -// { -// // Wall tests. -// -// // On x min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN, YMIN + OFFSET)); -// // On y min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMIN)); -// // On x max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX , YMIN + OFFSET)); -// // On y max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMAX)); -// -// // Inside x min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + TOLERANCE, YMIN + OFFSET)); -// // Inside y min bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMIN + TOLERANCE)); -// // Inside x max bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX - TOLERANCE , YMIN + OFFSET)); -// // Inside y max bounds. -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMAX - TOLERANCE)); -// -// // Outside x min bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN - TOLERANCE, YMIN + OFFSET)); -// // Outside y min bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMIN - TOLERANCE)); -// // Outside x max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX + TOLERANCE , YMIN + OFFSET)); -// // Outside y max bounds. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN + OFFSET, YMAX + TOLERANCE)); -// -// // Corner tests. -// -// // On minX/minY corner -// assertTrue(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN, YMIN)); -// // On minX/maxY corner -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN, YMAX)); -// // On maxX/maxY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX , YMAX)); -// // On maxX/minY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX, YMIN)); -// -// // Outside minX/minY corner -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN - TOLERANCE, YMIN - TOLERANCE)); -// // Outside minX/maxY corner -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMIN - TOLERANCE, YMAX + TOLERANCE)); -// // Outside maxX/maxY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX + TOLERANCE , YMAX + TOLERANCE)); -// // Outside maxX/minY corner. -// assertFalse(containsStd(XMIN, YMIN -// , XMAX, YMAX -// , XMAX + TOLERANCE, YMIN - TOLERANCE)); -// } - - @Test - public void testIntersects() - { - // Complete overlap - assertTrue(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN, YMIN, XMAX, YMAX)); - - // A fully contains B - assertTrue(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN + TOLERANCE, YMIN + TOLERANCE, XMAX - TOLERANCE, YMAX - TOLERANCE)); - - // Wall tests - - // A xmin overlaps B xmax - assertTrue(intersectsAABB(XMIN , YMIN , XMAX, YMAX - , XMIN - OFFSET, YMIN + OFFSET, XMIN, YMAX - OFFSET)); - // A xmax overlaps B xmin - assertTrue(intersectsAABB(XMIN, YMIN , XMAX , YMAX - , XMAX, YMIN + OFFSET, XMAX + OFFSET, YMAX - OFFSET)); - // A ymin overlaps B ymax - assertTrue(intersectsAABB(XMIN , YMIN , XMAX , YMAX - , XMIN + OFFSET, YMIN - OFFSET, XMAX - OFFSET, YMIN)); - // A ymax overlaps B ymin - assertTrue(intersectsAABB(XMIN , YMIN, XMAX , YMAX - , XMIN + OFFSET, YMAX, XMAX - OFFSET, YMAX + OFFSET)); - - // A xmin above B xmax - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN + OFFSET, XMIN - TOLERANCE, YMAX - OFFSET)); - // A xmax below B xmin - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMIN + OFFSET, XMAX + OFFSET, YMAX - OFFSET)); - // A ymin above B ymax - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMIN - OFFSET, XMAX - OFFSET, YMIN - TOLERANCE)); - // A ymax below B ymin - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN + OFFSET, YMAX + TOLERANCE, XMAX - OFFSET, YMAX + OFFSET)); - - // Corner tests. - - // B fully below A xmin and A ymin - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMIN - OFFSET, XMIN - TOLERANCE, YMIN - TOLERANCE)); - // B fully above A xmax and A ymax - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMAX + TOLERANCE, XMAX + OFFSET, YMAX + OFFSET)); - // B above and to right of A - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMIN - OFFSET, YMAX + TOLERANCE, XMIN - TOLERANCE, YMAX + OFFSET)); - // B below and to the left of A - assertFalse(intersectsAABB(XMIN, YMIN, XMAX, YMAX - , XMAX + TOLERANCE, YMIN - OFFSET, XMAX + OFFSET, YMIN - TOLERANCE)); - - } - -} diff --git a/critterai/legacy/util-java/test/org/critterai/math/geom/Triangle2Test.java b/critterai/legacy/util-java/test/org/critterai/math/geom/Triangle2Test.java deleted file mode 100644 index 3fc6876e..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/geom/Triangle2Test.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import static org.critterai.math.geom.Triangle2.*; - -import org.critterai.math.geom.Triangle2; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Triangle2} class. - */ -public class Triangle2Test { - - // Clockwise wrapped - private static final float AX = 3; - private static final float AY = 2; - private static final float BX = 2; - private static final float BY = -1; - private static final float CX = 0; - private static final float CY = -1; - - // Clockwise Wrapped - private static final float AXI = 3; - private static final float AYI = 2; - private static final float BXI = 2; - private static final float BYI = -1; - private static final float CXI = 0; - private static final float CYI = -1; - - public static final float TOLERANCE = 0.0001f; - - @Before - public void setUp() throws Exception - { - } - - @Test - public void testStaticContains() - { - - // Vertex inclusion tests - - assertTrue(contains(AX, AY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(BX, BY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(BX - TOLERANCE, BY + TOLERANCE, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(BX + TOLERANCE, BY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(CX, CY, AX, AY, BX, BY, CX, CY)); - - // Wall inclusion tests - - float midpointX = AX + (BX - AX) / 2; - float midpointY = AY + (BY - AY) / 2; - assertTrue(contains(midpointX, midpointY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(midpointX - TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(midpointX + TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - midpointX = BX + (CX - BX) / 2; - midpointY = BY + (CY - BY) / 2; - assertTrue(contains(midpointX, midpointY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(midpointX, midpointY + TOLERANCE, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(midpointX, midpointY - TOLERANCE, AX, AY, BX, BY, CX, CY)); - midpointX = CX + (AX - CX) / 2; - midpointY = CY + (AY - CY) / 2; - assertTrue(contains(midpointX, midpointY, AX, AY, BX, BY, CX, CY)); - assertTrue(contains(midpointX + TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - assertFalse(contains(midpointX - TOLERANCE, midpointY, AX, AY, BX, BY, CX, CY)); - - } - - - - @Test - public void testAreaFloat() - { - float result = getSignedAreaX2(AX, AY, BX, BY, CX, CY); - assertTrue(result == -6); - result = getSignedAreaX2(AX, AY, CX, CY, BX, BY); - assertTrue(result == 6); - } - - @Test - public void testAreaInt() - { - float result = getSignedAreaX2(AXI, AYI, BXI, BYI, CXI, CYI); - assertTrue(result == -6); - result = getSignedAreaX2(AXI, AYI, CXI, CYI, BXI, BYI); - assertTrue(result == 6); - } - -} diff --git a/critterai/legacy/util-java/test/org/critterai/math/geom/Triangle3Tests.java b/critterai/legacy/util-java/test/org/critterai/math/geom/Triangle3Tests.java deleted file mode 100644 index 05ee41ec..00000000 --- a/critterai/legacy/util-java/test/org/critterai/math/geom/Triangle3Tests.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2010 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -package org.critterai.math.geom; - -import static org.junit.Assert.*; -import static org.critterai.math.geom.Triangle3.*; -import static org.critterai.math.MathUtil.*; -import static org.critterai.math.Vector3.*; - -import org.critterai.math.Vector3; -import org.critterai.math.geom.Triangle3; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for the {@link Triangle3} class. - */ -public class Triangle3Tests { - - // Clockwise wrapped - private static final float AX = 3; - private static final float AY = 2; - private static final float AZ = -1; - private static final float BX = 2; - private static final float BY = -1; - private static final float BZ = 1; - private static final float CX = 0; - private static final float CY = -1; - private static final float CZ = 0; - - @Before - public void setUp() - throws Exception - { - } - - @Test - public void testGetArea() - { - float expected = getHeronArea(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ); - float actual = getArea(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ); - assertTrue(sloppyEquals(actual, expected, 0.0001f)); - } - - @Test - public void testGetAreaComp() - { - float expected = getHeronArea(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ); - float actual = (float)Math.sqrt(getAreaComp(AX, AY, AZ, BX, BY, BZ, CX, CY, CZ))/2; - assertTrue(sloppyEquals(actual, expected, 0.0001f)); - } - - @Test - public void testGetNormalFloatVector3() - { - Vector3 v = new Vector3(); - assertTrue(v == getNormal(AX, AY, 0, BX, BY, 0, CX, CY, 0, v)); - assertTrue(v.sloppyEquals(0, 0, -1, 0.0001f)); - assertTrue(v == getNormal(AX, AY, 0, CX, CY, 0, BX, BY, 0, v)); - assertTrue(v.sloppyEquals(0, 0, 1, 0.0001f)); - assertTrue(v == getNormal(AX, 0, AZ, BX, 0, BZ, CX, 0, CZ, v)); - assertTrue(v.sloppyEquals(0, -1, 0, 0.0001f)); - assertTrue(v == getNormal(0, AY, AZ, 0, BY, BZ, 0, CY, CZ, v)); - assertTrue(v.sloppyEquals(1, 0, 0, 0.0001f)); - } - - @Test - public void testGetNormalArrayVector3() - { - float[] vertices = { - 5, 5, 5 - , AX, 0, AZ - , BX, 0, BZ - , CX, 0, CZ - , 9, 9, 9 - }; - Vector3 v = new Vector3(); - assertTrue(v == getNormal(vertices, 1, v)); - assertTrue(v.sloppyEquals(0, -1, 0, 0.0001f)); - } - - private float getHeronArea(float ax, float ay, float az - , float bx, float by, float bz - , float cx, float cy, float cz) - { - double a = Math.sqrt(getDistanceSq(AX, AY, AZ, BX, BY, BZ)); - double b = Math.sqrt(getDistanceSq(AX, AY, AZ, CX, CY, CZ)); - double c = Math.sqrt(getDistanceSq(CX, CY, CZ, BX, BY, BZ)); - double s = (a + b + c)/2; - return (float)Math.sqrt(s * (s - a) * (s - b) * (s - c)); - } - -} diff --git a/critterai/src/main/Assets/CAI/GlobalAssets/CAINavEditorSettings.asset b/critterai/src/main/Assets/CAI/GlobalAssets/CAINavEditorSettings.asset deleted file mode 100644 index 3d23912f..00000000 Binary files a/critterai/src/main/Assets/CAI/GlobalAssets/CAINavEditorSettings.asset and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/GlobalAssets/ReadMe.txt b/critterai/src/main/Assets/CAI/GlobalAssets/ReadMe.txt deleted file mode 100644 index 3b6b87f9..00000000 --- a/critterai/src/main/Assets/CAI/GlobalAssets/ReadMe.txt +++ /dev/null @@ -1,3 +0,0 @@ -This directory contains 'singleton' assets. (One per project.) Various -editors will use the assets in this directory, automatically creating them -if they don't exist. diff --git a/critterai/src/main/Assets/CAI/nav-u3d/CAIBakedNavmesh.cs b/critterai/src/main/Assets/CAI/nav-u3d/CAIBakedNavmesh.cs deleted file mode 100644 index ca55c833..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/CAIBakedNavmesh.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/CrowdAgentDebug.cs b/critterai/src/main/Assets/CAI/nav-u3d/CrowdAgentDebug.cs deleted file mode 100644 index e2488318..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/CrowdAgentDebug.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAIBakedNavmeshEditor.cs b/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAIBakedNavmeshEditor.cs deleted file mode 100644 index f172f52d..00000000 --- a/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAIBakedNavmeshEditor.cs +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2012 Stephen A. Pratt - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -using UnityEngine; -using UnityEditor; -using org.critterai.nav; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using org.critterai.u3d.editor; -using org.critterai.nav.u3d.editor; - -/// -/// editor. -/// -/// -[CustomEditor(typeof(CAIBakedNavmesh))] -public sealed class CAIBakedNavmeshEditor - : Editor -{ - /// - /// Controls behavior of the inspector. - /// - public override void OnInspectorGUI() - { - CAIBakedNavmesh targ = (CAIBakedNavmesh)target; - - EditorGUILayout.Separator(); - - EditorGUILayout.LabelField("Status", (targ.HasNavmesh ? "Has mesh" : "Empty")); - EditorGUILayout.LabelField("Version", targ.Version.ToString()); - EditorGUILayout.LabelField("Input Scene", NavEditorUtil.SceneDisplayName(targ.BuildInfo)); - - EditorGUILayout.Separator(); - - NavmeshSceneDraw.Instance.OnGUI(targ, "Show Mesh", true, true); - - EditorGUILayout.Separator(); - - EditorGUILayout.BeginHorizontal(); - - GUI.enabled = targ.HasNavmesh; - if (GUILayout.Button("Save")) - { - string filePath = EditorUtility.SaveFilePanel( - "Save Navigation Mesh" - , "" - , targ.name - , "navmesh"); - SaveMesh(targ, filePath); - } - GUI.enabled = true; - - if (GUILayout.Button("Load")) - { - string filePath = EditorUtility.OpenFilePanel( - "Select Serialized Navmesh" - , "" - , "navmesh"); - if (LoadMesh(targ, filePath)) - GUI.changed = true; - } - - EditorGUILayout.EndHorizontal(); - - if (targ.HasNavmesh) - { - EditorGUILayout.Separator(); - - if (GUILayout.Button("Log Mesh State")) - Debug.Log(targ.GetMeshReport()); - } - - EditorGUILayout.Separator(); - - if (GUI.changed) - EditorUtility.SetDirty(target); - } - - private static bool LoadMesh(CAIBakedNavmesh targ, string filePath) - { - string msg = null; - - if (filePath.Length == 0) - return false; - - FileStream fs = null; - BinaryFormatter formatter = new BinaryFormatter(); - - try - { - fs = new FileStream(filePath, FileMode.Open); - System.Object obj = formatter.Deserialize(fs); - - NavStatus status = targ.Load((byte[])obj, null); - if ((status & NavStatus.Sucess) == 0) - msg = status.ToString(); - } - catch (System.Exception ex) - { - msg = ex.Message; - } - finally - { - if (fs != null) - fs.Close(); - } - - if (msg != null) - { - Debug.LogError(targ.name + ": BakedNavmesh: Load bytes failed: " - + msg); - return false; - } - - return true; - } - - private static void SaveMesh(CAIBakedNavmesh targ, string filePath) - { - if (filePath.Length == 0 || !targ.HasNavmesh) - return; - - FileStream fs = null; - BinaryFormatter formatter = new BinaryFormatter(); - - try - { - fs = new FileStream(filePath, FileMode.Create); - formatter.Serialize(fs, targ.GetNavmesh().GetSerializedMesh()); - } - catch (System.Exception ex) - { - Debug.LogError(targ.name + ": BakedNavmesh: Save bytes failed: " - + ex.Message); - } - finally - { - if (fs != null) - fs.Close(); - } - - fs = new FileStream(filePath, FileMode.Open); - - System.Object obj = formatter.Deserialize(fs); - byte[] datas = (byte[])obj; - - string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(filePath); - filePath = filePath.Replace(fileNameWithoutExtension + ".", "srv_" + fileNameWithoutExtension + "."); - FileStream fs1 = new FileStream(filePath, FileMode.Create, FileAccess.Write); - fs1.Write(datas, 0, datas.Length); - fs1.Close(); - fs.Close(); - } - - [MenuItem(EditorUtil.NavAssetMenu + "Baked Navmesh", false, NavEditorUtil.NavAssetGroup)] - static void CreateAsset() - { - CAIBakedNavmesh item = EditorUtil.CreateAsset(NavEditorUtil.AssetLabel); - EditorUtility.FocusProjectWindow(); - Selection.activeObject = item; - } - - [MenuItem(EditorUtil.ViewMenu + "Hide Navmesh", true)] - static bool HideNavmeshValidate() - { - return NavmeshSceneDraw.Instance.IsShown(); - } - - [MenuItem(EditorUtil.ViewMenu + "Hide Navmesh", false, EditorUtil.ViewGroup)] - static void HideNavmesh() - { - NavmeshSceneDraw.Instance.Hide(); - } -} \ No newline at end of file diff --git a/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAINavEditorSettings.cs b/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAINavEditorSettings.cs deleted file mode 100644 index 5c594f94..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAINavEditorSettings.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAINavEditorSettingsEditor.cs b/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAINavEditorSettingsEditor.cs deleted file mode 100644 index 1020cc3f..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/Editor/CAINavEditorSettingsEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/Editor/NavEditorUtil.cs b/critterai/src/main/Assets/CAI/nav-u3d/Editor/NavEditorUtil.cs deleted file mode 100644 index d734330d..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/Editor/NavEditorUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/Editor/NavmeshSceneDraw.cs b/critterai/src/main/Assets/CAI/nav-u3d/Editor/NavmeshSceneDraw.cs deleted file mode 100644 index 38bc67fc..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/Editor/NavmeshSceneDraw.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/INavmeshData.cs b/critterai/src/main/Assets/CAI/nav-u3d/INavmeshData.cs deleted file mode 100644 index 8d070341..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/INavmeshData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/NavDebug.cs b/critterai/src/main/Assets/CAI/nav-u3d/NavDebug.cs deleted file mode 100644 index 5863ce0a..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/NavDebug.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/NavGroup.cs b/critterai/src/main/Assets/CAI/nav-u3d/NavGroup.cs deleted file mode 100644 index 553a3b9b..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/NavGroup.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav-u3d/NavmeshBuildInfo.cs b/critterai/src/main/Assets/CAI/nav-u3d/NavmeshBuildInfo.cs deleted file mode 100644 index 4eb748a8..00000000 Binary files a/critterai/src/main/Assets/CAI/nav-u3d/NavmeshBuildInfo.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CornerData.cs b/critterai/src/main/Assets/CAI/nav/CornerData.cs deleted file mode 100644 index 1f27c43d..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CornerData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdAgent.cs b/critterai/src/main/Assets/CAI/nav/CrowdAgent.cs deleted file mode 100644 index d397102a..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdAgent.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdAgentCoreData.cs b/critterai/src/main/Assets/CAI/nav/CrowdAgentCoreData.cs deleted file mode 100644 index f0232953..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdAgentCoreData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdAgentParams.cs b/critterai/src/main/Assets/CAI/nav/CrowdAgentParams.cs deleted file mode 100644 index ac4b0fb8..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdAgentParams.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdAgentState.cs b/critterai/src/main/Assets/CAI/nav/CrowdAgentState.cs deleted file mode 100644 index fc7bf1b8..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdAgentState.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdAvoidanceParams.cs b/critterai/src/main/Assets/CAI/nav/CrowdAvoidanceParams.cs deleted file mode 100644 index cba3e735..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdAvoidanceParams.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdLocalBoundaryData.cs b/critterai/src/main/Assets/CAI/nav/CrowdLocalBoundaryData.cs deleted file mode 100644 index 15a72617..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdLocalBoundaryData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdManager.cs b/critterai/src/main/Assets/CAI/nav/CrowdManager.cs deleted file mode 100644 index 9aa13228..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdManager.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdNeighbor.cs b/critterai/src/main/Assets/CAI/nav/CrowdNeighbor.cs deleted file mode 100644 index 016ecb57..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdNeighbor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdProximityGrid.cs b/critterai/src/main/Assets/CAI/nav/CrowdProximityGrid.cs deleted file mode 100644 index 0d9cf6fb..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdProximityGrid.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/CrowdUpdateFlags.cs b/critterai/src/main/Assets/CAI/nav/CrowdUpdateFlags.cs deleted file mode 100644 index bfed8e99..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/CrowdUpdateFlags.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavStatus.cs b/critterai/src/main/Assets/CAI/nav/NavStatus.cs deleted file mode 100644 index 891a60d3..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavStatus.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavUtil.cs b/critterai/src/main/Assets/CAI/nav/NavUtil.cs deleted file mode 100644 index f14f9fe8..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/Navmesh.cs b/critterai/src/main/Assets/CAI/nav/Navmesh.cs deleted file mode 100644 index fbe4f82a..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/Navmesh.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshBVNode.cs b/critterai/src/main/Assets/CAI/nav/NavmeshBVNode.cs deleted file mode 100644 index 82c58e90..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshBVNode.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshConnection.cs b/critterai/src/main/Assets/CAI/nav/NavmeshConnection.cs deleted file mode 100644 index 91f1786b..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshConnection.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshDetailMesh.cs b/critterai/src/main/Assets/CAI/nav/NavmeshDetailMesh.cs deleted file mode 100644 index db2b8ace..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshDetailMesh.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshLink.cs b/critterai/src/main/Assets/CAI/nav/NavmeshLink.cs deleted file mode 100644 index b0b5128d..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshLink.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshParams.cs b/critterai/src/main/Assets/CAI/nav/NavmeshParams.cs deleted file mode 100644 index 6f471b04..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshParams.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshPoint.cs b/critterai/src/main/Assets/CAI/nav/NavmeshPoint.cs deleted file mode 100644 index c664ad63..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshPoint.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshPoly.cs b/critterai/src/main/Assets/CAI/nav/NavmeshPoly.cs deleted file mode 100644 index d68445ed..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshPoly.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshPolyType.cs b/critterai/src/main/Assets/CAI/nav/NavmeshPolyType.cs deleted file mode 100644 index 97fdb746..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshPolyType.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshQuery.cs b/critterai/src/main/Assets/CAI/nav/NavmeshQuery.cs deleted file mode 100644 index 9f173b78..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshQuery.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshQueryFilter.cs b/critterai/src/main/Assets/CAI/nav/NavmeshQueryFilter.cs deleted file mode 100644 index f21016bc..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshQueryFilter.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshTile.cs b/critterai/src/main/Assets/CAI/nav/NavmeshTile.cs deleted file mode 100644 index d8e405c4..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshTile.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshTileBuildData.cs b/critterai/src/main/Assets/CAI/nav/NavmeshTileBuildData.cs deleted file mode 100644 index 4b76c47b..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshTileBuildData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshTileData.cs b/critterai/src/main/Assets/CAI/nav/NavmeshTileData.cs deleted file mode 100644 index cbece9dc..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshTileData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshTileExtract.cs b/critterai/src/main/Assets/CAI/nav/NavmeshTileExtract.cs deleted file mode 100644 index 98dfc496..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshTileExtract.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/NavmeshTileHeader.cs b/critterai/src/main/Assets/CAI/nav/NavmeshTileHeader.cs deleted file mode 100644 index 52239236..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/NavmeshTileHeader.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/OffMeshConnection.cs b/critterai/src/main/Assets/CAI/nav/OffMeshConnection.cs deleted file mode 100644 index 308f0282..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/OffMeshConnection.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/PathCorridor.cs b/critterai/src/main/Assets/CAI/nav/PathCorridor.cs deleted file mode 100644 index 9de800bf..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/PathCorridor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/PathCorridorData.cs b/critterai/src/main/Assets/CAI/nav/PathCorridorData.cs deleted file mode 100644 index dcdbe6d8..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/PathCorridorData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/WaypointFlag.cs b/critterai/src/main/Assets/CAI/nav/WaypointFlag.cs deleted file mode 100644 index bc988a15..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/WaypointFlag.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/CrowdAgentEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/CrowdAgentEx.cs deleted file mode 100644 index 83250502..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/CrowdAgentEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/CrowdManagerEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/CrowdManagerEx.cs deleted file mode 100644 index 9e3c3dae..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/CrowdManagerEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/CrowdProximityGridEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/CrowdProximityGridEx.cs deleted file mode 100644 index 422d3469..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/CrowdProximityGridEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/NavInteropUtil.cs b/critterai/src/main/Assets/CAI/nav/rcn/NavInteropUtil.cs deleted file mode 100644 index 14e3683b..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/NavInteropUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/NavmeshEx.cs deleted file mode 100644 index 4532ca4a..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshQueryEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/NavmeshQueryEx.cs deleted file mode 100644 index c01542aa..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshQueryEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshQueryFilterEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/NavmeshQueryFilterEx.cs deleted file mode 100644 index a017263b..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshQueryFilterEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshTileEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/NavmeshTileEx.cs deleted file mode 100644 index f9b52697..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/NavmeshTileEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nav/rcn/PathCorridorEx.cs b/critterai/src/main/Assets/CAI/nav/rcn/PathCorridorEx.cs deleted file mode 100644 index ea6a7cda..00000000 Binary files a/critterai/src/main/Assets/CAI/nav/rcn/PathCorridorEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/BoxAreaMarker.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/BoxAreaMarker.cs deleted file mode 100644 index 63b52d6a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/BoxAreaMarker.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/CylinderAreaMarker.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/CylinderAreaMarker.cs deleted file mode 100644 index 897dffd2..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/CylinderAreaMarker.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerCompiler.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerCompiler.cs deleted file mode 100644 index c9fafc1e..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerCompiler.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerCompilerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerCompilerEditor.cs deleted file mode 100644 index bc4c5174..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerCompilerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerEditor.cs deleted file mode 100644 index e671c195..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/AreaMarkerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/BoxAreaMarkerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/BoxAreaMarkerEditor.cs deleted file mode 100644 index 0c190bce..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/BoxAreaMarkerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/CylinderAreaMarkerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/CylinderAreaMarkerEditor.cs deleted file mode 100644 index 6f2db56d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/CylinderAreaMarkerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/NMGenComponentEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/NMGenComponentEditor.cs deleted file mode 100644 index f7e0e00f..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/NMGenComponentEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionCompiler.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionCompiler.cs deleted file mode 100644 index b1f23bf6..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionCompiler.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionCompilerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionCompilerEditor.cs deleted file mode 100644 index 322191fd..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionCompilerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionEditor.cs deleted file mode 100644 index dfbd0026..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/Editor/OFMConnectionEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/NMGenAreaMarker.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/NMGenAreaMarker.cs deleted file mode 100644 index 6302dace..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/NMGenAreaMarker.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/NMGenComponent.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/NMGenComponent.cs deleted file mode 100644 index 13769d0f..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/NMGenComponent.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/OFMConnection.cs b/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/OFMConnection.cs deleted file mode 100644 index 79611188..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-extras-u3d/OFMConnection.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MatchPredicate.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MatchPredicate.cs deleted file mode 100644 index f34a97bd..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MatchPredicate.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MatchType.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MatchType.cs deleted file mode 100644 index 8641e6f6..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MatchType.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MeshUtil.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MeshUtil.cs deleted file mode 100644 index 65ed3ed9..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/MeshUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMBEditorUtil.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMBEditorUtil.cs deleted file mode 100644 index acc91310..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMBEditorUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMBuildSettings.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMBuildSettings.cs deleted file mode 100644 index 7086b6d6..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMBuildSettings.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMGenConfig.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMGenConfig.cs deleted file mode 100644 index 47a4080a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMGenConfig.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMGenDebug.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMGenDebug.cs deleted file mode 100644 index 39ec1369..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NMGenDebug.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuild.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuild.cs deleted file mode 100644 index cc34871b..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuild.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildDelegate.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildDelegate.cs deleted file mode 100644 index 2661c84a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildDelegate.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildEditor.cs deleted file mode 100644 index 46ff3fa4..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildHelper.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildHelper.cs deleted file mode 100644 index af40801c..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildHelper.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildManager.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildManager.cs deleted file mode 100644 index f4cebb5d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildManager.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildState.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildState.cs deleted file mode 100644 index c2791e6b..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildState.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildType.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildType.cs deleted file mode 100644 index 6a32c893..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/NavmeshBuildType.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TerrainUtil.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TerrainUtil.cs deleted file mode 100644 index dd6cdd7c..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TerrainUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildData.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildData.cs deleted file mode 100644 index bb124400..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildDataItem.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildDataItem.cs deleted file mode 100644 index 7b8196a5..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildDataItem.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildState.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildState.cs deleted file mode 100644 index 72b6a861..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileBuildState.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileSelection.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileSelection.cs deleted file mode 100644 index 24934261..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/TileSelection.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/UnityBuildContext.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/UnityBuildContext.cs deleted file mode 100644 index a877a179..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/UnityBuildContext.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildControl.cs deleted file mode 100644 index 4cc477aa..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildController.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildController.cs deleted file mode 100644 index 700e9a60..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildController.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildProcessor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildProcessor.cs deleted file mode 100644 index 3b72c1d9..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildProcessor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildSelector.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildSelector.cs deleted file mode 100644 index e4fb22fd..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuildSelector.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuilderControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuilderControl.cs deleted file mode 100644 index 7fbe54d7..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/BuilderControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/ControlContext.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/ControlContext.cs deleted file mode 100644 index f447c841..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/ControlContext.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/ControlUtil.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/ControlUtil.cs deleted file mode 100644 index 680e323b..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/ControlUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/CoreFailureControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/CoreFailureControl.cs deleted file mode 100644 index 680d8527..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/CoreFailureControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/FailureControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/FailureControl.cs deleted file mode 100644 index 11e55e3a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/FailureControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/IBuildControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/IBuildControl.cs deleted file mode 100644 index 9468710d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/IBuildControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/InputCompileControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/InputCompileControl.cs deleted file mode 100644 index b400bb79..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/InputCompileControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/MiniInputCompile.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/MiniInputCompile.cs deleted file mode 100644 index 378c888f..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/MiniInputCompile.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/MultiTileBuildControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/MultiTileBuildControl.cs deleted file mode 100644 index 349e5d04..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/MultiTileBuildControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/NMGenConfigControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/NMGenConfigControl.cs deleted file mode 100644 index c5837d95..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/NMGenConfigControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/SingleTileBuildControl.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/SingleTileBuildControl.cs deleted file mode 100644 index 7bfc4d13..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/controls/SingleTileBuildControl.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/AreaFlagDef.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/AreaFlagDef.cs deleted file mode 100644 index a3cd0a36..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/AreaFlagDef.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/AreaFlagDefEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/AreaFlagDefEditor.cs deleted file mode 100644 index 730a3fb4..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/AreaFlagDefEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderCompiler.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderCompiler.cs deleted file mode 100644 index b073aa10..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderCompiler.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderCompilerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderCompilerEditor.cs deleted file mode 100644 index e90e5fc6..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderCompilerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderHelper.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderHelper.cs deleted file mode 100644 index ab0045c2..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ColliderHelper.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/DefaultAreaDef.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/DefaultAreaDef.cs deleted file mode 100644 index 674c1752..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/DefaultAreaDef.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/DefaultAreaDefEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/DefaultAreaDefEditor.cs deleted file mode 100644 index d7cc19e7..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/DefaultAreaDefEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/IInputBuildProcessor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/IInputBuildProcessor.cs deleted file mode 100644 index ea44f77c..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/IInputBuildProcessor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ISceneQuery.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ISceneQuery.cs deleted file mode 100644 index ac3b2b57..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/ISceneQuery.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputAssets.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputAssets.cs deleted file mode 100644 index 5dcd8f9a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputAssets.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildContext.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildContext.cs deleted file mode 100644 index d8401093..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildContext.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildInfo.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildInfo.cs deleted file mode 100644 index a6e2ad2b..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildInfo.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildOption.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildOption.cs deleted file mode 100644 index 46b63e87..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildOption.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildState.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildState.cs deleted file mode 100644 index 88a5678c..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildState.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildTask.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildTask.cs deleted file mode 100644 index 78a28f76..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuildTask.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuilder.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuilder.cs deleted file mode 100644 index 279454bd..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/InputBuilder.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshAreaDef.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshAreaDef.cs deleted file mode 100644 index 01ecdc2e..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshAreaDef.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshAreaDefEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshAreaDefEditor.cs deleted file mode 100644 index bbffe855..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshAreaDefEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshColocationOption.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshColocationOption.cs deleted file mode 100644 index e0884101..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshColocationOption.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshCompiler.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshCompiler.cs deleted file mode 100644 index aa2f4725..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshCompiler.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshCompilerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshCompilerEditor.cs deleted file mode 100644 index 86db2e74..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshCompilerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshInputFilter.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshInputFilter.cs deleted file mode 100644 index a5837be5..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshInputFilter.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshInputFilterEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshInputFilterEditor.cs deleted file mode 100644 index e43e5d2a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/MeshInputFilterEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/StaticFilter.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/StaticFilter.cs deleted file mode 100644 index 2e9fef3d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/StaticFilter.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/StaticFilterEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/StaticFilterEditor.cs deleted file mode 100644 index d0894008..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/StaticFilterEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagAreaDef.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagAreaDef.cs deleted file mode 100644 index 28c6aee0..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagAreaDef.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagAreaDefEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagAreaDefEditor.cs deleted file mode 100644 index 8433f53f..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagAreaDefEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagInputFilter.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagInputFilter.cs deleted file mode 100644 index be72ee88..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagInputFilter.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagInputFilterEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagInputFilterEditor.cs deleted file mode 100644 index b8b2947c..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagInputFilterEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagSceneQuery.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagSceneQuery.cs deleted file mode 100644 index 7f2787cf..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagSceneQuery.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagSceneQueryEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagSceneQueryEditor.cs deleted file mode 100644 index c21b3a6c..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TagSceneQueryEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TerrainCompiler.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TerrainCompiler.cs deleted file mode 100644 index ff13382d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TerrainCompiler.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TerrainCompilerEditor.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TerrainCompilerEditor.cs deleted file mode 100644 index 0215e456..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/input/TerrainCompilerEditor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/DebugViewContext.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/DebugViewContext.cs deleted file mode 100644 index f88f7e77..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/DebugViewContext.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/InputDebugView.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/InputDebugView.cs deleted file mode 100644 index 0f5da75e..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/InputDebugView.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/MeshDebugOption.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/MeshDebugOption.cs deleted file mode 100644 index a7f50bdc..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/MeshDebugOption.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/MeshDebugView.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/MeshDebugView.cs deleted file mode 100644 index c2443157..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/MeshDebugView.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/SelectionDebugView.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/SelectionDebugView.cs deleted file mode 100644 index 84a128ab..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/SelectionDebugView.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/TileGridDebugView.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/TileGridDebugView.cs deleted file mode 100644 index 55472f0e..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/TileGridDebugView.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/ViewOption.cs b/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/ViewOption.cs deleted file mode 100644 index 7aa55c7e..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild-u3d/Editor/views/ViewOption.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTask.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTask.cs deleted file mode 100644 index 30625db3..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTask.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTaskProcessor.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTaskProcessor.cs deleted file mode 100644 index 6a2a8dea..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTaskProcessor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTaskState.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTaskState.cs deleted file mode 100644 index f4522db7..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/BuildTaskState.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/ConnectionSet.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/ConnectionSet.cs deleted file mode 100644 index d2cd8c41..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/ConnectionSet.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/ConnectionSetCompiler.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/ConnectionSetCompiler.cs deleted file mode 100644 index 3f237ac7..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/ConnectionSetCompiler.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/IBuildTask.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/IBuildTask.cs deleted file mode 100644 index d0153f2c..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/IBuildTask.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/IncrementalBuilder.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/IncrementalBuilder.cs deleted file mode 100644 index 2167ba04..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/IncrementalBuilder.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometry.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometry.cs deleted file mode 100644 index 0dddd7b9..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometry.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometryBuilder.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometryBuilder.cs deleted file mode 100644 index e6c49e00..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometryBuilder.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometryCompiler.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometryCompiler.cs deleted file mode 100644 index fe60b0c7..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/InputGeometryCompiler.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMBuild.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/NMBuild.cs deleted file mode 100644 index f11053d3..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMBuild.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenAssetFlag.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenAssetFlag.cs deleted file mode 100644 index 017a92cc..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenAssetFlag.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenAssets.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenAssets.cs deleted file mode 100644 index 61882f36..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenAssets.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenContext.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenContext.cs deleted file mode 100644 index 02eef9ac..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenContext.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenFlag.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenFlag.cs deleted file mode 100644 index 3256c3cb..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenFlag.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenState.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenState.cs deleted file mode 100644 index 30a28501..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenState.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenTask.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenTask.cs deleted file mode 100644 index 8868bad0..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/NMGenTask.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/ProcessorSet.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/ProcessorSet.cs deleted file mode 100644 index d0fd85ed..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/ProcessorSet.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileBuildAssets.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/TileBuildAssets.cs deleted file mode 100644 index fbcc09a6..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileBuildAssets.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileBuildTask.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/TileBuildTask.cs deleted file mode 100644 index dac8b8bd..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileBuildTask.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileSetDefinition.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/TileSetDefinition.cs deleted file mode 100644 index e7c19107..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileSetDefinition.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileZone.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/TileZone.cs deleted file mode 100644 index 002e03d3..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/TileZone.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/ApplyPolygonFlags.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/ApplyPolygonFlags.cs deleted file mode 100644 index 6269750d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/ApplyPolygonFlags.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaBoxMarker.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaBoxMarker.cs deleted file mode 100644 index 23234c36..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaBoxMarker.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaConvexMarker.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaConvexMarker.cs deleted file mode 100644 index 53973be8..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaConvexMarker.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaCylinderMarker.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaCylinderMarker.cs deleted file mode 100644 index c09231a4..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaCylinderMarker.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaFlagMapper.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaFlagMapper.cs deleted file mode 100644 index 0e0238fa..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaFlagMapper.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaMarker.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaMarker.cs deleted file mode 100644 index f37e3635..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/AreaMarker.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/FilterLedgeSpans.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/FilterLedgeSpans.cs deleted file mode 100644 index e1ad3fd6..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/FilterLedgeSpans.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/FilterLowHeightSpans.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/FilterLowHeightSpans.cs deleted file mode 100644 index f6e2da0d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/FilterLowHeightSpans.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/INMGenProcessor.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/INMGenProcessor.cs deleted file mode 100644 index 2b082804..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/INMGenProcessor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/LowObstaclesWalkable.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/LowObstaclesWalkable.cs deleted file mode 100644 index f0fcbb2d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/LowObstaclesWalkable.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/NMGenProcessor.cs b/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/NMGenProcessor.cs deleted file mode 100644 index 3d7f8b9d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmbuild/Editor/processors/NMGenProcessor.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/BuildContext.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/BuildContext.cs deleted file mode 100644 index eec7eb48..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/BuildContext.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriMesh.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriMesh.cs deleted file mode 100644 index 7fd43980..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriMesh.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriMeshBuilder.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriMeshBuilder.cs deleted file mode 100644 index 5ed51ed3..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriMeshBuilder.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriNode.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriNode.cs deleted file mode 100644 index c6b0490b..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/ChunkyTriNode.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/CompactCell.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/CompactCell.cs deleted file mode 100644 index 8efec324..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/CompactCell.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/CompactHeightfield.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/CompactHeightfield.cs deleted file mode 100644 index 898773e9..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/CompactHeightfield.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/CompactSpan.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/CompactSpan.cs deleted file mode 100644 index 34877af4..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/CompactSpan.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/Contour.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/Contour.cs deleted file mode 100644 index d9e73698..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/Contour.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/ContourBuildFlags.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/ContourBuildFlags.cs deleted file mode 100644 index bf8d0136..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/ContourBuildFlags.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/ContourFlags.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/ContourFlags.cs deleted file mode 100644 index 3078c827..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/ContourFlags.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/ContourSet.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/ContourSet.cs deleted file mode 100644 index b3599910..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/ContourSet.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/HeightFieldLayer.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/HeightFieldLayer.cs deleted file mode 100644 index ad91b5f8..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/HeightFieldLayer.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/HeightFieldLayerSet.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/HeightFieldLayerSet.cs deleted file mode 100644 index d82978ec..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/HeightFieldLayerSet.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/Heightfield.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/Heightfield.cs deleted file mode 100644 index 1489804a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/Heightfield.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/HeightfieldSpan.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/HeightfieldSpan.cs deleted file mode 100644 index 2645412d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/HeightfieldSpan.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/NMGen.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/NMGen.cs deleted file mode 100644 index 87fbcd56..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/NMGen.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/NMGenParams.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/NMGenParams.cs deleted file mode 100644 index 5279610d..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/NMGenParams.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/NMGenTileParams.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/NMGenTileParams.cs deleted file mode 100644 index 662029af..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/NMGenTileParams.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMesh.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMesh.cs deleted file mode 100644 index 09da2b20..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMesh.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshData.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshData.cs deleted file mode 100644 index 45ccb336..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshDetail.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshDetail.cs deleted file mode 100644 index df12cc6a..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshDetail.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshDetailData.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshDetailData.cs deleted file mode 100644 index f9bd40c9..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/PolyMeshDetailData.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/BuildContextEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/BuildContextEx.cs deleted file mode 100644 index f55dcaf8..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/BuildContextEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/CompactHeightfieldEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/CompactHeightfieldEx.cs deleted file mode 100644 index 72bdef1b..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/CompactHeightfieldEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/ContourSetEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/ContourSetEx.cs deleted file mode 100644 index ec381b6b..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/ContourSetEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/HeightfieldEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/HeightfieldEx.cs deleted file mode 100644 index 0195d74f..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/HeightfieldEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/HeightfieldLayerSetEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/HeightfieldLayerSetEx.cs deleted file mode 100644 index 3aeff7bd..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/HeightfieldLayerSetEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/NMGenEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/NMGenEx.cs deleted file mode 100644 index befb9075..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/NMGenEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/NMGenInteropUtil.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/NMGenInteropUtil.cs deleted file mode 100644 index effcccb5..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/NMGenInteropUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/PolyMeshDetailEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/PolyMeshDetailEx.cs deleted file mode 100644 index 18a3b141..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/PolyMeshDetailEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/PolyMeshEx.cs b/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/PolyMeshEx.cs deleted file mode 100644 index 962a1712..00000000 Binary files a/critterai/src/main/Assets/CAI/nmgen/Editor/rcn/PolyMeshEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/nmgen/ReadMe.txt b/critterai/src/main/Assets/CAI/nmgen/ReadMe.txt deleted file mode 100644 index 35144b8e..00000000 --- a/critterai/src/main/Assets/CAI/nmgen/ReadMe.txt +++ /dev/null @@ -1,7 +0,0 @@ -The NMGen source is located in the editor directory -since it is normally only used in the Unity Editor. -This layout prevents code bloat in the Project build. - -Just move the source to this directory if NMGen is -required at runtime. - diff --git a/critterai/src/main/Assets/CAI/util-u3d/ColorUtil.cs b/critterai/src/main/Assets/CAI/util-u3d/ColorUtil.cs deleted file mode 100644 index 0ce3cb4c..00000000 Binary files a/critterai/src/main/Assets/CAI/util-u3d/ColorUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util-u3d/DebugDraw.cs b/critterai/src/main/Assets/CAI/util-u3d/DebugDraw.cs deleted file mode 100644 index 5f8ab30d..00000000 Binary files a/critterai/src/main/Assets/CAI/util-u3d/DebugDraw.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util-u3d/Editor/EditorUtil.cs b/critterai/src/main/Assets/CAI/util-u3d/Editor/EditorUtil.cs deleted file mode 100644 index afb7c3a8..00000000 Binary files a/critterai/src/main/Assets/CAI/util-u3d/Editor/EditorUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/ArrayUtil.cs b/critterai/src/main/Assets/CAI/util/ArrayUtil.cs deleted file mode 100644 index 33b27962..00000000 Binary files a/critterai/src/main/Assets/CAI/util/ArrayUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/CAIUtil.cs b/critterai/src/main/Assets/CAI/util/CAIUtil.cs deleted file mode 100644 index c2bbe325..00000000 Binary files a/critterai/src/main/Assets/CAI/util/CAIUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/IPriorityItem.cs b/critterai/src/main/Assets/CAI/util/IPriorityItem.cs deleted file mode 100644 index 5d831768..00000000 Binary files a/critterai/src/main/Assets/CAI/util/IPriorityItem.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/MathUtil.cs b/critterai/src/main/Assets/CAI/util/MathUtil.cs deleted file mode 100644 index 3fe01652..00000000 Binary files a/critterai/src/main/Assets/CAI/util/MathUtil.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/PriorityComparer.cs b/critterai/src/main/Assets/CAI/util/PriorityComparer.cs deleted file mode 100644 index 97c02305..00000000 Binary files a/critterai/src/main/Assets/CAI/util/PriorityComparer.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/Vector2.cs b/critterai/src/main/Assets/CAI/util/Vector2.cs deleted file mode 100644 index 4a5002ae..00000000 Binary files a/critterai/src/main/Assets/CAI/util/Vector2.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/Vector2Util.cs b/critterai/src/main/Assets/CAI/util/Vector2Util.cs deleted file mode 100644 index edf6699d..00000000 Binary files a/critterai/src/main/Assets/CAI/util/Vector2Util.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/Vector3.cs b/critterai/src/main/Assets/CAI/util/Vector3.cs deleted file mode 100644 index 0c30fb5f..00000000 Binary files a/critterai/src/main/Assets/CAI/util/Vector3.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/Vector3Util.cs b/critterai/src/main/Assets/CAI/util/Vector3Util.cs deleted file mode 100644 index 46356830..00000000 Binary files a/critterai/src/main/Assets/CAI/util/Vector3Util.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/Circle.cs b/critterai/src/main/Assets/CAI/util/geom/Circle.cs deleted file mode 100644 index 79c0bb03..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/Circle.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/Line2.cs b/critterai/src/main/Assets/CAI/util/geom/Line2.cs deleted file mode 100644 index 7c3eb5fb..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/Line2.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/LineRelType.cs b/critterai/src/main/Assets/CAI/util/geom/LineRelType.cs deleted file mode 100644 index 6128266c..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/LineRelType.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/PointLineRelType.cs b/critterai/src/main/Assets/CAI/util/geom/PointLineRelType.cs deleted file mode 100644 index 03ef0f49..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/PointLineRelType.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/Polygon3.cs b/critterai/src/main/Assets/CAI/util/geom/Polygon3.cs deleted file mode 100644 index 33a137f8..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/Polygon3.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/Rectangle2.cs b/critterai/src/main/Assets/CAI/util/geom/Rectangle2.cs deleted file mode 100644 index a61ab5f8..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/Rectangle2.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/Triangle2.cs b/critterai/src/main/Assets/CAI/util/geom/Triangle2.cs deleted file mode 100644 index d45d2eb4..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/Triangle2.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/Triangle3.cs b/critterai/src/main/Assets/CAI/util/geom/Triangle3.cs deleted file mode 100644 index ac6d9bb7..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/Triangle3.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/TriangleMesh.cs b/critterai/src/main/Assets/CAI/util/geom/TriangleMesh.cs deleted file mode 100644 index 3409faf9..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/TriangleMesh.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/geom/Wavefront.cs b/critterai/src/main/Assets/CAI/util/geom/Wavefront.cs deleted file mode 100644 index ea46a833..00000000 Binary files a/critterai/src/main/Assets/CAI/util/geom/Wavefront.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/interop/AllocType.cs b/critterai/src/main/Assets/CAI/util/interop/AllocType.cs deleted file mode 100644 index 26849fb3..00000000 Binary files a/critterai/src/main/Assets/CAI/util/interop/AllocType.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/interop/IManagedObject.cs b/critterai/src/main/Assets/CAI/util/interop/IManagedObject.cs deleted file mode 100644 index 40e18a76..00000000 Binary files a/critterai/src/main/Assets/CAI/util/interop/IManagedObject.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/interop/ManagedObject.cs b/critterai/src/main/Assets/CAI/util/interop/ManagedObject.cs deleted file mode 100644 index 0068c369..00000000 Binary files a/critterai/src/main/Assets/CAI/util/interop/ManagedObject.cs and /dev/null differ diff --git a/critterai/src/main/Assets/CAI/util/interop/UtilEx.cs b/critterai/src/main/Assets/CAI/util/interop/UtilEx.cs deleted file mode 100644 index 173d16f8..00000000 Binary files a/critterai/src/main/Assets/CAI/util/interop/UtilEx.cs and /dev/null differ diff --git a/critterai/src/main/Assets/Plugins/ReadMe.txt b/critterai/src/main/Assets/Plugins/ReadMe.txt deleted file mode 100644 index 4104f2f3..00000000 --- a/critterai/src/main/Assets/Plugins/ReadMe.txt +++ /dev/null @@ -1,5 +0,0 @@ -Add the following plugins to this directory if you are using it as the basis for -a Unity project: - -cai-nav-rcn.dll -cai-nmgen-rcn.dll diff --git a/critterai/src/main/ReadMe.txt b/critterai/src/main/ReadMe.txt deleted file mode 100644 index dce23f6e..00000000 --- a/critterai/src/main/ReadMe.txt +++ /dev/null @@ -1,5 +0,0 @@ -The source code in the 'Assets' directory structure is in the same -layout it should be if deployed directly to a Unity project. -(I.e. The 'Assets/CAI' directory can be dragged and dropped into -a Unity project.) The porject documentation contains some important -notes when using a source distribution. diff --git a/critterai/src/nav-rcn/Detour/Include/DetourAlloc.h b/critterai/src/nav-rcn/Detour/Include/DetourAlloc.h deleted file mode 100644 index e814b62a..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourAlloc.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURALLOCATOR_H -#define DETOURALLOCATOR_H - -/// Provides hint values to the memory allocator on how long the -/// memory is expected to be used. -enum dtAllocHint -{ - DT_ALLOC_PERM, ///< Memory persist after a function call. - DT_ALLOC_TEMP ///< Memory used temporarily within a function. -}; - -/// A memory allocation function. -// @param[in] size The size, in bytes of memory, to allocate. -// @param[in] rcAllocHint A hint to the allocator on how long the memory is expected to be in use. -// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. -/// @see dtAllocSetCustom -typedef void* (dtAllocFunc)(int size, dtAllocHint hint); - -/// A memory deallocation function. -/// @param[in] ptr A pointer to a memory block previously allocated using #dtAllocFunc. -/// @see dtAllocSetCustom -typedef void (dtFreeFunc)(void* ptr); - -/// Sets the base custom allocation functions to be used by Detour. -/// @param[in] allocFunc The memory allocation function to be used by #dtAlloc -/// @param[in] freeFunc The memory de-allocation function to be used by #dtFree -void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc); - -/// Allocates a memory block. -/// @param[in] size The size, in bytes of memory, to allocate. -/// @param[in] hint A hint to the allocator on how long the memory is expected to be in use. -/// @return A pointer to the beginning of the allocated memory block, or null if the allocation failed. -/// @see dtFree -void* dtAlloc(int size, dtAllocHint hint); - -/// Deallocates a memory block. -/// @param[in] ptr A pointer to a memory block previously allocated using #dtAlloc. -/// @see dtAlloc -void dtFree(void* ptr); - -#endif diff --git a/critterai/src/nav-rcn/Detour/Include/DetourAssert.h b/critterai/src/nav-rcn/Detour/Include/DetourAssert.h deleted file mode 100644 index 3cf65228..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourAssert.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURASSERT_H -#define DETOURASSERT_H - -// Note: This header file's only purpose is to include define assert. -// Feel free to change the file and include your own implementation instead. - -#ifdef NDEBUG -// From http://cnicholson.net/2009/02/stupid-c-tricks-adventures-in-assert/ -# define dtAssert(x) do { (void)sizeof(x); } while((void)(__LINE__==-1),false) -#else -# include -# define dtAssert assert -#endif - -#endif // DETOURASSERT_H diff --git a/critterai/src/nav-rcn/Detour/Include/DetourCommon.h b/critterai/src/nav-rcn/Detour/Include/DetourCommon.h deleted file mode 100644 index ed7c5149..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourCommon.h +++ /dev/null @@ -1,530 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURCOMMON_H -#define DETOURCOMMON_H - -/** -@defgroup detour Detour - -Members in this module are used to create, manipulate, and query navigation -meshes. - -@note This is a summary list of members. Use the index or search -feature to find minor members. -*/ - -/// @name General helper functions -/// @{ - -/// Swaps the values of the two parameters. -/// @param[in,out] a Value A -/// @param[in,out] b Value B -template inline void dtSwap(T& a, T& b) { T t = a; a = b; b = t; } - -/// Returns the minimum of two values. -/// @param[in] a Value A -/// @param[in] b Value B -/// @return The minimum of the two values. -template inline T dtMin(T a, T b) { return a < b ? a : b; } - -/// Returns the maximum of two values. -/// @param[in] a Value A -/// @param[in] b Value B -/// @return The maximum of the two values. -template inline T dtMax(T a, T b) { return a > b ? a : b; } - -/// Returns the absolute value. -/// @param[in] a The value. -/// @return The absolute value of the specified value. -template inline T dtAbs(T a) { return a < 0 ? -a : a; } - -/// Returns the square of the value. -/// @param[in] a The value. -/// @return The square of the value. -template inline T dtSqr(T a) { return a*a; } - -/// Clamps the value to the specified range. -/// @param[in] v The value to clamp. -/// @param[in] mn The minimum permitted return value. -/// @param[in] mx The maximum permitted return value. -/// @return The value, clamped to the specified range. -template inline T dtClamp(T v, T mn, T mx) { return v < mn ? mn : (v > mx ? mx : v); } - -/// Returns the square root of the value. -/// @param[in] x The value. -/// @return The square root of the vlaue. -float dtSqrt(float x); - -/// @} -/// @name Vector helper functions. -/// @{ - -/// Derives the cross product of two vectors. (@p v1 x @p v2) -/// @param[out] dest The cross product. [(x, y, z)] -/// @param[in] v1 A Vector [(x, y, z)] -/// @param[in] v2 A vector [(x, y, z)] -inline void dtVcross(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[1]*v2[2] - v1[2]*v2[1]; - dest[1] = v1[2]*v2[0] - v1[0]*v2[2]; - dest[2] = v1[0]*v2[1] - v1[1]*v2[0]; -} - -/// Derives the dot product of two vectors. (@p v1 . @p v2) -/// @param[in] v1 A Vector [(x, y, z)] -/// @param[in] v2 A vector [(x, y, z)] -/// @return The dot product. -inline float dtVdot(const float* v1, const float* v2) -{ - return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; -} - -/// Performs a scaled vector addition. (@p v1 + (@p v2 * @p s)) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to scale and add to @p v1. [(x, y, z)] -/// @param[in] s The amount to scale @p v2 by before adding to @p v1. -inline void dtVmad(float* dest, const float* v1, const float* v2, const float s) -{ - dest[0] = v1[0]+v2[0]*s; - dest[1] = v1[1]+v2[1]*s; - dest[2] = v1[2]+v2[2]*s; -} - -/// Performs a linear interpolation between two vectors. (@p v1 toward @p v2) -/// @param[out] dest The result vector. [(x, y, x)] -/// @param[in] v1 The starting vector. -/// @param[in] v2 The destination vector. -/// @param[in] t The interpolation factor. [Limits: 0 <= value <= 1.0] -inline void dtVlerp(float* dest, const float* v1, const float* v2, const float t) -{ - dest[0] = v1[0]+(v2[0]-v1[0])*t; - dest[1] = v1[1]+(v2[1]-v1[1])*t; - dest[2] = v1[2]+(v2[2]-v1[2])*t; -} - -/// Performs a vector addition. (@p v1 + @p v2) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to add to @p v1. [(x, y, z)] -inline void dtVadd(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]+v2[0]; - dest[1] = v1[1]+v2[1]; - dest[2] = v1[2]+v2[2]; -} - -/// Performs a vector subtraction. (@p v1 - @p v2) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v1 The base vector. [(x, y, z)] -/// @param[in] v2 The vector to subtract from @p v1. [(x, y, z)] -inline void dtVsub(float* dest, const float* v1, const float* v2) -{ - dest[0] = v1[0]-v2[0]; - dest[1] = v1[1]-v2[1]; - dest[2] = v1[2]-v2[2]; -} - -/// Scales the vector by the specified value. (@p v * @p t) -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] v The vector to scale. [(x, y, z)] -/// @param[in] t The scaling factor. -inline void dtVscale(float* dest, const float* v, const float t) -{ - dest[0] = v[0]*t; - dest[1] = v[1]*t; - dest[2] = v[2]*t; -} - -/// Selects the minimum value of each element from the specified vectors. -/// @param[in,out] mn A vector. (Will be updated with the result.) [(x, y, z)] -/// @param[in] v A vector. [(x, y, z)] -inline void dtVmin(float* mn, const float* v) -{ - mn[0] = dtMin(mn[0], v[0]); - mn[1] = dtMin(mn[1], v[1]); - mn[2] = dtMin(mn[2], v[2]); -} - -/// Selects the maximum value of each element from the specified vectors. -/// @param[in,out] mx A vector. (Will be updated with the result.) [(x, y, z)] -/// @param[in] v A vector. [(x, y, z)] -inline void dtVmax(float* mx, const float* v) -{ - mx[0] = dtMax(mx[0], v[0]); - mx[1] = dtMax(mx[1], v[1]); - mx[2] = dtMax(mx[2], v[2]); -} - -/// Sets the vector elements to the specified values. -/// @param[out] dest The result vector. [(x, y, z)] -/// @param[in] x The x-value of the vector. -/// @param[in] y The y-value of the vector. -/// @param[in] z The z-value of the vector. -inline void dtVset(float* dest, const float x, const float y, const float z) -{ - dest[0] = x; dest[1] = y; dest[2] = z; -} - -/// Performs a vector copy. -/// @param[out] dest The result. [(x, y, z)] -/// @param[in] a The vector to copy. [(x, y, z)] -inline void dtVcopy(float* dest, const float* a) -{ - dest[0] = a[0]; - dest[1] = a[1]; - dest[2] = a[2]; -} - -/// Derives the scalar length of the vector. -/// @param[in] v The vector. [(x, y, z)] -/// @return The scalar length of the vector. -inline float dtVlen(const float* v) -{ - return dtSqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]); -} - -/// Derives the square of the scalar length of the vector. (len * len) -/// @param[in] v The vector. [(x, y, z)] -/// @return The square of the scalar length of the vector. -inline float dtVlenSqr(const float* v) -{ - return v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; -} - -/// Returns the distance between two points. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The distance between the two points. -inline float dtVdist(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; - const float dz = v2[2] - v1[2]; - return dtSqrt(dx*dx + dy*dy + dz*dz); -} - -/// Returns the square of the distance between two points. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The square of the distance between the two points. -inline float dtVdistSqr(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; - const float dz = v2[2] - v1[2]; - return dx*dx + dy*dy + dz*dz; -} - -/// Derives the distance between the specified points on the xz-plane. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The distance between the point on the xz-plane. -/// -/// The vectors are projected onto the xz-plane, so the y-values are ignored. -inline float dtVdist2D(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dz = v2[2] - v1[2]; - return dtSqrt(dx*dx + dz*dz); -} - -/// Derives the square of the distance between the specified points on the xz-plane. -/// @param[in] v1 A point. [(x, y, z)] -/// @param[in] v2 A point. [(x, y, z)] -/// @return The square of the distance between the point on the xz-plane. -inline float dtVdist2DSqr(const float* v1, const float* v2) -{ - const float dx = v2[0] - v1[0]; - const float dz = v2[2] - v1[2]; - return dx*dx + dz*dz; -} - -/// Normalizes the vector. -/// @param[in,out] v The vector to normalize. [(x, y, z)] -inline void dtVnormalize(float* v) -{ - float d = 1.0f / dtSqrt(dtSqr(v[0]) + dtSqr(v[1]) + dtSqr(v[2])); - v[0] *= d; - v[1] *= d; - v[2] *= d; -} - -/// Performs a 'sloppy' colocation check of the specified points. -/// @param[in] p0 A point. [(x, y, z)] -/// @param[in] p1 A point. [(x, y, z)] -/// @return True if the points are considered to be at the same location. -/// -/// Basically, this function will return true if the specified points are -/// close enough to eachother to be considered colocated. -inline bool dtVequal(const float* p0, const float* p1) -{ - static const float thr = dtSqr(1.0f/16384.0f); - const float d = dtVdistSqr(p0, p1); - return d < thr; -} - -/// Derives the dot product of two vectors on the xz-plane. (@p u . @p v) -/// @param[in] u A vector [(x, y, z)] -/// @param[in] v A vector [(x, y, z)] -/// @return The dot product on the xz-plane. -/// -/// The vectors are projected onto the xz-plane, so the y-values are ignored. -inline float dtVdot2D(const float* u, const float* v) -{ - return u[0]*v[0] + u[2]*v[2]; -} - -/// Derives the xz-plane 2D perp product of the two vectors. (uz*vx - ux*vz) -/// @param[in] u The LHV vector [(x, y, z)] -/// @param[in] v The RHV vector [(x, y, z)] -/// @return The dot product on the xz-plane. -/// -/// The vectors are projected onto the xz-plane, so the y-values are ignored. -inline float dtVperp2D(const float* u, const float* v) -{ - return u[2]*v[0] - u[0]*v[2]; -} - -/// @} -/// @name Computational geometry helper functions. -/// @{ - -/// Derives the signed xz-plane area of the triangle ABC, or the relationship of line AB to point C. -/// @param[in] a Vertex A. [(x, y, z)] -/// @param[in] b Vertex B. [(x, y, z)] -/// @param[in] c Vertex C. [(x, y, z)] -/// @return The signed xz-plane area of the triangle. -inline float dtTriArea2D(const float* a, const float* b, const float* c) -{ - const float abx = b[0] - a[0]; - const float abz = b[2] - a[2]; - const float acx = c[0] - a[0]; - const float acz = c[2] - a[2]; - return acx*abz - abx*acz; -} - -/// Determines if two axis-aligned bounding boxes overlap. -/// @param[in] amin Minimum bounds of box A. [(x, y, z)] -/// @param[in] amax Maximum bounds of box A. [(x, y, z)] -/// @param[in] bmin Minimum bounds of box B. [(x, y, z)] -/// @param[in] bmax Maximum bounds of box B. [(x, y, z)] -/// @return True if the two AABB's overlap. -/// @see dtOverlapBounds -inline bool dtOverlapQuantBounds(const unsigned short amin[3], const unsigned short amax[3], - const unsigned short bmin[3], const unsigned short bmax[3]) -{ - bool overlap = true; - overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; - overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; - overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; - return overlap; -} - -/// Determines if two axis-aligned bounding boxes overlap. -/// @param[in] amin Minimum bounds of box A. [(x, y, z)] -/// @param[in] amax Maximum bounds of box A. [(x, y, z)] -/// @param[in] bmin Minimum bounds of box B. [(x, y, z)] -/// @param[in] bmax Maximum bounds of box B. [(x, y, z)] -/// @return True if the two AABB's overlap. -/// @see dtOverlapQuantBounds -inline bool dtOverlapBounds(const float* amin, const float* amax, - const float* bmin, const float* bmax) -{ - bool overlap = true; - overlap = (amin[0] > bmax[0] || amax[0] < bmin[0]) ? false : overlap; - overlap = (amin[1] > bmax[1] || amax[1] < bmin[1]) ? false : overlap; - overlap = (amin[2] > bmax[2] || amax[2] < bmin[2]) ? false : overlap; - return overlap; -} - -/// Derives the closest point on a triangle from the specified reference point. -/// @param[out] closest The closest point on the triangle. -/// @param[in] p The reference point from which to test. [(x, y, z)] -/// @param[in] a Vertex A of triangle ABC. [(x, y, z)] -/// @param[in] b Vertex B of triangle ABC. [(x, y, z)] -/// @param[in] c Vertex C of triangle ABC. [(x, y, z)] -void dtClosestPtPointTriangle(float* closest, const float* p, - const float* a, const float* b, const float* c); - -/// Derives the y-axis height of the closest point on the triangle from the specified reference point. -/// @param[in] p The reference point from which to test. [(x, y, z)] -/// @param[in] a Vertex A of triangle ABC. [(x, y, z)] -/// @param[in] b Vertex B of triangle ABC. [(x, y, z)] -/// @param[in] c Vertex C of triangle ABC. [(x, y, z)] -/// @param[out] h The resulting height. -bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h); - -bool dtIntersectSegmentPoly2D(const float* p0, const float* p1, - const float* verts, int nverts, - float& tmin, float& tmax, - int& segMin, int& segMax); - -bool dtIntersectSegSeg2D(const float* ap, const float* aq, - const float* bp, const float* bq, - float& s, float& t); - -/// Determines if the specified point is inside the convex polygon on the xz-plane. -/// @param[in] pt The point to check. [(x, y, z)] -/// @param[in] verts The polygon vertices. [(x, y, z) * @p nverts] -/// @param[in] nverts The number of vertices. [Limit: >= 3] -/// @return True if the point is inside the polygon. -bool dtPointInPolygon(const float* pt, const float* verts, const int nverts); - -bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts, - float* ed, float* et); - -float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t); - -/// Derives the centroid of a convex polygon. -/// @param[out] tc The centroid of the polgyon. [(x, y, z)] -/// @param[in] idx The polygon indices. [(vertIndex) * @p nidx] -/// @param[in] nidx The number of indices in the polygon. [Limit: >= 3] -/// @param[in] verts The polygon vertices. [(x, y, z) * vertCount] -void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts); - -/// Determines if the two convex polygons overlap on the xz-plane. -/// @param[in] polya Polygon A vertices. [(x, y, z) * @p npolya] -/// @param[in] npolya The number of vertices in polygon A. -/// @param[in] polyb Polygon B vertices. [(x, y, z) * @p npolyb] -/// @param[in] npolyb The number of vertices in polygon B. -/// @return True if the two polygons overlap. -bool dtOverlapPolyPoly2D(const float* polya, const int npolya, - const float* polyb, const int npolyb); - -/// @} -/// @name Miscellanious functions. -/// @{ - -inline unsigned int dtNextPow2(unsigned int v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - -inline unsigned int dtIlog2(unsigned int v) -{ - unsigned int r; - unsigned int shift; - r = (v > 0xffff) << 4; v >>= r; - shift = (v > 0xff) << 3; v >>= shift; r |= shift; - shift = (v > 0xf) << 2; v >>= shift; r |= shift; - shift = (v > 0x3) << 1; v >>= shift; r |= shift; - r |= (v >> 1); - return r; -} - -inline int dtAlign4(int x) { return (x+3) & ~3; } - -inline int dtOppositeTile(int side) { return (side+4) & 0x7; } - -inline void dtSwapByte(unsigned char* a, unsigned char* b) -{ - unsigned char tmp = *a; - *a = *b; - *b = tmp; -} - -inline void dtSwapEndian(unsigned short* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+1); -} - -inline void dtSwapEndian(short* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+1); -} - -inline void dtSwapEndian(unsigned int* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); -} - -inline void dtSwapEndian(int* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); -} - -inline void dtSwapEndian(float* v) -{ - unsigned char* x = (unsigned char*)v; - dtSwapByte(x+0, x+3); dtSwapByte(x+1, x+2); -} - -void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas, - const float s, const float t, float* out); - -/// @} - -#endif // DETOURCOMMON_H - -/////////////////////////////////////////////////////////////////////////// - -// This section contains detailed documentation for members that don't have -// a source file. It reduces clutter in the main section of the header. - -/** - -@fn float dtTriArea2D(const float* a, const float* b, const float* c) -@par - -The vertices are projected onto the xz-plane, so the y-values are ignored. - -This is a low cost function than can be used for various purposes. Its main purpose -is for point/line relationship testing. - -In all cases: A value of zero indicates that all vertices are collinear or represent the same point. -(On the xz-plane.) - -When used for point/line relationship tests, AB usually represents a line against which -the C point is to be tested. In this case: - -A positive value indicates that point C is to the left of line AB, looking from A toward B.
          -A negative value indicates that point C is to the right of lineAB, looking from A toward B. - -When used for evaluating a triangle: - -The absolute value of the return value is two times the area of the triangle when it is -projected onto the xz-plane. - -A positive return value indicates: - -
            -
          • The vertices are wrapped in the normal Detour wrap direction.
          • -
          • The triangle's 3D face normal is in the general up direction.
          • -
          - -A negative return value indicates: - -
            -
          • The vertices are reverse wrapped. (Wrapped opposite the normal Detour wrap direction.)
          • -
          • The triangle's 3D face normal is in the general down direction.
          • -
          - -*/ diff --git a/critterai/src/nav-rcn/Detour/Include/DetourNavMesh.h b/critterai/src/nav-rcn/Detour/Include/DetourNavMesh.h deleted file mode 100644 index 9539a199..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourNavMesh.h +++ /dev/null @@ -1,689 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNAVMESH_H -#define DETOURNAVMESH_H - -#include "DetourAlloc.h" -#include "DetourStatus.h" - -// Note: If you want to use 64-bit refs, change the types of both dtPolyRef & dtTileRef. -// It is also recommended that you change dtHashRef() to a proper 64-bit hash. - -/// A handle to a polygon within a navigation mesh tile. -/// @ingroup detour -typedef unsigned int dtPolyRef; - -/// A handle to a tile within a navigation mesh. -/// @ingroup detour -typedef unsigned int dtTileRef; - -/// The maximum number of vertices per navigation polygon. -/// @ingroup detour -static const int DT_VERTS_PER_POLYGON = 6; - -/// @{ -/// @name Tile Serialization Constants -/// These constants are used to detect whether a navigation tile's data -/// and state format is compatible with the current build. -/// - -/// A magic number used to detect compatibility of navigation tile data. -static const int DT_NAVMESH_MAGIC = 'D'<<24 | 'N'<<16 | 'A'<<8 | 'V'; - -/// A version number used to detect compatibility of navigation tile data. -static const int DT_NAVMESH_VERSION = 7; - -/// A magic number used to detect the compatibility of navigation tile states. -static const int DT_NAVMESH_STATE_MAGIC = 'D'<<24 | 'N'<<16 | 'M'<<8 | 'S'; - -/// A version number used to detect compatibility of navigation tile states. -static const int DT_NAVMESH_STATE_VERSION = 1; - -/// @} - -/// A flag that indicates that an entity links to an external entity. -/// (E.g. A polygon edge is a portal that links to another polygon.) -static const unsigned short DT_EXT_LINK = 0x8000; - -/// A value that indicates the entity does not link to anything. -static const unsigned int DT_NULL_LINK = 0xffffffff; - -/// A flag that indicates that an off-mesh connection can be traversed in both directions. (Is bidirectional.) -static const unsigned int DT_OFFMESH_CON_BIDIR = 1; - -/// The maximum number of user defined area ids. -/// @ingroup detour -static const int DT_MAX_AREAS = 64; - -/// Tile flags used for various functions and fields. -/// For an example, see dtNavMesh::addTile(). -enum dtTileFlags -{ - /// The navigation mesh owns the tile memory and is responsible for freeing it. - DT_TILE_FREE_DATA = 0x01, -}; - -/// Vertex flags returned by dtNavMeshQuery::findStraightPath. -enum dtStraightPathFlags -{ - DT_STRAIGHTPATH_START = 0x01, ///< The vertex is the start position in the path. - DT_STRAIGHTPATH_END = 0x02, ///< The vertex is the end position in the path. - DT_STRAIGHTPATH_OFFMESH_CONNECTION = 0x04, ///< The vertex is the start of an off-mesh connection. -}; - -/// Options for dtNavMeshQuery::findStraightPath. -enum dtStraightPathOptions -{ - DT_STRAIGHTPATH_AREA_CROSSINGS = 0x01, ///< Add a vertex at every polygon edge crossing where area changes. - DT_STRAIGHTPATH_ALL_CROSSINGS = 0x02, ///< Add a vertex at every polygon edge crossing. -}; - -/// Flags representing the type of a navigation mesh polygon. -enum dtPolyTypes -{ - /// The polygon is a standard convex polygon that is part of the surface of the mesh. - DT_POLYTYPE_GROUND = 0, - /// The polygon is an off-mesh connection consisting of two vertices. - DT_POLYTYPE_OFFMESH_CONNECTION = 1, -}; - - -/// Defines a polyogn within a dtMeshTile object. -/// @ingroup detour -struct dtPoly -{ - /// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.) - unsigned int firstLink; - - /// The indices of the polygon's vertices. - /// The actual vertices are located in dtMeshTile::verts. - unsigned short verts[DT_VERTS_PER_POLYGON]; - - /// Packed data representing neighbor polygons references and flags for each edge. - unsigned short neis[DT_VERTS_PER_POLYGON]; - - /// The user defined polygon flags. - unsigned short flags; - - /// The number of vertices in the polygon. - unsigned char vertCount; - - /// The bit packed area id and polygon type. - /// @note Use the structure's set and get methods to acess this value. - unsigned char areaAndtype; - - /// Sets the user defined area id. [Limit: < #DT_MAX_AREAS] - inline void setArea(unsigned char a) { areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); } - - /// Sets the polygon type. (See: #dtPolyTypes.) - inline void setType(unsigned char t) { areaAndtype = (areaAndtype & 0x3f) | (t << 6); } - - /// Gets the user defined area id. - inline unsigned char getArea() const { return areaAndtype & 0x3f; } - - /// Gets the polygon type. (See: #dtPolyTypes) - inline unsigned char getType() const { return areaAndtype >> 6; } -}; - -/// Defines the location of detail sub-mesh data within a dtMeshTile. -struct dtPolyDetail -{ - unsigned int vertBase; ///< The offset of the vertices in the dtMeshTile::detailVerts array. - unsigned int triBase; ///< The offset of the triangles in the dtMeshTile::detailTris array. - unsigned char vertCount; ///< The number of vertices in the sub-mesh. - unsigned char triCount; ///< The number of triangles in the sub-mesh. -}; - -/// Defines a link between polygons. -/// @note This structure is rarely if ever used by the end user. -/// @see dtMeshTile -struct dtLink -{ - dtPolyRef ref; ///< Neighbour reference. (The neighbor that is linked to.) - unsigned int next; ///< Index of the next link. - unsigned char edge; ///< Index of the polygon edge that owns this link. - unsigned char side; ///< If a boundary link, defines on which side the link is. - unsigned char bmin; ///< If a boundary link, defines the minimum sub-edge area. - unsigned char bmax; ///< If a boundary link, defines the maximum sub-edge area. -}; - -/// Bounding volume node. -/// @note This structure is rarely if ever used by the end user. -/// @see dtMeshTile -struct dtBVNode -{ - unsigned short bmin[3]; ///< Minimum bounds of the node's AABB. [(x, y, z)] - unsigned short bmax[3]; ///< Maximum bounds of the node's AABB. [(x, y, z)] - int i; ///< The node's index. (Negative for escape sequence.) -}; - -/// Defines an navigation mesh off-mesh connection within a dtMeshTile object. -/// An off-mesh connection is a user defined traversable connection made up to two vertices. -struct dtOffMeshConnection -{ - /// The endpoints of the connection. [(ax, ay, az, bx, by, bz)] - float pos[6]; - - /// The radius of the endpoints. [Limit: >= 0] - float rad; - - /// The polygon reference of the connection within the tile. - unsigned short poly; - - /// Link flags. - /// @note These are not the connection's user defined flags. Those are assigned via the - /// connection's dtPoly definition. These are link flags used for internal purposes. - unsigned char flags; - - /// End point side. - unsigned char side; - - /// The id of the offmesh connection. (User assigned when the navigation mesh is built.) - unsigned int userId; -}; - -/// Provides high level information related to a dtMeshTile object. -/// @ingroup detour -struct dtMeshHeader -{ - int magic; ///< Tile magic number. (Used to identify the data format.) - int version; ///< Tile data format version number. - int x; ///< The x-position of the tile within the dtNavMesh tile grid. (x, y, layer) - int y; ///< The y-position of the tile within the dtNavMesh tile grid. (x, y, layer) - int layer; ///< The layer of the tile within the dtNavMesh tile grid. (x, y, layer) - unsigned int userId; ///< The user defined id of the tile. - int polyCount; ///< The number of polygons in the tile. - int vertCount; ///< The number of vertices in the tile. - int maxLinkCount; ///< The number of allocated links. - int detailMeshCount; ///< The number of sub-meshes in the detail mesh. - - /// The number of unique vertices in the detail mesh. (In addition to the polygon vertices.) - int detailVertCount; - - int detailTriCount; ///< The number of triangles in the detail mesh. - int bvNodeCount; ///< The number of bounding volume nodes. (Zero if bounding volumes are disabled.) - int offMeshConCount; ///< The number of off-mesh connections. - int offMeshBase; ///< The index of the first polygon which is an off-mesh connection. - float walkableHeight; ///< The height of the agents using the tile. - float walkableRadius; ///< The radius of the agents using the tile. - float walkableClimb; ///< The maximum climb height of the agents using the tile. - float bmin[3]; ///< The minimum bounds of the tile's AABB. [(x, y, z)] - float bmax[3]; ///< The maximum bounds of the tile's AABB. [(x, y, z)] - - /// The bounding volume quantization factor. - float bvQuantFactor; -}; - -/// Defines a navigation mesh tile. -/// @ingroup detour -struct dtMeshTile -{ - unsigned int salt; ///< Counter describing modifications to the tile. - - unsigned int linksFreeList; ///< Index to the next free link. - dtMeshHeader* header; ///< The tile header. - dtPoly* polys; ///< The tile polygons. [Size: dtMeshHeader::polyCount] - float* verts; ///< The tile vertices. [Size: dtMeshHeader::vertCount] - dtLink* links; ///< The tile links. [Size: dtMeshHeader::maxLinkCount] - dtPolyDetail* detailMeshes; ///< The tile's detail sub-meshes. [Size: dtMeshHeader::detailMeshCount] - - /// The detail mesh's unique vertices. [(x, y, z) * dtMeshHeader::detailVertCount] - float* detailVerts; - - /// The detail mesh's triangles. [(vertA, vertB, vertC) * dtMeshHeader::detailTriCount] - unsigned char* detailTris; - - /// The tile bounding volume nodes. [Size: dtMeshHeader::bvNodeCount] - /// (Will be null if bounding volumes are disabled.) - dtBVNode* bvTree; - - dtOffMeshConnection* offMeshCons; ///< The tile off-mesh connections. [Size: dtMeshHeader::offMeshConCount] - - unsigned char* data; ///< The tile data. (Not directly accessed under normal situations.) - int dataSize; ///< Size of the tile data. - int flags; ///< Tile flags. (See: #dtTileFlags) - dtMeshTile* next; ///< The next free tile, or the next tile in the spatial grid. -}; - -/// Configuration parameters used to define multi-tile navigation meshes. -/// The values are used to allocate space during the initialization of a navigation mesh. -/// @see dtNavMesh::init() -/// @ingroup detour -struct dtNavMeshParams -{ - float orig[3]; ///< The world space origin of the navigation mesh's tile space. [(x, y, z)] - float tileWidth; ///< The width of each tile. (Along the x-axis.) - float tileHeight; ///< The height of each tile. (Along the z-axis.) - int maxTiles; ///< The maximum number of tiles the navigation mesh can contain. - int maxPolys; ///< The maximum number of polygons each tile can contain. -}; - -/// A navigation mesh based on tiles of convex polygons. -/// @ingroup detour -class dtNavMesh -{ -public: - dtNavMesh(); - ~dtNavMesh(); - - /// @{ - /// @name Initialization and Tile Management - - /// Initializes the navigation mesh for tiled use. - /// @param[in] params Initialization parameters. - /// @return The status flags for the operation. - dtStatus init(const dtNavMeshParams* params); - - /// Initializes the navigation mesh for single tile use. - /// @param[in] data Data of the new tile. (See: #dtCreateNavMeshData) - /// @param[in] dataSize The data size of the new tile. - /// @param[in] flags The tile flags. (See: #dtTileFlags) - /// @return The status flags for the operation. - /// @see dtCreateNavMeshData - dtStatus init(unsigned char* data, const int dataSize, const int flags); - - /// The navigation mesh initialization params. - const dtNavMeshParams* getParams() const; - - /// Adds a tile to the navigation mesh. - /// @param[in] data Data for the new tile mesh. (See: #dtCreateNavMeshData) - /// @param[in] dataSize Data size of the new tile mesh. - /// @param[in] flags Tile flags. (See: #dtTileFlags) - /// @param[in] lastRef The desired reference for the tile. (When reloading a tile.) [opt] [Default: 0] - /// @param[out] result The tile reference. (If the tile was succesfully added.) [opt] - /// @return The status flags for the operation. - dtStatus addTile(unsigned char* data, int dataSize, int flags, dtTileRef lastRef, dtTileRef* result); - - /// Removes the specified tile from the navigation mesh. - /// @param[in] ref The reference of the tile to remove. - /// @param[out] data Data associated with deleted tile. - /// @param[out] dataSize Size of the data associated with deleted tile. - /// @return The status flags for the operation. - dtStatus removeTile(dtTileRef ref, unsigned char** data, int* dataSize); - - /// @} - - /// @{ - /// @name Query Functions - - /// Calculates the tile grid location for the specified world position. - /// @param[in] pos The world position for the query. [(x, y, z)] - /// @param[out] tx The tile's x-location. (x, y) - /// @param[out] ty The tile's y-location. (x, y) - void calcTileLoc(const float* pos, int* tx, int* ty) const; - - /// Gets the tile at the specified grid location. - /// @param[in] x The tile's x-location. (x, y, layer) - /// @param[in] y The tile's y-location. (x, y, layer) - /// @param[in] layer The tile's layer. (x, y, layer) - /// @return The tile, or null if the tile does not exist. - const dtMeshTile* getTileAt(const int x, const int y, const int layer) const; - - /// Gets all tiles at the specified grid location. (All layers.) - /// @param[in] x The tile's x-location. (x, y) - /// @param[in] y The tile's y-location. (x, y) - /// @param[out] tiles A pointer to an array of tiles that will hold the result. - /// @param[in] maxTiles The maximum tiles the tiles parameter can hold. - /// @return The number of tiles returned in the tiles array. - int getTilesAt(const int x, const int y, - dtMeshTile const** tiles, const int maxTiles) const; - - /// Gets the tile reference for the tile at specified grid location. - /// @param[in] x The tile's x-location. (x, y, layer) - /// @param[in] y The tile's y-location. (x, y, layer) - /// @param[in] layer The tile's layer. (x, y, layer) - /// @return The tile reference of the tile, or 0 if there is none. - dtTileRef getTileRefAt(int x, int y, int layer) const; - - /// Gets the tile reference for the specified tile. - /// @param[in] tile The tile. - /// @return The tile reference of the tile. - dtTileRef getTileRef(const dtMeshTile* tile) const; - - /// Gets the tile for the specified tile reference. - /// @param[in] ref The tile reference of the tile to retrieve. - /// @return The tile for the specified reference, or null if the - /// reference is invalid. - const dtMeshTile* getTileByRef(dtTileRef ref) const; - - /// The maximum number of tiles supported by the navigation mesh. - /// @return The maximum number of tiles supported by the navigation mesh. - int getMaxTiles() const; - - /// Gets the tile at the specified index. - /// @param[in] i The tile index. [Limit: 0 >= index < #getMaxTiles()] - /// @return The tile at the specified index. - const dtMeshTile* getTile(int i) const; - - /// Gets the tile and polygon for the specified polygon reference. - /// @param[in] ref The reference for the a polygon. - /// @param[out] tile The tile containing the polygon. - /// @param[out] poly The polygon. - /// @return The status flags for the operation. - dtStatus getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; - - /// Returns the tile and polygon for the specified polygon reference. - /// @param[in] ref A known valid reference for a polygon. - /// @param[out] tile The tile containing the polygon. - /// @param[out] poly The polygon. - void getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const; - - /// Checks the validity of a polygon reference. - /// @param[in] ref The polygon reference to check. - /// @return True if polygon reference is valid for the navigation mesh. - bool isValidPolyRef(dtPolyRef ref) const; - - /// Gets the polygon reference for the tile's base polygon. - /// @param[in] tile The tile. - /// @return The polygon reference for the base polygon in the specified tile. - dtPolyRef getPolyRefBase(const dtMeshTile* tile) const; - - /// Gets the endpoints for an off-mesh connection, ordered by "direction of travel". - /// @param[in] prevRef The reference of the polygon before the connection. - /// @param[in] polyRef The reference of the off-mesh connection polygon. - /// @param[out] startPos The start position of the off-mesh connection. [(x, y, z)] - /// @param[out] endPos The end position of the off-mesh connection. [(x, y, z)] - /// @return The status flags for the operation. - dtStatus getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const; - - /// Gets the specified off-mesh connection. - /// @param[in] ref The polygon reference of the off-mesh connection. - /// @return The specified off-mesh connection, or null if the polygon reference is not valid. - const dtOffMeshConnection* getOffMeshConnectionByRef(dtPolyRef ref) const; - - /// @} - - /// @{ - /// @name State Management - /// These functions do not effect #dtTileRef or #dtPolyRef's. - - /// Sets the user defined flags for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[in] flags The new flags for the polygon. - /// @return The status flags for the operation. - dtStatus setPolyFlags(dtPolyRef ref, unsigned short flags); - - /// Gets the user defined flags for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[out] resultFlags The polygon flags. - /// @return The status flags for the operation. - dtStatus getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const; - - /// Sets the user defined area for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[in] area The new area id for the polygon. [Limit: < #DT_MAX_AREAS] - /// @return The status flags for the operation. - dtStatus setPolyArea(dtPolyRef ref, unsigned char area); - - /// Gets the user defined area for the specified polygon. - /// @param[in] ref The polygon reference. - /// @param[out] resultArea The area id for the polygon. - /// @return The status flags for the operation. - dtStatus getPolyArea(dtPolyRef ref, unsigned char* resultArea) const; - - /// Gets the size of the buffer required by #storeTileState to store the specified tile's state. - /// @param[in] tile The tile. - /// @return The size of the buffer required to store the state. - int getTileStateSize(const dtMeshTile* tile) const; - - /// Stores the non-structural state of the tile in the specified buffer. (Flags, area ids, etc.) - /// @param[in] tile The tile. - /// @param[out] data The buffer to store the tile's state in. - /// @param[in] maxDataSize The size of the data buffer. [Limit: >= #getTileStateSize] - /// @return The status flags for the operation. - dtStatus storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const; - - /// Restores the state of the tile. - /// @param[in] tile The tile. - /// @param[in] data The new state. (Obtained from #storeTileState.) - /// @param[in] maxDataSize The size of the state within the data buffer. - /// @return The status flags for the operation. - dtStatus restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize); - - /// @} - - /// @{ - /// @name Encoding and Decoding - /// These functions are generally meant for internal use only. - - /// Derives a standard polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] salt The tile's salt value. - /// @param[in] it The index of the tile. - /// @param[in] ip The index of the polygon within the tile. - inline dtPolyRef encodePolyId(unsigned int salt, unsigned int it, unsigned int ip) const - { - return ((dtPolyRef)salt << (m_polyBits+m_tileBits)) | ((dtPolyRef)it << m_polyBits) | (dtPolyRef)ip; - } - - /// Decodes a standard polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference to decode. - /// @param[out] salt The tile's salt value. - /// @param[out] it The index of the tile. - /// @param[out] ip The index of the polygon within the tile. - /// @see #encodePolyId - inline void decodePolyId(dtPolyRef ref, unsigned int& salt, unsigned int& it, unsigned int& ip) const - { - const dtPolyRef saltMask = ((dtPolyRef)1<> (m_polyBits+m_tileBits)) & saltMask); - it = (unsigned int)((ref >> m_polyBits) & tileMask); - ip = (unsigned int)(ref & polyMask); - } - - /// Extracts a tile's salt value from the specified polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference. - /// @see #encodePolyId - inline unsigned int decodePolyIdSalt(dtPolyRef ref) const - { - const dtPolyRef saltMask = ((dtPolyRef)1<> (m_polyBits+m_tileBits)) & saltMask); - } - - /// Extracts the tile's index from the specified polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference. - /// @see #encodePolyId - inline unsigned int decodePolyIdTile(dtPolyRef ref) const - { - const dtPolyRef tileMask = ((dtPolyRef)1<> m_polyBits) & tileMask); - } - - /// Extracts the polygon's index (within its tile) from the specified polygon reference. - /// @note This function is generally meant for internal use only. - /// @param[in] ref The polygon reference. - /// @see #encodePolyId - inline unsigned int decodePolyIdPoly(dtPolyRef ref) const - { - const dtPolyRef polyMask = ((dtPolyRef)1<header->bvQuantFactor; -const dtBVNode* n = &tile->bvTree[i]; -if (n->i >= 0) -{ - // This is a leaf node. - float worldMinX = tile->header->bmin[0] + n->bmin[0]*cs; - float worldMinY = tile->header->bmin[0] + n->bmin[1]*cs; - // Etc... -} -@endcode - -@struct dtMeshTile -@par - -Tiles generally only exist within the context of a dtNavMesh object. - -Some tile content is optional. For example, a tile may not contain any -off-mesh connections. In this case the associated pointer will be null. - -If a detail mesh exists it will share vertices with the base polygon mesh. -Only the vertices unique to the detail mesh will be stored in #detailVerts. - -@warning Tiles returned by a dtNavMesh object are not guarenteed to be populated. -For example: The tile at a location might not have been loaded yet, or may have been removed. -In this case, pointers will be null. So if in doubt, check the polygon count in the -tile's header to determine if a tile has polygons defined. - -@var float dtOffMeshConnection::pos[6] -@par - -For a properly built navigation mesh, vertex A will always be within the bounds of the mesh. -Vertex B is not required to be within the bounds of the mesh. - -*/ diff --git a/critterai/src/nav-rcn/Detour/Include/DetourNavMeshBuilder.h b/critterai/src/nav-rcn/Detour/Include/DetourNavMeshBuilder.h deleted file mode 100644 index c80d1717..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourNavMeshBuilder.h +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNAVMESHBUILDER_H -#define DETOURNAVMESHBUILDER_H - -#include "DetourAlloc.h" - -/// Represents the source data used to build an navigation mesh tile. -/// @ingroup detour -struct dtNavMeshCreateParams -{ - - /// @name Polygon Mesh Attributes - /// Used to create the base navigation graph. - /// See #rcPolyMesh for details related to these attributes. - /// @{ - - const unsigned short* verts; ///< The polygon mesh vertices. [(x, y, z) * #vertCount] [Unit: vx] - int vertCount; ///< The number vertices in the polygon mesh. [Limit: >= 3] - const unsigned short* polys; ///< The polygon data. [Size: #polyCount * 2 * #nvp] - const unsigned short* polyFlags; ///< The user defined flags assigned to each polygon. [Size: #polyCount] - const unsigned char* polyAreas; ///< The user defined area ids assigned to each polygon. [Size: #polyCount] - int polyCount; ///< Number of polygons in the mesh. [Limit: >= 1] - int nvp; ///< Number maximum number of vertices per polygon. [Limit: >= 3] - - /// @} - /// @name Height Detail Attributes (Optional) - /// See #rcPolyMeshDetail for details related to these attributes. - /// @{ - - const unsigned int* detailMeshes; ///< The height detail sub-mesh data. [Size: 4 * #polyCount] - const float* detailVerts; ///< The detail mesh vertices. [Size: 3 * #detailVertsCount] [Unit: wu] - int detailVertsCount; ///< The number of vertices in the detail mesh. - const unsigned char* detailTris; ///< The detail mesh triangles. [Size: 4 * #detailTriCount] - int detailTriCount; ///< The number of triangles in the detail mesh. - - /// @} - /// @name Off-Mesh Connections Attributes (Optional) - /// Used to define a custom point-to-point edge within the navigation graph, an - /// off-mesh connection is a user defined traversable connection made up to two vertices, - /// at least one of which resides within a navigation mesh polygon. - /// @{ - - /// Off-mesh connection vertices. [(ax, ay, az, bx, by, bz) * #offMeshConCount] [Unit: wu] - const float* offMeshConVerts; - /// Off-mesh connection radii. [Size: #offMeshConCount] [Unit: wu] - const float* offMeshConRad; - /// User defined flags assigned to the off-mesh connections. [Size: #offMeshConCount] - const unsigned short* offMeshConFlags; - /// User defined area ids assigned to the off-mesh connections. [Size: #offMeshConCount] - const unsigned char* offMeshConAreas; - /// The permitted travel direction of the off-mesh connections. [Size: #offMeshConCount] - /// - /// 0 = Travel only from endpoint A to endpoint B.
          - /// #DT_OFFMESH_CON_BIDIR = Bidirectional travel. - const unsigned char* offMeshConDir; - /// The user defined ids of the off-mesh connection. [Size: #offMeshConCount] - const unsigned int* offMeshConUserID; - /// The number of off-mesh connections. [Limit: >= 0] - int offMeshConCount; - - /// @} - /// @name Tile Attributes - /// @note The tile grid/layer data can be left at zero if the destination is a single tile mesh. - /// @{ - - unsigned int userId; ///< The user defined id of the tile. - int tileX; ///< The tile's x-grid location within the multi-tile destination mesh. (Along the x-axis.) - int tileY; ///< The tile's y-grid location within the multi-tile desitation mesh. (Along the z-axis.) - int tileLayer; ///< The tile's layer within the layered destination mesh. [Limit: >= 0] (Along the y-axis.) - float bmin[3]; ///< The minimum bounds of the tile. [(x, y, z)] [Unit: wu] - float bmax[3]; ///< The maximum bounds of the tile. [(x, y, z)] [Unit: wu] - - /// @} - /// @name General Configuration Attributes - /// @{ - - float walkableHeight; ///< The agent height. [Unit: wu] - float walkableRadius; ///< The agent radius. [Unit: wu] - float walkableClimb; ///< The agent maximum traversable ledge. (Up/Down) [Unit: wu] - float cs; ///< The xz-plane cell size of the polygon mesh. [Limit: > 0] [Unit: wu] - float ch; ///< The y-axis cell height of the polygon mesh. [Limit: > 0] [Unit: wu] - - /// True if a bounding volume tree should be built for the tile. - /// @note The BVTree is not normally needed for layered navigation meshes. - bool buildBvTree; - - /// @} -}; - -/// Builds navigation mesh tile data from the provided tile creation data. -/// @ingroup detour -/// @param[in] params Tile creation data. -/// @param[out] outData The resulting tile data. -/// @param[out] outDataSize The size of the tile data array. -/// @return True if the tile data was successfully created. -bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize); - -/// Swaps the endianess of the tile data's header (#dtMeshHeader). -/// @param[in,out] data The tile data array. -/// @param[in] dataSize The size of the data array. -bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int dataSize); - -/// Swaps endianess of the tile data. -/// @param[in,out] data The tile data array. -/// @param[in] dataSize The size of the data array. -bool dtNavMeshDataSwapEndian(unsigned char* data, const int dataSize); - -#endif // DETOURNAVMESHBUILDER_H - -// This section contains detailed documentation for members that don't have -// a source file. It reduces clutter in the main section of the header. - -/** - -@struct dtNavMeshCreateParams -@par - -This structure is used to marshal data between the Recast mesh generation pipeline and Detour navigation components. - -See the rcPolyMesh and rcPolyMeshDetail documentation for detailed information related to mesh structure. - -Units are usually in voxels (vx) or world units (wu). The units for voxels, grid size, and cell size -are all based on the values of #cs and #ch. - -The standard navigation mesh build process is to create tile data using dtCreateNavMeshData, then add the tile -to a navigation mesh using either the dtNavMesh single tile init() function or the dtNavMesh::addTile() -function. - -@see dtCreateNavMeshData - -*/ \ No newline at end of file diff --git a/critterai/src/nav-rcn/Detour/Include/DetourNavMeshQuery.h b/critterai/src/nav-rcn/Detour/Include/DetourNavMeshQuery.h deleted file mode 100644 index d431bf17..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourNavMeshQuery.h +++ /dev/null @@ -1,488 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNAVMESHQUERY_H -#define DETOURNAVMESHQUERY_H - -#include "DetourNavMesh.h" -#include "DetourStatus.h" - - -// Define DT_VIRTUAL_QUERYFILTER if you wish to derive a custom filter from dtQueryFilter. -// On certain platforms indirect or virtual function call is expensive. The default -// setting is to use non-virtual functions, the actual implementations of the functions -// are declared as inline for maximum speed. - -//#define DT_VIRTUAL_QUERYFILTER 1 - -/// Defines polygon filtering and traversal costs for navigation mesh query operations. -/// @ingroup detour -class dtQueryFilter -{ - float m_areaCost[DT_MAX_AREAS]; ///< Cost per area type. (Used by default implementation.) - unsigned short m_includeFlags; ///< Flags for polygons that can be visited. (Used by default implementation.) - unsigned short m_excludeFlags; ///< Flags for polygons that should not be visted. (Used by default implementation.) - -public: - dtQueryFilter(); - - /// Returns true if the polygon can be visited. (I.e. Is traversable.) - /// @param[in] ref The reference id of the polygon test. - /// @param[in] tile The tile containing the polygon. - /// @param[in] poly The polygon to test. -#ifdef DT_VIRTUAL_QUERYFILTER - virtual bool passFilter(const dtPolyRef ref, - const dtMeshTile* tile, - const dtPoly* poly) const; -#else - bool passFilter(const dtPolyRef ref, - const dtMeshTile* tile, - const dtPoly* poly) const; -#endif - - /// Returns cost to move from the beginning to the end of a line segment - /// that is fully contained within a polygon. - /// @param[in] pa The start position on the edge of the previous and current polygon. [(x, y, z)] - /// @param[in] pb The end position on the edge of the current and next polygon. [(x, y, z)] - /// @param[in] prevRef The reference id of the previous polygon. [opt] - /// @param[in] prevTile The tile containing the previous polygon. [opt] - /// @param[in] prevPoly The previous polygon. [opt] - /// @param[in] curRef The reference id of the current polygon. - /// @param[in] curTile The tile containing the current polygon. - /// @param[in] curPoly The current polygon. - /// @param[in] nextRef The refernece id of the next polygon. [opt] - /// @param[in] nextTile The tile containing the next polygon. [opt] - /// @param[in] nextPoly The next polygon. [opt] -#ifdef DT_VIRTUAL_QUERYFILTER - virtual float getCost(const float* pa, const float* pb, - const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, - const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, - const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; -#else - float getCost(const float* pa, const float* pb, - const dtPolyRef prevRef, const dtMeshTile* prevTile, const dtPoly* prevPoly, - const dtPolyRef curRef, const dtMeshTile* curTile, const dtPoly* curPoly, - const dtPolyRef nextRef, const dtMeshTile* nextTile, const dtPoly* nextPoly) const; -#endif - - /// @name Getters and setters for the default implementation data. - ///@{ - - /// Returns the traversal cost of the area. - /// @param[in] i The id of the area. - /// @returns The traversal cost of the area. - inline float getAreaCost(const int i) const { return m_areaCost[i]; } - - /// Sets the traversal cost of the area. - /// @param[in] i The id of the area. - /// @param[in] cost The new cost of traversing the area. - inline void setAreaCost(const int i, const float cost) { m_areaCost[i] = cost; } - - /// Returns the include flags for the filter. - /// Any polygons that include one or more of these flags will be - /// included in the operation. - inline unsigned short getIncludeFlags() const { return m_includeFlags; } - - /// Sets the include flags for the filter. - /// @param[in] flags The new flags. - inline void setIncludeFlags(const unsigned short flags) { m_includeFlags = flags; } - - /// Returns the exclude flags for the filter. - /// Any polygons that include one ore more of these flags will be - /// excluded from the operation. - inline unsigned short getExcludeFlags() const { return m_excludeFlags; } - - /// Sets the exclude flags for the filter. - /// @param[in] flags The new flags. - inline void setExcludeFlags(const unsigned short flags) { m_excludeFlags = flags; } - - ///@} - -}; - -/// Provides the ability to perform pathfinding related queries against -/// a navigation mesh. -/// @ingroup detour -class dtNavMeshQuery -{ -public: - dtNavMeshQuery(); - ~dtNavMeshQuery(); - - /// Initializes the query object. - /// @param[in] nav Pointer to the dtNavMesh object to use for all queries. - /// @param[in] maxNodes Maximum number of search nodes. [Limits: 0 < value <= 65536] - /// @returns The status flags for the query. - dtStatus init(const dtNavMesh* nav, const int maxNodes); - - /// @name Standard Pathfinding Functions - // /@{ - - /// Finds a path from the start polygon to the end polygon. - /// @param[in] startRef The refrence id of the start polygon. - /// @param[in] endRef The reference id of the end polygon. - /// @param[in] startPos A position within the start polygon. [(x, y, z)] - /// @param[in] endPos A position within the end polygon. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) - /// [(polyRef) * @p pathCount] - /// @param[out] pathCount The number of polygons returned in the @p path array. - /// @param[in] maxPath The maximum number of polygons the @p path array can hold. [Limit: >= 1] - dtStatus findPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter, - dtPolyRef* path, int* pathCount, const int maxPath) const; - - /// Finds the straight path from the start to the end position within the polygon corridor. - /// @param[in] startPos Path start position. [(x, y, z)] - /// @param[in] endPos Path end position. [(x, y, z)] - /// @param[in] path An array of polygon references that represent the path corridor. - /// @param[in] pathSize The number of polygons in the @p path array. - /// @param[out] straightPath Points describing the straight path. [(x, y, z) * @p straightPathCount]. - /// @param[out] straightPathFlags Flags describing each point. (See: #dtStraightPathFlags) [opt] - /// @param[out] straightPathRefs The reference id of the polygon that is being entered at each point. [opt] - /// @param[out] straightPathCount The number of points in the straight path. - /// @param[in] maxStraightPath The maximum number of points the straight path arrays can hold. [Limit: > 0] - /// @param[in] options Query options. (see: #dtStraightPathOptions) - /// @returns The status flags for the query. - dtStatus findStraightPath(const float* startPos, const float* endPos, - const dtPolyRef* path, const int pathSize, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath, const int options = 0) const; - - ///@} - /// @name Sliced Pathfinding Functions - /// Common use case: - /// -# Call initSlicedFindPath() to initialize the sliced path query. - /// -# Call updateSlicedFindPath() until it returns complete. - /// -# Call finalizeSlicedFindPath() to get the path. - ///@{ - - /// Intializes a sliced path query. - /// @param[in] startRef The refrence id of the start polygon. - /// @param[in] endRef The reference id of the end polygon. - /// @param[in] startPos A position within the start polygon. [(x, y, z)] - /// @param[in] endPos A position within the end polygon. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @returns The status flags for the query. - dtStatus initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter); - - /// Updates an in-progress sliced path query. - /// @param[in] maxIter The maximum number of iterations to perform. - /// @param[out] doneIters The actual number of iterations completed. [opt] - /// @returns The status flags for the query. - dtStatus updateSlicedFindPath(const int maxIter, int* doneIters); - - /// Finalizes and returns the results of a sliced path query. - /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) - /// [(polyRef) * @p pathCount] - /// @param[out] pathCount The number of polygons returned in the @p path array. - /// @param[in] maxPath The max number of polygons the path array can hold. [Limit: >= 1] - /// @returns The status flags for the query. - dtStatus finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath); - - /// Finalizes and returns the results of an incomplete sliced path query, returning the path to the furthest - /// polygon on the existing path that was visited during the search. - /// @param[out] existing An array of polygon references for the existing path. - /// @param[out] existingSize The number of polygon in the @p existing array. - /// @param[out] path An ordered list of polygon references representing the path. (Start to end.) - /// [(polyRef) * @p pathCount] - /// @param[out] pathCount The number of polygons returned in the @p path array. - /// @param[in] maxPath The max number of polygons the @p path array can hold. [Limit: >= 1] - /// @returns The status flags for the query. - dtStatus finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, - dtPolyRef* path, int* pathCount, const int maxPath); - - ///@} - /// @name Dijkstra Search Functions - /// @{ - - /// Finds the polygons along the navigation graph that touch the specified circle. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] centerPos The center of the search circle. [(x, y, z)] - /// @param[in] radius The radius of the search circle. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultRef The reference ids of the polygons touched by the circle. [opt] - /// @param[out] resultParent The reference ids of the parent polygons for each result. - /// Zero if a result polygon has no parent. [opt] - /// @param[out] resultCost The search cost from @p centerPos to the polygon. [opt] - /// @param[out] resultCount The number of polygons found. [opt] - /// @param[in] maxResult The maximum number of polygons the result arrays can hold. - /// @returns The status flags for the query. - dtStatus findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const; - - /// Finds the polygons along the naviation graph that touch the specified convex polygon. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] verts The vertices describing the convex polygon. (CCW) - /// [(x, y, z) * @p nverts] - /// @param[in] nverts The number of vertices in the polygon. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultRef The reference ids of the polygons touched by the search polygon. [opt] - /// @param[out] resultParent The reference ids of the parent polygons for each result. Zero if a - /// result polygon has no parent. [opt] - /// @param[out] resultCost The search cost from the centroid point to the polygon. [opt] - /// @param[out] resultCount The number of polygons found. - /// @param[in] maxResult The maximum number of polygons the result arrays can hold. - /// @returns The status flags for the query. - dtStatus findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const; - - /// @} - /// @name Local Query Functions - ///@{ - - /// Finds the polygon nearest to the specified center point. - /// @param[in] center The center of the search box. [(x, y, z)] - /// @param[in] extents The search distance along each axis. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] nearestRef The reference id of the nearest polygon. - /// @param[out] nearestPt The nearest point on the polygon. [opt] [(x, y, z)] - /// @returns The status flags for the query. - dtStatus findNearestPoly(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* nearestRef, float* nearestPt) const; - - /// Finds polygons that overlap the search box. - /// @param[in] center The center of the search box. [(x, y, z)] - /// @param[in] extents The search distance along each axis. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] polys The reference ids of the polygons that overlap the query box. - /// @param[out] polyCount The number of polygons in the search result. - /// @param[in] maxPolys The maximum number of polygons the search result can hold. - /// @returns The status flags for the query. - dtStatus queryPolygons(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* polys, int* polyCount, const int maxPolys) const; - - /// Finds the non-overlapping navigation polygons in the local neighbourhood around the center position. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] centerPos The center of the query circle. [(x, y, z)] - /// @param[in] radius The radius of the query circle. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultRef The reference ids of the polygons touched by the circle. - /// @param[out] resultParent The reference ids of the parent polygons for each result. - /// Zero if a result polygon has no parent. [opt] - /// @param[out] resultCount The number of polygons found. - /// @param[in] maxResult The maximum number of polygons the result arrays can hold. - /// @returns The status flags for the query. - dtStatus findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, - int* resultCount, const int maxResult) const; - - /// Moves from the start to the end position constrained to the navigation mesh. - /// @param[in] startRef The reference id of the start polygon. - /// @param[in] startPos A position of the mover within the start polygon. [(x, y, x)] - /// @param[in] endPos The desired end position of the mover. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] resultPos The result position of the mover. [(x, y, z)] - /// @param[out] visited The reference ids of the polygons visited during the move. - /// @param[out] visitedCount The number of polygons visited during the move. - /// @param[in] maxVisitedSize The maximum number of polygons the @p visited array can hold. - /// @returns The status flags for the query. - dtStatus moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const; - - /// Casts a 'walkability' ray along the surface of the navigation mesh from - /// the start position toward the end position. - /// @param[in] startRef The reference id of the start polygon. - /// @param[in] startPos A position within the start polygon representing - /// the start of the ray. [(x, y, z)] - /// @param[in] endPos The position to cast the ray toward. [(x, y, z)] - /// @param[out] t The hit parameter. (FLT_MAX if no wall hit.) - /// @param[out] hitNormal The normal of the nearest wall hit. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] path The reference ids of the visited polygons. [opt] - /// @param[out] pathCount The number of visited polygons. [opt] - /// @param[in] maxPath The maximum number of polygons the @p path array can hold. - /// @returns The status flags for the query. - dtStatus raycast(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const; - - /// Finds the distance from the specified position to the nearest polygon wall. - /// @param[in] startRef The reference id of the polygon containing @p centerPos. - /// @param[in] centerPos The center of the search circle. [(x, y, z)] - /// @param[in] maxRadius The radius of the search circle. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] hitDist The distance to the nearest wall from @p centerPos. - /// @param[out] hitPos The nearest position on the wall that was hit. [(x, y, z)] - /// @param[out] hitNormal The normalized ray formed from the wall point to the - /// source point. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, - const dtQueryFilter* filter, - float* hitDist, float* hitPos, float* hitNormal) const; - - /// Returns the segments for the specified polygon, optionally including portals. - /// @param[in] ref The reference id of the polygon. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[out] segmentVerts The segments. [(ax, ay, az, bx, by, bz) * segmentCount] - /// @param[out] segmentRefs The reference ids of each segment's neighbor polygon. - /// Or zero if the segment is a wall. [opt] [(parentRef) * @p segmentCount] - /// @param[out] segmentCount The number of segments returned. - /// @param[in] maxSegments The maximum number of segments the result arrays can hold. - /// @returns The status flags for the query. - dtStatus getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, - float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, - const int maxSegments) const; - - /// Returns random location on navmesh. - /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon. - /// @param[in] filter The polygon filter to apply to the query. - /// @param[in] frand Function returning a random number [0..1). - /// @param[out] randomRef The reference id of the random location. - /// @param[out] randomPt The random location. - /// @returns The status flags for the query. - dtStatus findRandomPoint(const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const; - - /// Returns random location on navmesh within the reach of specified location. - /// Polygons are chosen weighted by area. The search runs in linear related to number of polygon. - /// The location is not exactly constrained by the circle, but it limits the visited polygons. - /// @param[in] startRef The reference id of the polygon where the search starts. - /// @param[in] centerPos The center of the search circle. [(x, y, z)] - /// @param[in] filter The polygon filter to apply to the query. - /// @param[in] frand Function returning a random number [0..1). - /// @param[out] randomRef The reference id of the random location. - /// @param[out] randomPt The random location. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float maxRadius, - const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const; - - /// Finds the closest point on the specified polygon. - /// @param[in] ref The reference id of the polygon. - /// @param[in] pos The position to check. [(x, y, z)] - /// @param[out] closest The closest point on the polygon. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const; - - /// Returns a point on the boundary closest to the source point if the source point is outside the - /// polygon's xz-bounds. - /// @param[in] ref The reference id to the polygon. - /// @param[in] pos The position to check. [(x, y, z)] - /// @param[out] closest The closest point. [(x, y, z)] - /// @returns The status flags for the query. - dtStatus closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const; - - /// Gets the height of the polygon at the provided position using the height detail. (Most accurate.) - /// @param[in] ref The reference id of the polygon. - /// @param[in] pos A position within the xz-bounds of the polygon. [(x, y, z)] - /// @param[out] height The height at the surface of the polygon. - /// @returns The status flags for the query. - dtStatus getPolyHeight(dtPolyRef ref, const float* pos, float* height) const; - - /// @} - /// @name Miscellaneous Functions - /// @{ - - /// Returns true if the polygon reference is valid and passes the filter restrictions. - /// @param[in] ref The polygon reference to check. - /// @param[in] filter The filter to apply. - bool isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const; - - /// Returns true if the polygon reference is in the closed list. - /// @param[in] ref The reference id of the polygon to check. - /// @returns True if the polygon is in closed list. - bool isInClosedList(dtPolyRef ref) const; - - /// Gets the node pool. - /// @returns The node pool. - class dtNodePool* getNodePool() const { return m_nodePool; } - - /// Gets the navigation mesh the query object is using. - /// @return The navigation mesh the query object is using. - const dtNavMesh* getAttachedNavMesh() const { return m_nav; } - - /// @} - -private: - - /// Returns neighbour tile based on side. - dtMeshTile* getNeighbourTileAt(int x, int y, int side) const; - - /// Queries polygons within a tile. - int queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, const dtQueryFilter* filter, - dtPolyRef* polys, const int maxPolys) const; - /// Find nearest polygon within a tile. - dtPolyRef findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents, - const dtQueryFilter* filter, float* nearestPt) const; - /// Returns closest point on polygon. - void closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, const float* pos, float* closest) const; - - /// Returns portal points between two polygons. - dtStatus getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, - unsigned char& fromType, unsigned char& toType) const; - dtStatus getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* left, float* right) const; - - /// Returns edge mid point between two polygons. - dtStatus getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const; - dtStatus getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* mid) const; - - // Appends vertex to a straight path - dtStatus appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath) const; - - // Appends intermediate portal points to a straight path. - dtStatus appendPortals(const int startIdx, const int endIdx, const float* endPos, const dtPolyRef* path, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath, const int options) const; - - const dtNavMesh* m_nav; ///< Pointer to navmesh data. - - struct dtQueryData - { - dtStatus status; - struct dtNode* lastBestNode; - float lastBestNodeCost; - dtPolyRef startRef, endRef; - float startPos[3], endPos[3]; - const dtQueryFilter* filter; - }; - dtQueryData m_query; ///< Sliced query state. - - class dtNodePool* m_tinyNodePool; ///< Pointer to small node pool. - class dtNodePool* m_nodePool; ///< Pointer to node pool. - class dtNodeQueue* m_openList; ///< Pointer to open list queue. -}; - -/// Allocates a query object using the Detour allocator. -/// @return An allocated query object, or null on failure. -/// @ingroup detour -dtNavMeshQuery* dtAllocNavMeshQuery(); - -/// Frees the specified query object using the Detour allocator. -/// @param[in] query A query object allocated using #dtAllocNavMeshQuery -/// @ingroup detour -void dtFreeNavMeshQuery(dtNavMeshQuery* query); - -#endif // DETOURNAVMESHQUERY_H diff --git a/critterai/src/nav-rcn/Detour/Include/DetourNode.h b/critterai/src/nav-rcn/Detour/Include/DetourNode.h deleted file mode 100644 index b68c922d..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourNode.h +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURNODE_H -#define DETOURNODE_H - -#include "DetourNavMesh.h" - -enum dtNodeFlags -{ - DT_NODE_OPEN = 0x01, - DT_NODE_CLOSED = 0x02, -}; - -typedef unsigned short dtNodeIndex; -static const dtNodeIndex DT_NULL_IDX = (dtNodeIndex)~0; - -struct dtNode -{ - float pos[3]; ///< Position of the node. - float cost; ///< Cost from previous node to current node. - float total; ///< Cost up to the node. - unsigned int pidx : 30; ///< Index to parent node. - unsigned int flags : 2; ///< Node flags 0/open/closed. - dtPolyRef id; ///< Polygon ref the node corresponds to. -}; - - -class dtNodePool -{ -public: - dtNodePool(int maxNodes, int hashSize); - ~dtNodePool(); - inline void operator=(const dtNodePool&) {} - void clear(); - dtNode* getNode(dtPolyRef id); - dtNode* findNode(dtPolyRef id); - - inline unsigned int getNodeIdx(const dtNode* node) const - { - if (!node) return 0; - return (unsigned int)(node - m_nodes)+1; - } - - inline dtNode* getNodeAtIdx(unsigned int idx) - { - if (!idx) return 0; - return &m_nodes[idx-1]; - } - - inline const dtNode* getNodeAtIdx(unsigned int idx) const - { - if (!idx) return 0; - return &m_nodes[idx-1]; - } - - inline int getMemUsed() const - { - return sizeof(*this) + - sizeof(dtNode)*m_maxNodes + - sizeof(dtNodeIndex)*m_maxNodes + - sizeof(dtNodeIndex)*m_hashSize; - } - - inline int getMaxNodes() const { return m_maxNodes; } - - inline int getHashSize() const { return m_hashSize; } - inline dtNodeIndex getFirst(int bucket) const { return m_first[bucket]; } - inline dtNodeIndex getNext(int i) const { return m_next[i]; } - -private: - - dtNode* m_nodes; - dtNodeIndex* m_first; - dtNodeIndex* m_next; - const int m_maxNodes; - const int m_hashSize; - int m_nodeCount; -}; - -class dtNodeQueue -{ -public: - dtNodeQueue(int n); - ~dtNodeQueue(); - inline void operator=(dtNodeQueue&) {} - - inline void clear() - { - m_size = 0; - } - - inline dtNode* top() - { - return m_heap[0]; - } - - inline dtNode* pop() - { - dtNode* result = m_heap[0]; - m_size--; - trickleDown(0, m_heap[m_size]); - return result; - } - - inline void push(dtNode* node) - { - m_size++; - bubbleUp(m_size-1, node); - } - - inline void modify(dtNode* node) - { - for (int i = 0; i < m_size; ++i) - { - if (m_heap[i] == node) - { - bubbleUp(i, node); - return; - } - } - } - - inline bool empty() const { return m_size == 0; } - - inline int getMemUsed() const - { - return sizeof(*this) + - sizeof(dtNode*)*(m_capacity+1); - } - - inline int getCapacity() const { return m_capacity; } - -private: - void bubbleUp(int i, dtNode* node); - void trickleDown(int i, dtNode* node); - - dtNode** m_heap; - const int m_capacity; - int m_size; -}; - - -#endif // DETOURNODE_H diff --git a/critterai/src/nav-rcn/Detour/Include/DetourStatus.h b/critterai/src/nav-rcn/Detour/Include/DetourStatus.h deleted file mode 100644 index af822c4a..00000000 --- a/critterai/src/nav-rcn/Detour/Include/DetourStatus.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURSTATUS_H -#define DETOURSTATUS_H - -typedef unsigned int dtStatus; - -// High level status. -static const unsigned int DT_FAILURE = 1u << 31; // Operation failed. -static const unsigned int DT_SUCCESS = 1u << 30; // Operation succeed. -static const unsigned int DT_IN_PROGRESS = 1u << 29; // Operation still in progress. - -// Detail information for status. -static const unsigned int DT_STATUS_DETAIL_MASK = 0x0ffffff; -static const unsigned int DT_WRONG_MAGIC = 1 << 0; // Input data is not recognized. -static const unsigned int DT_WRONG_VERSION = 1 << 1; // Input data is in wrong version. -static const unsigned int DT_OUT_OF_MEMORY = 1 << 2; // Operation ran out of memory. -static const unsigned int DT_INVALID_PARAM = 1 << 3; // An input parameter was invalid. -static const unsigned int DT_BUFFER_TOO_SMALL = 1 << 4; // Result buffer for the query was too small to store all results. -static const unsigned int DT_OUT_OF_NODES = 1 << 5; // Query ran out of nodes during search. -static const unsigned int DT_PARTIAL_RESULT = 1 << 6; // Query did not reach the end location, returning best guess. - - -// Returns true of status is success. -inline bool dtStatusSucceed(dtStatus status) -{ - return (status & DT_SUCCESS) != 0; -} - -// Returns true of status is failure. -inline bool dtStatusFailed(dtStatus status) -{ - return (status & DT_FAILURE) != 0; -} - -// Returns true of status is in progress. -inline bool dtStatusInProgress(dtStatus status) -{ - return (status & DT_IN_PROGRESS) != 0; -} - -// Returns true if specific detail is set. -inline bool dtStatusDetail(dtStatus status, unsigned int detail) -{ - return (status & detail) != 0; -} - -#endif // DETOURSTATUS_H diff --git a/critterai/src/nav-rcn/Detour/Source/DetourAlloc.cpp b/critterai/src/nav-rcn/Detour/Source/DetourAlloc.cpp deleted file mode 100644 index 5f671df5..00000000 --- a/critterai/src/nav-rcn/Detour/Source/DetourAlloc.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include "DetourAlloc.h" - -static void *dtAllocDefault(int size, dtAllocHint) -{ - return malloc(size); -} - -static void dtFreeDefault(void *ptr) -{ - free(ptr); -} - -static dtAllocFunc* sAllocFunc = dtAllocDefault; -static dtFreeFunc* sFreeFunc = dtFreeDefault; - -void dtAllocSetCustom(dtAllocFunc *allocFunc, dtFreeFunc *freeFunc) -{ - sAllocFunc = allocFunc ? allocFunc : dtAllocDefault; - sFreeFunc = freeFunc ? freeFunc : dtFreeDefault; -} - -void* dtAlloc(int size, dtAllocHint hint) -{ - return sAllocFunc(size, hint); -} - -void dtFree(void* ptr) -{ - if (ptr) - sFreeFunc(ptr); -} diff --git a/critterai/src/nav-rcn/Detour/Source/DetourCommon.cpp b/critterai/src/nav-rcn/Detour/Source/DetourCommon.cpp deleted file mode 100644 index b5700f59..00000000 --- a/critterai/src/nav-rcn/Detour/Source/DetourCommon.cpp +++ /dev/null @@ -1,393 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include "DetourCommon.h" - -////////////////////////////////////////////////////////////////////////////////////////// - -float dtSqrt(float x) -{ - return sqrtf(x); -} - -void dtClosestPtPointTriangle(float* closest, const float* p, - const float* a, const float* b, const float* c) -{ - // Check if P in vertex region outside A - float ab[3], ac[3], ap[3]; - dtVsub(ab, b, a); - dtVsub(ac, c, a); - dtVsub(ap, p, a); - float d1 = dtVdot(ab, ap); - float d2 = dtVdot(ac, ap); - if (d1 <= 0.0f && d2 <= 0.0f) - { - // barycentric coordinates (1,0,0) - dtVcopy(closest, a); - return; - } - - // Check if P in vertex region outside B - float bp[3]; - dtVsub(bp, p, b); - float d3 = dtVdot(ab, bp); - float d4 = dtVdot(ac, bp); - if (d3 >= 0.0f && d4 <= d3) - { - // barycentric coordinates (0,1,0) - dtVcopy(closest, b); - return; - } - - // Check if P in edge region of AB, if so return projection of P onto AB - float vc = d1*d4 - d3*d2; - if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) - { - // barycentric coordinates (1-v,v,0) - float v = d1 / (d1 - d3); - closest[0] = a[0] + v * ab[0]; - closest[1] = a[1] + v * ab[1]; - closest[2] = a[2] + v * ab[2]; - return; - } - - // Check if P in vertex region outside C - float cp[3]; - dtVsub(cp, p, c); - float d5 = dtVdot(ab, cp); - float d6 = dtVdot(ac, cp); - if (d6 >= 0.0f && d5 <= d6) - { - // barycentric coordinates (0,0,1) - dtVcopy(closest, c); - return; - } - - // Check if P in edge region of AC, if so return projection of P onto AC - float vb = d5*d2 - d1*d6; - if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) - { - // barycentric coordinates (1-w,0,w) - float w = d2 / (d2 - d6); - closest[0] = a[0] + w * ac[0]; - closest[1] = a[1] + w * ac[1]; - closest[2] = a[2] + w * ac[2]; - return; - } - - // Check if P in edge region of BC, if so return projection of P onto BC - float va = d3*d6 - d5*d4; - if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) - { - // barycentric coordinates (0,1-w,w) - float w = (d4 - d3) / ((d4 - d3) + (d5 - d6)); - closest[0] = b[0] + w * (c[0] - b[0]); - closest[1] = b[1] + w * (c[1] - b[1]); - closest[2] = b[2] + w * (c[2] - b[2]); - return; - } - - // P inside face region. Compute Q through its barycentric coordinates (u,v,w) - float denom = 1.0f / (va + vb + vc); - float v = vb * denom; - float w = vc * denom; - closest[0] = a[0] + ab[0] * v + ac[0] * w; - closest[1] = a[1] + ab[1] * v + ac[1] * w; - closest[2] = a[2] + ab[2] * v + ac[2] * w; -} - -bool dtIntersectSegmentPoly2D(const float* p0, const float* p1, - const float* verts, int nverts, - float& tmin, float& tmax, - int& segMin, int& segMax) -{ - static const float EPS = 0.00000001f; - - tmin = 0; - tmax = 1; - segMin = -1; - segMax = -1; - - float dir[3]; - dtVsub(dir, p1, p0); - - for (int i = 0, j = nverts-1; i < nverts; j=i++) - { - float edge[3], diff[3]; - dtVsub(edge, &verts[i*3], &verts[j*3]); - dtVsub(diff, p0, &verts[j*3]); - const float n = dtVperp2D(edge, diff); - const float d = dtVperp2D(dir, edge); - if (fabsf(d) < EPS) - { - // S is nearly parallel to this edge - if (n < 0) - return false; - else - continue; - } - const float t = n / d; - if (d < 0) - { - // segment S is entering across this edge - if (t > tmin) - { - tmin = t; - segMin = j; - // S enters after leaving polygon - if (tmin > tmax) - return false; - } - } - else - { - // segment S is leaving across this edge - if (t < tmax) - { - tmax = t; - segMax = j; - // S leaves before entering polygon - if (tmax < tmin) - return false; - } - } - } - - return true; -} - -float dtDistancePtSegSqr2D(const float* pt, const float* p, const float* q, float& t) -{ - float pqx = q[0] - p[0]; - float pqz = q[2] - p[2]; - float dx = pt[0] - p[0]; - float dz = pt[2] - p[2]; - float d = pqx*pqx + pqz*pqz; - t = pqx*dx + pqz*dz; - if (d > 0) t /= d; - if (t < 0) t = 0; - else if (t > 1) t = 1; - dx = p[0] + t*pqx - pt[0]; - dz = p[2] + t*pqz - pt[2]; - return dx*dx + dz*dz; -} - -void dtCalcPolyCenter(float* tc, const unsigned short* idx, int nidx, const float* verts) -{ - tc[0] = 0.0f; - tc[1] = 0.0f; - tc[2] = 0.0f; - for (int j = 0; j < nidx; ++j) - { - const float* v = &verts[idx[j]*3]; - tc[0] += v[0]; - tc[1] += v[1]; - tc[2] += v[2]; - } - const float s = 1.0f / nidx; - tc[0] *= s; - tc[1] *= s; - tc[2] *= s; -} - -bool dtClosestHeightPointTriangle(const float* p, const float* a, const float* b, const float* c, float& h) -{ - float v0[3], v1[3], v2[3]; - dtVsub(v0, c,a); - dtVsub(v1, b,a); - dtVsub(v2, p,a); - - const float dot00 = dtVdot2D(v0, v0); - const float dot01 = dtVdot2D(v0, v1); - const float dot02 = dtVdot2D(v0, v2); - const float dot11 = dtVdot2D(v1, v1); - const float dot12 = dtVdot2D(v1, v2); - - // Compute barycentric coordinates - const float invDenom = 1.0f / (dot00 * dot11 - dot01 * dot01); - const float u = (dot11 * dot02 - dot01 * dot12) * invDenom; - const float v = (dot00 * dot12 - dot01 * dot02) * invDenom; - - // The (sloppy) epsilon is needed to allow to get height of points which - // are interpolated along the edges of the triangles. - static const float EPS = 1e-4f; - - // If point lies inside the triangle, return interpolated ycoord. - if (u >= -EPS && v >= -EPS && (u+v) <= 1+EPS) - { - h = a[1] + v0[1]*u + v1[1]*v; - return true; - } - - return false; -} - -/// @par -/// -/// All points are projected onto the xz-plane, so the y-values are ignored. -bool dtPointInPolygon(const float* pt, const float* verts, const int nverts) -{ - // TODO: Replace pnpoly with triArea2D tests? - int i, j; - bool c = false; - for (i = 0, j = nverts-1; i < nverts; j = i++) - { - const float* vi = &verts[i*3]; - const float* vj = &verts[j*3]; - if (((vi[2] > pt[2]) != (vj[2] > pt[2])) && - (pt[0] < (vj[0]-vi[0]) * (pt[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) ) - c = !c; - } - return c; -} - -bool dtDistancePtPolyEdgesSqr(const float* pt, const float* verts, const int nverts, - float* ed, float* et) -{ - // TODO: Replace pnpoly with triArea2D tests? - int i, j; - bool c = false; - for (i = 0, j = nverts-1; i < nverts; j = i++) - { - const float* vi = &verts[i*3]; - const float* vj = &verts[j*3]; - if (((vi[2] > pt[2]) != (vj[2] > pt[2])) && - (pt[0] < (vj[0]-vi[0]) * (pt[2]-vi[2]) / (vj[2]-vi[2]) + vi[0]) ) - c = !c; - ed[j] = dtDistancePtSegSqr2D(pt, vj, vi, et[j]); - } - return c; -} - -static void projectPoly(const float* axis, const float* poly, const int npoly, - float& rmin, float& rmax) -{ - rmin = rmax = dtVdot2D(axis, &poly[0]); - for (int i = 1; i < npoly; ++i) - { - const float d = dtVdot2D(axis, &poly[i*3]); - rmin = dtMin(rmin, d); - rmax = dtMax(rmax, d); - } -} - -inline bool overlapRange(const float amin, const float amax, - const float bmin, const float bmax, - const float eps) -{ - return ((amin+eps) > bmax || (amax-eps) < bmin) ? false : true; -} - -/// @par -/// -/// All vertices are projected onto the xz-plane, so the y-values are ignored. -bool dtOverlapPolyPoly2D(const float* polya, const int npolya, - const float* polyb, const int npolyb) -{ - const float eps = 1e-4f; - - for (int i = 0, j = npolya-1; i < npolya; j=i++) - { - const float* va = &polya[j*3]; - const float* vb = &polya[i*3]; - const float n[3] = { vb[2]-va[2], 0, -(vb[0]-va[0]) }; - float amin,amax,bmin,bmax; - projectPoly(n, polya, npolya, amin,amax); - projectPoly(n, polyb, npolyb, bmin,bmax); - if (!overlapRange(amin,amax, bmin,bmax, eps)) - { - // Found separating axis - return false; - } - } - for (int i = 0, j = npolyb-1; i < npolyb; j=i++) - { - const float* va = &polyb[j*3]; - const float* vb = &polyb[i*3]; - const float n[3] = { vb[2]-va[2], 0, -(vb[0]-va[0]) }; - float amin,amax,bmin,bmax; - projectPoly(n, polya, npolya, amin,amax); - projectPoly(n, polyb, npolyb, bmin,bmax); - if (!overlapRange(amin,amax, bmin,bmax, eps)) - { - // Found separating axis - return false; - } - } - return true; -} - -// Returns a random point in a convex polygon. -// Adapted from Graphics Gems article. -void dtRandomPointInConvexPoly(const float* pts, const int npts, float* areas, - const float s, const float t, float* out) -{ - // Calc triangle araes - float areasum = 0.0f; - for (int i = 2; i < npts; i++) { - areas[i] = dtTriArea2D(&pts[0], &pts[(i-1)*3], &pts[i*3]); - areasum += dtMax(0.001f, areas[i]); - } - // Find sub triangle weighted by area. - const float thr = s*areasum; - float acc = 0.0f; - float u = 0.0f; - int tri = 0; - for (int i = 2; i < npts; i++) { - const float dacc = areas[i]; - if (thr >= acc && thr < (acc+dacc)) - { - u = (thr - acc) / dacc; - tri = i; - break; - } - acc += dacc; - } - - float v = dtSqrt(t); - - const float a = 1 - v; - const float b = (1 - u) * v; - const float c = u * v; - const float* pa = &pts[0]; - const float* pb = &pts[(tri-1)*3]; - const float* pc = &pts[tri*3]; - - out[0] = a*pa[0] + b*pb[0] + c*pc[0]; - out[1] = a*pa[1] + b*pb[1] + c*pc[1]; - out[2] = a*pa[2] + b*pb[2] + c*pc[2]; -} - -inline float vperpXZ(const float* a, const float* b) { return a[0]*b[2] - a[2]*b[0]; } - -bool dtIntersectSegSeg2D(const float* ap, const float* aq, - const float* bp, const float* bq, - float& s, float& t) -{ - float u[3], v[3], w[3]; - dtVsub(u,aq,ap); - dtVsub(v,bq,bp); - dtVsub(w,ap,bp); - float d = vperpXZ(u,v); - if (fabsf(d) < 1e-6f) return false; - s = vperpXZ(v,w) / d; - t = vperpXZ(u,w) / d; - return true; -} - diff --git a/critterai/src/nav-rcn/Detour/Source/DetourNavMesh.cpp b/critterai/src/nav-rcn/Detour/Source/DetourNavMesh.cpp deleted file mode 100644 index 98d354bc..00000000 --- a/critterai/src/nav-rcn/Detour/Source/DetourNavMesh.cpp +++ /dev/null @@ -1,1479 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include -#include -#include "DetourNavMesh.h" -#include "DetourNode.h" -#include "DetourCommon.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include - - -inline bool overlapSlabs(const float* amin, const float* amax, - const float* bmin, const float* bmax, - const float px, const float py) -{ - // Check for horizontal overlap. - // The segment is shrunken a little so that slabs which touch - // at end points are not connected. - const float minx = dtMax(amin[0]+px,bmin[0]+px); - const float maxx = dtMin(amax[0]-px,bmax[0]-px); - if (minx > maxx) - return false; - - // Check vertical overlap. - const float ad = (amax[1]-amin[1]) / (amax[0]-amin[0]); - const float ak = amin[1] - ad*amin[0]; - const float bd = (bmax[1]-bmin[1]) / (bmax[0]-bmin[0]); - const float bk = bmin[1] - bd*bmin[0]; - const float aminy = ad*minx + ak; - const float amaxy = ad*maxx + ak; - const float bminy = bd*minx + bk; - const float bmaxy = bd*maxx + bk; - const float dmin = bminy - aminy; - const float dmax = bmaxy - amaxy; - - // Crossing segments always overlap. - if (dmin*dmax < 0) - return true; - - // Check for overlap at endpoints. - const float thr = dtSqr(py*2); - if (dmin*dmin <= thr || dmax*dmax <= thr) - return true; - - return false; -} - -static float getSlabCoord(const float* va, const int side) -{ - if (side == 0 || side == 4) - return va[0]; - else if (side == 2 || side == 6) - return va[2]; - return 0; -} - -static void calcSlabEndPoints(const float* va, const float* vb, float* bmin, float* bmax, const int side) -{ - if (side == 0 || side == 4) - { - if (va[2] < vb[2]) - { - bmin[0] = va[2]; - bmin[1] = va[1]; - bmax[0] = vb[2]; - bmax[1] = vb[1]; - } - else - { - bmin[0] = vb[2]; - bmin[1] = vb[1]; - bmax[0] = va[2]; - bmax[1] = va[1]; - } - } - else if (side == 2 || side == 6) - { - if (va[0] < vb[0]) - { - bmin[0] = va[0]; - bmin[1] = va[1]; - bmax[0] = vb[0]; - bmax[1] = vb[1]; - } - else - { - bmin[0] = vb[0]; - bmin[1] = vb[1]; - bmax[0] = va[0]; - bmax[1] = va[1]; - } - } -} - -inline int computeTileHash(int x, int y, const int mask) -{ - const unsigned int h1 = 0x8da6b343; // Large multiplicative constants; - const unsigned int h2 = 0xd8163841; // here arbitrarily chosen primes - unsigned int n = h1 * x + h2 * y; - return (int)(n & mask); -} - -inline unsigned int allocLink(dtMeshTile* tile) -{ - if (tile->linksFreeList == DT_NULL_LINK) - return DT_NULL_LINK; - unsigned int link = tile->linksFreeList; - tile->linksFreeList = tile->links[link].next; - return link; -} - -inline void freeLink(dtMeshTile* tile, unsigned int link) -{ - tile->links[link].next = tile->linksFreeList; - tile->linksFreeList = link; -} - - -dtNavMesh* dtAllocNavMesh() -{ - void* mem = dtAlloc(sizeof(dtNavMesh), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtNavMesh; -} - -/// @par -/// -/// This function will only free the memory for tiles with the #DT_TILE_FREE_DATA -/// flag set. -void dtFreeNavMesh(dtNavMesh* navmesh) -{ - if (!navmesh) return; - navmesh->~dtNavMesh(); - dtFree(navmesh); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -/** -@class dtNavMesh - -The navigation mesh consists of one or more tiles defining three primary types of structural data: - -A polygon mesh which defines most of the navigation graph. (See rcPolyMesh for its structure.) -A detail mesh used for determining surface height on the polygon mesh. (See rcPolyMeshDetail for its structure.) -Off-mesh connections, which define custom point-to-point edges within the navigation graph. - -The general build process is as follows: - --# Create rcPolyMesh and rcPolyMeshDetail data using the Recast build pipeline. --# Optionally, create off-mesh connection data. --# Combine the source data into a dtNavMeshCreateParams structure. --# Create a tile data array using dtCreateNavMeshData(). --# Allocate at dtNavMesh object and initialize it. (For single tile navigation meshes, - the tile data is loaded during this step.) --# For multi-tile navigation meshes, load the tile data using dtNavMesh::addTile(). - -Notes: - -- This class is usually used in conjunction with the dtNavMeshQuery class for pathfinding. -- Technically, all navigation meshes are tiled. A 'solo' mesh is simply a navigation mesh initialized - to have only a single tile. -- This class does not implement any asynchronous methods. So the ::dtStatus result of all methods will - always contain either a success or failure flag. - -@see dtNavMeshQuery, dtCreateNavMeshData, dtNavMeshCreateParams, #dtAllocNavMesh, #dtFreeNavMesh -*/ - -dtNavMesh::dtNavMesh() : - m_tileWidth(0), - m_tileHeight(0), - m_maxTiles(0), - m_tileLutSize(0), - m_tileLutMask(0), - m_posLookup(0), - m_nextFree(0), - m_tiles(0), - m_saltBits(0), - m_tileBits(0), - m_polyBits(0) -{ - memset(&m_params, 0, sizeof(dtNavMeshParams)); - m_orig[0] = 0; - m_orig[1] = 0; - m_orig[2] = 0; -} - -dtNavMesh::~dtNavMesh() -{ - for (int i = 0; i < m_maxTiles; ++i) - { - if (m_tiles[i].flags & DT_TILE_FREE_DATA) - { - dtFree(m_tiles[i].data); - m_tiles[i].data = 0; - m_tiles[i].dataSize = 0; - } - } - dtFree(m_posLookup); - dtFree(m_tiles); -} - -dtStatus dtNavMesh::init(const dtNavMeshParams* params) -{ - memcpy(&m_params, params, sizeof(dtNavMeshParams)); - dtVcopy(m_orig, params->orig); - m_tileWidth = params->tileWidth; - m_tileHeight = params->tileHeight; - - // Init tiles - m_maxTiles = params->maxTiles; - m_tileLutSize = dtNextPow2(params->maxTiles/4); - if (!m_tileLutSize) m_tileLutSize = 1; - m_tileLutMask = m_tileLutSize-1; - - m_tiles = (dtMeshTile*)dtAlloc(sizeof(dtMeshTile)*m_maxTiles, DT_ALLOC_PERM); - if (!m_tiles) - return DT_FAILURE | DT_OUT_OF_MEMORY; - m_posLookup = (dtMeshTile**)dtAlloc(sizeof(dtMeshTile*)*m_tileLutSize, DT_ALLOC_PERM); - if (!m_posLookup) - return DT_FAILURE | DT_OUT_OF_MEMORY; - memset(m_tiles, 0, sizeof(dtMeshTile)*m_maxTiles); - memset(m_posLookup, 0, sizeof(dtMeshTile*)*m_tileLutSize); - m_nextFree = 0; - for (int i = m_maxTiles-1; i >= 0; --i) - { - m_tiles[i].salt = 1; - m_tiles[i].next = m_nextFree; - m_nextFree = &m_tiles[i]; - } - - // Init ID generator values. - m_tileBits = dtIlog2(dtNextPow2((unsigned int)params->maxTiles)); - m_polyBits = dtIlog2(dtNextPow2((unsigned int)params->maxPolys)); - // Only allow 31 salt bits, since the salt mask is calculated using 32bit uint and it will overflow. - m_saltBits = dtMin((unsigned int)31, 32 - m_tileBits - m_polyBits); - if (m_saltBits < 10) - return DT_FAILURE | DT_INVALID_PARAM; - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::init(unsigned char* data, const int dataSize, const int flags) -{ - // Make sure the data is in right format. - dtMeshHeader* header = (dtMeshHeader*)data; - if (header->magic != DT_NAVMESH_MAGIC) - return DT_FAILURE | DT_WRONG_MAGIC; - if (header->version != DT_NAVMESH_VERSION) - return DT_FAILURE | DT_WRONG_VERSION; - - dtNavMeshParams params; - dtVcopy(params.orig, header->bmin); - params.tileWidth = header->bmax[0] - header->bmin[0]; - params.tileHeight = header->bmax[2] - header->bmin[2]; - params.maxTiles = 1; - params.maxPolys = header->polyCount; - - dtStatus status = init(¶ms); - if (dtStatusFailed(status)) - return status; - - return addTile(data, dataSize, flags, 0, 0); -} - -/// @par -/// -/// @note The parameters are created automatically when the single tile -/// initialization is performed. -const dtNavMeshParams* dtNavMesh::getParams() const -{ - return &m_params; -} - -////////////////////////////////////////////////////////////////////////////////////////// -int dtNavMesh::findConnectingPolys(const float* va, const float* vb, - const dtMeshTile* tile, int side, - dtPolyRef* con, float* conarea, int maxcon) const -{ - if (!tile) return 0; - - float amin[2], amax[2]; - calcSlabEndPoints(va,vb, amin,amax, side); - const float apos = getSlabCoord(va, side); - - // Remove links pointing to 'side' and compact the links array. - float bmin[2], bmax[2]; - unsigned short m = DT_EXT_LINK | (unsigned short)side; - int n = 0; - - dtPolyRef base = getPolyRefBase(tile); - - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - const int nv = poly->vertCount; - for (int j = 0; j < nv; ++j) - { - // Skip edges which do not point to the right side. - if (poly->neis[j] != m) continue; - - const float* vc = &tile->verts[poly->verts[j]*3]; - const float* vd = &tile->verts[poly->verts[(j+1) % nv]*3]; - const float bpos = getSlabCoord(vc, side); - - // Segments are not close enough. - if (dtAbs(apos-bpos) > 0.01f) - continue; - - // Check if the segments touch. - calcSlabEndPoints(vc,vd, bmin,bmax, side); - - if (!overlapSlabs(amin,amax, bmin,bmax, 0.01f, tile->header->walkableClimb)) continue; - - // Add return value. - if (n < maxcon) - { - conarea[n*2+0] = dtMax(amin[0], bmin[0]); - conarea[n*2+1] = dtMin(amax[0], bmax[0]); - con[n] = base | (dtPolyRef)i; - n++; - } - break; - } - } - return n; -} - -void dtNavMesh::unconnectExtLinks(dtMeshTile* tile, dtMeshTile* target) -{ - if (!tile || !target) return; - - const unsigned int targetNum = decodePolyIdTile(getTileRef(target)); - - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - unsigned int j = poly->firstLink; - unsigned int pj = DT_NULL_LINK; - while (j != DT_NULL_LINK) - { - if (tile->links[j].side != 0xff && - decodePolyIdTile(tile->links[j].ref) == targetNum) - { - // Revove link. - unsigned int nj = tile->links[j].next; - if (pj == DT_NULL_LINK) - poly->firstLink = nj; - else - tile->links[pj].next = nj; - freeLink(tile, j); - j = nj; - } - else - { - // Advance - pj = j; - j = tile->links[j].next; - } - } - } -} - -void dtNavMesh::connectExtLinks(dtMeshTile* tile, dtMeshTile* target, int side) -{ - if (!tile) return; - - // Connect border links. - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - - // Create new links. -// unsigned short m = DT_EXT_LINK | (unsigned short)side; - - const int nv = poly->vertCount; - for (int j = 0; j < nv; ++j) - { - // Skip non-portal edges. - if ((poly->neis[j] & DT_EXT_LINK) == 0) - continue; - - const int dir = (int)(poly->neis[j] & 0xff); - if (side != -1 && dir != side) - continue; - - // Create new links - const float* va = &tile->verts[poly->verts[j]*3]; - const float* vb = &tile->verts[poly->verts[(j+1) % nv]*3]; - dtPolyRef nei[4]; - float neia[4*2]; - int nnei = findConnectingPolys(va,vb, target, dtOppositeTile(dir), nei,neia,4); - for (int k = 0; k < nnei; ++k) - { - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - dtLink* link = &tile->links[idx]; - link->ref = nei[k]; - link->edge = (unsigned char)j; - link->side = (unsigned char)dir; - - link->next = poly->firstLink; - poly->firstLink = idx; - - // Compress portal limits to a byte value. - if (dir == 0 || dir == 4) - { - float tmin = (neia[k*2+0]-va[2]) / (vb[2]-va[2]); - float tmax = (neia[k*2+1]-va[2]) / (vb[2]-va[2]); - if (tmin > tmax) - dtSwap(tmin,tmax); - link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f); - link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f); - } - else if (dir == 2 || dir == 6) - { - float tmin = (neia[k*2+0]-va[0]) / (vb[0]-va[0]); - float tmax = (neia[k*2+1]-va[0]) / (vb[0]-va[0]); - if (tmin > tmax) - dtSwap(tmin,tmax); - link->bmin = (unsigned char)(dtClamp(tmin, 0.0f, 1.0f)*255.0f); - link->bmax = (unsigned char)(dtClamp(tmax, 0.0f, 1.0f)*255.0f); - } - } - } - } - } -} - -void dtNavMesh::connectExtOffMeshLinks(dtMeshTile* tile, dtMeshTile* target, int side) -{ - if (!tile) return; - - // Connect off-mesh links. - // We are interested on links which land from target tile to this tile. - const unsigned char oppositeSide = (side == -1) ? 0xff : (unsigned char)dtOppositeTile(side); - - for (int i = 0; i < target->header->offMeshConCount; ++i) - { - dtOffMeshConnection* targetCon = &target->offMeshCons[i]; - if (targetCon->side != oppositeSide) - continue; - - dtPoly* targetPoly = &target->polys[targetCon->poly]; - // Skip off-mesh connections which start location could not be connected at all. - if (targetPoly->firstLink == DT_NULL_LINK) - continue; - - const float ext[3] = { targetCon->rad, target->header->walkableClimb, targetCon->rad }; - - // Find polygon to connect to. - const float* p = &targetCon->pos[3]; - float nearestPt[3]; - dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); - if (!ref) - continue; - // findNearestPoly may return too optimistic results, further check to make sure. - if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(targetCon->rad)) - continue; - // Make sure the location is on current mesh. - float* v = &target->verts[targetPoly->verts[1]*3]; - dtVcopy(v, nearestPt); - - // Link off-mesh connection to target poly. - unsigned int idx = allocLink(target); - if (idx != DT_NULL_LINK) - { - dtLink* link = &target->links[idx]; - link->ref = ref; - link->edge = (unsigned char)1; - link->side = oppositeSide; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = targetPoly->firstLink; - targetPoly->firstLink = idx; - } - - // Link target poly to off-mesh connection. - if (targetCon->flags & DT_OFFMESH_CON_BIDIR) - { - unsigned int tidx = allocLink(tile); - if (tidx != DT_NULL_LINK) - { - const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); - dtPoly* landPoly = &tile->polys[landPolyIdx]; - dtLink* link = &tile->links[tidx]; - link->ref = getPolyRefBase(target) | (dtPolyRef)(targetCon->poly); - link->edge = 0xff; - link->side = (unsigned char)(side == -1 ? 0xff : side); - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = landPoly->firstLink; - landPoly->firstLink = tidx; - } - } - } - -} - -void dtNavMesh::connectIntLinks(dtMeshTile* tile) -{ - if (!tile) return; - - dtPolyRef base = getPolyRefBase(tile); - - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* poly = &tile->polys[i]; - poly->firstLink = DT_NULL_LINK; - - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Build edge links backwards so that the links will be - // in the linked list from lowest index to highest. - for (int j = poly->vertCount-1; j >= 0; --j) - { - // Skip hard and non-internal edges. - if (poly->neis[j] == 0 || (poly->neis[j] & DT_EXT_LINK)) continue; - - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - dtLink* link = &tile->links[idx]; - link->ref = base | (dtPolyRef)(poly->neis[j]-1); - link->edge = (unsigned char)j; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = poly->firstLink; - poly->firstLink = idx; - } - } - } -} - -void dtNavMesh::baseOffMeshLinks(dtMeshTile* tile) -{ - if (!tile) return; - - dtPolyRef base = getPolyRefBase(tile); - - // Base off-mesh connection start points. - for (int i = 0; i < tile->header->offMeshConCount; ++i) - { - dtOffMeshConnection* con = &tile->offMeshCons[i]; - dtPoly* poly = &tile->polys[con->poly]; - - const float ext[3] = { con->rad, tile->header->walkableClimb, con->rad }; - - // Find polygon to connect to. - const float* p = &con->pos[0]; // First vertex - float nearestPt[3]; - dtPolyRef ref = findNearestPolyInTile(tile, p, ext, nearestPt); - if (!ref) continue; - // findNearestPoly may return too optimistic results, further check to make sure. - if (dtSqr(nearestPt[0]-p[0])+dtSqr(nearestPt[2]-p[2]) > dtSqr(con->rad)) - continue; - // Make sure the location is on current mesh. - float* v = &tile->verts[poly->verts[0]*3]; - dtVcopy(v, nearestPt); - - // Link off-mesh connection to target poly. - unsigned int idx = allocLink(tile); - if (idx != DT_NULL_LINK) - { - dtLink* link = &tile->links[idx]; - link->ref = ref; - link->edge = (unsigned char)0; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = poly->firstLink; - poly->firstLink = idx; - } - - // Start end-point is always connect back to off-mesh connection. - unsigned int tidx = allocLink(tile); - if (tidx != DT_NULL_LINK) - { - const unsigned short landPolyIdx = (unsigned short)decodePolyIdPoly(ref); - dtPoly* landPoly = &tile->polys[landPolyIdx]; - dtLink* link = &tile->links[tidx]; - link->ref = base | (dtPolyRef)(con->poly); - link->edge = 0xff; - link->side = 0xff; - link->bmin = link->bmax = 0; - // Add to linked list. - link->next = landPoly->firstLink; - landPoly->firstLink = tidx; - } - } -} - -void dtNavMesh::closestPointOnPolyInTile(const dtMeshTile* tile, unsigned int ip, - const float* pos, float* closest) const -{ - const dtPoly* poly = &tile->polys[ip]; - // Off-mesh connections don't have detail polygons. - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - const float* v0 = &tile->verts[poly->verts[0]*3]; - const float* v1 = &tile->verts[poly->verts[1]*3]; - const float d0 = dtVdist(pos, v0); - const float d1 = dtVdist(pos, v1); - const float u = d0 / (d0+d1); - dtVlerp(closest, v0, v1, u); - return; - } - - const dtPolyDetail* pd = &tile->detailMeshes[ip]; - - // Clamp point to be inside the polygon. - float verts[DT_VERTS_PER_POLYGON*3]; - float edged[DT_VERTS_PER_POLYGON]; - float edget[DT_VERTS_PER_POLYGON]; - const int nv = poly->vertCount; - for (int i = 0; i < nv; ++i) - dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]); - - dtVcopy(closest, pos); - if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) - { - // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) - { - if (edged[i] < dmin) - { - dmin = edged[i]; - imin = i; - } - } - const float* va = &verts[imin*3]; - const float* vb = &verts[((imin+1)%nv)*3]; - dtVlerp(closest, va, vb, edget[imin]); - } - - // Find height at the location. - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - float h; - if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) - { - closest[1] = h; - break; - } - } -} - -dtPolyRef dtNavMesh::findNearestPolyInTile(const dtMeshTile* tile, - const float* center, const float* extents, - float* nearestPt) const -{ - float bmin[3], bmax[3]; - dtVsub(bmin, center, extents); - dtVadd(bmax, center, extents); - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = queryPolygonsInTile(tile, bmin, bmax, polys, 128); - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) - { - dtPolyRef ref = polys[i]; - float closestPtPoly[3]; - closestPointOnPolyInTile(tile, decodePolyIdPoly(ref), center, closestPtPoly); - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) - { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; - } - } - - return nearest; -} - -int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, - dtPolyRef* polys, const int maxPolys) const -{ - if (tile->bvTree) - { - const dtBVNode* node = &tile->bvTree[0]; - const dtBVNode* end = &tile->bvTree[tile->header->bvNodeCount]; - const float* tbmin = tile->header->bmin; - const float* tbmax = tile->header->bmax; - const float qfac = tile->header->bvQuantFactor; - - // Calculate quantized box - unsigned short bmin[3], bmax[3]; - // dtClamp query box to world box. - float minx = dtClamp(qmin[0], tbmin[0], tbmax[0]) - tbmin[0]; - float miny = dtClamp(qmin[1], tbmin[1], tbmax[1]) - tbmin[1]; - float minz = dtClamp(qmin[2], tbmin[2], tbmax[2]) - tbmin[2]; - float maxx = dtClamp(qmax[0], tbmin[0], tbmax[0]) - tbmin[0]; - float maxy = dtClamp(qmax[1], tbmin[1], tbmax[1]) - tbmin[1]; - float maxz = dtClamp(qmax[2], tbmin[2], tbmax[2]) - tbmin[2]; - // Quantize - bmin[0] = (unsigned short)(qfac * minx) & 0xfffe; - bmin[1] = (unsigned short)(qfac * miny) & 0xfffe; - bmin[2] = (unsigned short)(qfac * minz) & 0xfffe; - bmax[0] = (unsigned short)(qfac * maxx + 1) | 1; - bmax[1] = (unsigned short)(qfac * maxy + 1) | 1; - bmax[2] = (unsigned short)(qfac * maxz + 1) | 1; - - // Traverse tree - dtPolyRef base = getPolyRefBase(tile); - int n = 0; - while (node < end) - { - const bool overlap = dtOverlapQuantBounds(bmin, bmax, node->bmin, node->bmax); - const bool isLeafNode = node->i >= 0; - - if (isLeafNode && overlap) - { - if (n < maxPolys) - polys[n++] = base | (dtPolyRef)node->i; - } - - if (overlap || isLeafNode) - node++; - else - { - const int escapeIndex = -node->i; - node += escapeIndex; - } - } - - return n; - } - else - { - float bmin[3], bmax[3]; - int n = 0; - dtPolyRef base = getPolyRefBase(tile); - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - // Calc polygon bounds. - const float* v = &tile->verts[p->verts[0]*3]; - dtVcopy(bmin, v); - dtVcopy(bmax, v); - for (int j = 1; j < p->vertCount; ++j) - { - v = &tile->verts[p->verts[j]*3]; - dtVmin(bmin, v); - dtVmax(bmax, v); - } - if (dtOverlapBounds(qmin,qmax, bmin,bmax)) - { - if (n < maxPolys) - polys[n++] = base | (dtPolyRef)i; - } - } - return n; - } -} - -/// @par -/// -/// The add operation will fail if the data is in the wrong format, the allocated tile -/// space is full, or there is a tile already at the specified reference. -/// -/// The lastRef parameter is used to restore a tile with the same tile -/// reference it had previously used. In this case the #dtPolyRef's for the -/// tile will be restored to the same values they were before the tile was -/// removed. -/// -/// @see dtCreateNavMeshData, #removeTile -dtStatus dtNavMesh::addTile(unsigned char* data, int dataSize, int flags, - dtTileRef lastRef, dtTileRef* result) -{ - // Make sure the data is in right format. - dtMeshHeader* header = (dtMeshHeader*)data; - if (header->magic != DT_NAVMESH_MAGIC) - return DT_FAILURE | DT_WRONG_MAGIC; - if (header->version != DT_NAVMESH_VERSION) - return DT_FAILURE | DT_WRONG_VERSION; - - // Make sure the location is free. - if (getTileAt(header->x, header->y, header->layer)) - return DT_FAILURE; - - // Allocate a tile. - dtMeshTile* tile = 0; - if (!lastRef) - { - if (m_nextFree) - { - tile = m_nextFree; - m_nextFree = tile->next; - tile->next = 0; - } - } - else - { - // Try to relocate the tile to specific index with same salt. - int tileIndex = (int)decodePolyIdTile((dtPolyRef)lastRef); - if (tileIndex >= m_maxTiles) - return DT_FAILURE | DT_OUT_OF_MEMORY; - // Try to find the specific tile id from the free list. - dtMeshTile* target = &m_tiles[tileIndex]; - dtMeshTile* prev = 0; - tile = m_nextFree; - while (tile && tile != target) - { - prev = tile; - tile = tile->next; - } - // Could not find the correct location. - if (tile != target) - return DT_FAILURE | DT_OUT_OF_MEMORY; - // Remove from freelist - if (!prev) - m_nextFree = tile->next; - else - prev->next = tile->next; - - // Restore salt. - tile->salt = decodePolyIdSalt((dtPolyRef)lastRef); - } - - // Make sure we could allocate a tile. - if (!tile) - return DT_FAILURE | DT_OUT_OF_MEMORY; - - // Insert tile into the position lut. - int h = computeTileHash(header->x, header->y, m_tileLutMask); - tile->next = m_posLookup[h]; - m_posLookup[h] = tile; - - // Patch header pointers. - const int headerSize = dtAlign4(sizeof(dtMeshHeader)); - const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount); - const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount); - const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount)); - const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount); - const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount); - const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount); - const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount); - const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); - - unsigned char* d = data + headerSize; - tile->verts = (float*)d; d += vertsSize; - tile->polys = (dtPoly*)d; d += polysSize; - tile->links = (dtLink*)d; d += linksSize; - tile->detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - tile->detailVerts = (float*)d; d += detailVertsSize; - tile->detailTris = (unsigned char*)d; d += detailTrisSize; - tile->bvTree = (dtBVNode*)d; d += bvtreeSize; - tile->offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize; - - // If there are no items in the bvtree, reset the tree pointer. - if (!bvtreeSize) - tile->bvTree = 0; - - // Build links freelist - tile->linksFreeList = 0; - tile->links[header->maxLinkCount-1].next = DT_NULL_LINK; - for (int i = 0; i < header->maxLinkCount-1; ++i) - tile->links[i].next = i+1; - - // Init tile. - tile->header = header; - tile->data = data; - tile->dataSize = dataSize; - tile->flags = flags; - - connectIntLinks(tile); - baseOffMeshLinks(tile); - - // Create connections with neighbour tiles. - static const int MAX_NEIS = 32; - dtMeshTile* neis[MAX_NEIS]; - int nneis; - - // Connect with layers in current tile. - nneis = getTilesAt(header->x, header->y, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - if (neis[j] != tile) - { - connectExtLinks(tile, neis[j], -1); - connectExtLinks(neis[j], tile, -1); - } - connectExtOffMeshLinks(tile, neis[j], -1); - connectExtOffMeshLinks(neis[j], tile, -1); - } - - // Connect with neighbour tiles. - for (int i = 0; i < 8; ++i) - { - nneis = getNeighbourTilesAt(header->x, header->y, i, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - connectExtLinks(tile, neis[j], i); - connectExtLinks(neis[j], tile, dtOppositeTile(i)); - connectExtOffMeshLinks(tile, neis[j], i); - connectExtOffMeshLinks(neis[j], tile, dtOppositeTile(i)); - } - } - - if (result) - *result = getTileRef(tile); - - return DT_SUCCESS; -} - -const dtMeshTile* dtNavMesh::getTileAt(const int x, const int y, const int layer) const -{ - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y && - tile->header->layer == layer) - { - return tile; - } - tile = tile->next; - } - return 0; -} - -int dtNavMesh::getNeighbourTilesAt(const int x, const int y, const int side, dtMeshTile** tiles, const int maxTiles) const -{ - int nx = x, ny = y; - switch (side) - { - case 0: nx++; break; - case 1: nx++; ny++; break; - case 2: ny++; break; - case 3: nx--; ny++; break; - case 4: nx--; break; - case 5: nx--; ny--; break; - case 6: ny--; break; - case 7: nx++; ny--; break; - }; - - return getTilesAt(nx, ny, tiles, maxTiles); -} - -int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile** tiles, const int maxTiles) const -{ - int n = 0; - - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y) - { - if (n < maxTiles) - tiles[n++] = tile; - } - tile = tile->next; - } - - return n; -} - -/// @par -/// -/// This function will not fail if the tiles array is too small to hold the -/// entire result set. It will simply fill the array to capacity. -int dtNavMesh::getTilesAt(const int x, const int y, dtMeshTile const** tiles, const int maxTiles) const -{ - int n = 0; - - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y) - { - if (n < maxTiles) - tiles[n++] = tile; - } - tile = tile->next; - } - - return n; -} - - -dtTileRef dtNavMesh::getTileRefAt(const int x, const int y, const int layer) const -{ - // Find tile based on hash. - int h = computeTileHash(x,y,m_tileLutMask); - dtMeshTile* tile = m_posLookup[h]; - while (tile) - { - if (tile->header && - tile->header->x == x && - tile->header->y == y && - tile->header->layer == layer) - { - return getTileRef(tile); - } - tile = tile->next; - } - return 0; -} - -const dtMeshTile* dtNavMesh::getTileByRef(dtTileRef ref) const -{ - if (!ref) - return 0; - unsigned int tileIndex = decodePolyIdTile((dtPolyRef)ref); - unsigned int tileSalt = decodePolyIdSalt((dtPolyRef)ref); - if ((int)tileIndex >= m_maxTiles) - return 0; - const dtMeshTile* tile = &m_tiles[tileIndex]; - if (tile->salt != tileSalt) - return 0; - return tile; -} - -int dtNavMesh::getMaxTiles() const -{ - return m_maxTiles; -} - -dtMeshTile* dtNavMesh::getTile(int i) -{ - return &m_tiles[i]; -} - -const dtMeshTile* dtNavMesh::getTile(int i) const -{ - return &m_tiles[i]; -} - -void dtNavMesh::calcTileLoc(const float* pos, int* tx, int* ty) const -{ - *tx = (int)floorf((pos[0]-m_orig[0]) / m_tileWidth); - *ty = (int)floorf((pos[2]-m_orig[2]) / m_tileHeight); -} - -dtStatus dtNavMesh::getTileAndPolyByRef(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - if (ip >= (unsigned int)m_tiles[it].header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - *tile = &m_tiles[it]; - *poly = &m_tiles[it].polys[ip]; - return DT_SUCCESS; -} - -/// @par -/// -/// @warning Only use this function if it is known that the provided polygon -/// reference is valid. This function is faster than #getTileAndPolyByRef, but -/// it does not validate the reference. -void dtNavMesh::getTileAndPolyByRefUnsafe(const dtPolyRef ref, const dtMeshTile** tile, const dtPoly** poly) const -{ - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - *tile = &m_tiles[it]; - *poly = &m_tiles[it].polys[ip]; -} - -bool dtNavMesh::isValidPolyRef(dtPolyRef ref) const -{ - if (!ref) return false; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return false; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return false; - if (ip >= (unsigned int)m_tiles[it].header->polyCount) return false; - return true; -} - -/// @par -/// -/// This function returns the data for the tile so that, if desired, -/// it can be added back to the navigation mesh at a later point. -/// -/// @see #addTile -dtStatus dtNavMesh::removeTile(dtTileRef ref, unsigned char** data, int* dataSize) -{ - if (!ref) - return DT_FAILURE | DT_INVALID_PARAM; - unsigned int tileIndex = decodePolyIdTile((dtPolyRef)ref); - unsigned int tileSalt = decodePolyIdSalt((dtPolyRef)ref); - if ((int)tileIndex >= m_maxTiles) - return DT_FAILURE | DT_INVALID_PARAM; - dtMeshTile* tile = &m_tiles[tileIndex]; - if (tile->salt != tileSalt) - return DT_FAILURE | DT_INVALID_PARAM; - - // Remove tile from hash lookup. - int h = computeTileHash(tile->header->x,tile->header->y,m_tileLutMask); - dtMeshTile* prev = 0; - dtMeshTile* cur = m_posLookup[h]; - while (cur) - { - if (cur == tile) - { - if (prev) - prev->next = cur->next; - else - m_posLookup[h] = cur->next; - break; - } - prev = cur; - cur = cur->next; - } - - // Remove connections to neighbour tiles. - // Create connections with neighbour tiles. - static const int MAX_NEIS = 32; - dtMeshTile* neis[MAX_NEIS]; - int nneis; - - // Connect with layers in current tile. - nneis = getTilesAt(tile->header->x, tile->header->y, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - if (neis[j] == tile) continue; - unconnectExtLinks(neis[j], tile); - } - - // Connect with neighbour tiles. - for (int i = 0; i < 8; ++i) - { - nneis = getNeighbourTilesAt(tile->header->x, tile->header->y, i, neis, MAX_NEIS); - for (int j = 0; j < nneis; ++j) - unconnectExtLinks(neis[j], tile); - } - - // Reset tile. - if (tile->flags & DT_TILE_FREE_DATA) - { - // Owns data - dtFree(tile->data); - tile->data = 0; - tile->dataSize = 0; - if (data) *data = 0; - if (dataSize) *dataSize = 0; - } - else - { - if (data) *data = tile->data; - if (dataSize) *dataSize = tile->dataSize; - } - - tile->header = 0; - tile->flags = 0; - tile->linksFreeList = 0; - tile->polys = 0; - tile->verts = 0; - tile->links = 0; - tile->detailMeshes = 0; - tile->detailVerts = 0; - tile->detailTris = 0; - tile->bvTree = 0; - tile->offMeshCons = 0; - - // Update salt, salt should never be zero. - tile->salt = (tile->salt+1) & ((1<salt == 0) - tile->salt++; - - // Add to free list. - tile->next = m_nextFree; - m_nextFree = tile; - - return DT_SUCCESS; -} - -dtTileRef dtNavMesh::getTileRef(const dtMeshTile* tile) const -{ - if (!tile) return 0; - const unsigned int it = (unsigned int)(tile - m_tiles); - return (dtTileRef)encodePolyId(tile->salt, it, 0); -} - -/// @par -/// -/// Example use case: -/// @code -/// -/// const dtPolyRef base = navmesh->getPolyRefBase(tile); -/// for (int i = 0; i < tile->header->polyCount; ++i) -/// { -/// const dtPoly* p = &tile->polys[i]; -/// const dtPolyRef ref = base | (dtPolyRef)i; -/// -/// // Use the reference to access the polygon data. -/// } -/// @endcode -dtPolyRef dtNavMesh::getPolyRefBase(const dtMeshTile* tile) const -{ - if (!tile) return 0; - const unsigned int it = (unsigned int)(tile - m_tiles); - return encodePolyId(tile->salt, it, 0); -} - -struct dtTileState -{ - int magic; // Magic number, used to identify the data. - int version; // Data version number. - dtTileRef ref; // Tile ref at the time of storing the data. -}; - -struct dtPolyState -{ - unsigned short flags; // Flags (see dtPolyFlags). - unsigned char area; // Area ID of the polygon. -}; - -/// @see #storeTileState -int dtNavMesh::getTileStateSize(const dtMeshTile* tile) const -{ - if (!tile) return 0; - const int headerSize = dtAlign4(sizeof(dtTileState)); - const int polyStateSize = dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); - return headerSize + polyStateSize; -} - -/// @par -/// -/// Tile state includes non-structural data such as polygon flags, area ids, etc. -/// @note The state data is only valid until the tile reference changes. -/// @see #getTileStateSize, #restoreTileState -dtStatus dtNavMesh::storeTileState(const dtMeshTile* tile, unsigned char* data, const int maxDataSize) const -{ - // Make sure there is enough space to store the state. - const int sizeReq = getTileStateSize(tile); - if (maxDataSize < sizeReq) - return DT_FAILURE | DT_BUFFER_TOO_SMALL; - - dtTileState* tileState = (dtTileState*)data; data += dtAlign4(sizeof(dtTileState)); - dtPolyState* polyStates = (dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); - - // Store tile state. - tileState->magic = DT_NAVMESH_STATE_MAGIC; - tileState->version = DT_NAVMESH_STATE_VERSION; - tileState->ref = getTileRef(tile); - - // Store per poly state. - for (int i = 0; i < tile->header->polyCount; ++i) - { - const dtPoly* p = &tile->polys[i]; - dtPolyState* s = &polyStates[i]; - s->flags = p->flags; - s->area = p->getArea(); - } - - return DT_SUCCESS; -} - -/// @par -/// -/// Tile state includes non-structural data such as polygon flags, area ids, etc. -/// @note This function does not impact the tile's #dtTileRef and #dtPolyRef's. -/// @see #storeTileState -dtStatus dtNavMesh::restoreTileState(dtMeshTile* tile, const unsigned char* data, const int maxDataSize) -{ - // Make sure there is enough space to store the state. - const int sizeReq = getTileStateSize(tile); - if (maxDataSize < sizeReq) - return DT_FAILURE | DT_INVALID_PARAM; - - const dtTileState* tileState = (const dtTileState*)data; data += dtAlign4(sizeof(dtTileState)); - const dtPolyState* polyStates = (const dtPolyState*)data; data += dtAlign4(sizeof(dtPolyState) * tile->header->polyCount); - - // Check that the restore is possible. - if (tileState->magic != DT_NAVMESH_STATE_MAGIC) - return DT_FAILURE | DT_WRONG_MAGIC; - if (tileState->version != DT_NAVMESH_STATE_VERSION) - return DT_FAILURE | DT_WRONG_VERSION; - if (tileState->ref != getTileRef(tile)) - return DT_FAILURE | DT_INVALID_PARAM; - - // Restore per poly state. - for (int i = 0; i < tile->header->polyCount; ++i) - { - dtPoly* p = &tile->polys[i]; - const dtPolyState* s = &polyStates[i]; - p->flags = s->flags; - p->setArea(s->area); - } - - return DT_SUCCESS; -} - -/// @par -/// -/// Off-mesh connections are stored in the navigation mesh as special 2-vertex -/// polygons with a single edge. At least one of the vertices is expected to be -/// inside a normal polygon. So an off-mesh connection is "entered" from a -/// normal polygon at one of its endpoints. This is the polygon identified by -/// the prevRef parameter. -dtStatus dtNavMesh::getOffMeshConnectionPolyEndPoints(dtPolyRef prevRef, dtPolyRef polyRef, float* startPos, float* endPos) const -{ - unsigned int salt, it, ip; - - if (!polyRef) - return DT_FAILURE; - - // Get current polygon - decodePolyId(polyRef, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - const dtPoly* poly = &tile->polys[ip]; - - // Make sure that the current poly is indeed off-mesh link. - if (poly->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) - return DT_FAILURE; - - // Figure out which way to hand out the vertices. - int idx0 = 0, idx1 = 1; - - // Find link that points to first vertex. - for (unsigned int i = poly->firstLink; i != DT_NULL_LINK; i = tile->links[i].next) - { - if (tile->links[i].edge == 0) - { - if (tile->links[i].ref != prevRef) - { - idx0 = 1; - idx1 = 0; - } - break; - } - } - - dtVcopy(startPos, &tile->verts[poly->verts[idx0]*3]); - dtVcopy(endPos, &tile->verts[poly->verts[idx1]*3]); - - return DT_SUCCESS; -} - - -const dtOffMeshConnection* dtNavMesh::getOffMeshConnectionByRef(dtPolyRef ref) const -{ - unsigned int salt, it, ip; - - if (!ref) - return 0; - - // Get current polygon - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return 0; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return 0; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return 0; - const dtPoly* poly = &tile->polys[ip]; - - // Make sure that the current poly is indeed off-mesh link. - if (poly->getType() != DT_POLYTYPE_OFFMESH_CONNECTION) - return 0; - - const unsigned int idx = ip - tile->header->offMeshBase; - dtAssert(idx < (unsigned int)tile->header->offMeshConCount); - return &tile->offMeshCons[idx]; -} - - -dtStatus dtNavMesh::setPolyFlags(dtPolyRef ref, unsigned short flags) -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - dtPoly* poly = &tile->polys[ip]; - - // Change flags. - poly->flags = flags; - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::getPolyFlags(dtPolyRef ref, unsigned short* resultFlags) const -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - const dtPoly* poly = &tile->polys[ip]; - - *resultFlags = poly->flags; - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::setPolyArea(dtPolyRef ref, unsigned char area) -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - dtPoly* poly = &tile->polys[ip]; - - poly->setArea(area); - - return DT_SUCCESS; -} - -dtStatus dtNavMesh::getPolyArea(dtPolyRef ref, unsigned char* resultArea) const -{ - if (!ref) return DT_FAILURE; - unsigned int salt, it, ip; - decodePolyId(ref, salt, it, ip); - if (it >= (unsigned int)m_maxTiles) return DT_FAILURE | DT_INVALID_PARAM; - if (m_tiles[it].salt != salt || m_tiles[it].header == 0) return DT_FAILURE | DT_INVALID_PARAM; - const dtMeshTile* tile = &m_tiles[it]; - if (ip >= (unsigned int)tile->header->polyCount) return DT_FAILURE | DT_INVALID_PARAM; - const dtPoly* poly = &tile->polys[ip]; - - *resultArea = poly->getArea(); - - return DT_SUCCESS; -} - diff --git a/critterai/src/nav-rcn/Detour/Source/DetourNavMeshBuilder.cpp b/critterai/src/nav-rcn/Detour/Source/DetourNavMeshBuilder.cpp deleted file mode 100644 index 9d8471b9..00000000 --- a/critterai/src/nav-rcn/Detour/Source/DetourNavMeshBuilder.cpp +++ /dev/null @@ -1,775 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include -#include -#include -#include "DetourNavMesh.h" -#include "DetourCommon.h" -#include "DetourNavMeshBuilder.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" - -static unsigned short MESH_NULL_IDX = 0xffff; - - -struct BVItem -{ - unsigned short bmin[3]; - unsigned short bmax[3]; - int i; -}; - -static int compareItemX(const void* va, const void* vb) -{ - const BVItem* a = (const BVItem*)va; - const BVItem* b = (const BVItem*)vb; - if (a->bmin[0] < b->bmin[0]) - return -1; - if (a->bmin[0] > b->bmin[0]) - return 1; - return 0; -} - -static int compareItemY(const void* va, const void* vb) -{ - const BVItem* a = (const BVItem*)va; - const BVItem* b = (const BVItem*)vb; - if (a->bmin[1] < b->bmin[1]) - return -1; - if (a->bmin[1] > b->bmin[1]) - return 1; - return 0; -} - -static int compareItemZ(const void* va, const void* vb) -{ - const BVItem* a = (const BVItem*)va; - const BVItem* b = (const BVItem*)vb; - if (a->bmin[2] < b->bmin[2]) - return -1; - if (a->bmin[2] > b->bmin[2]) - return 1; - return 0; -} - -static void calcExtends(BVItem* items, const int /*nitems*/, const int imin, const int imax, - unsigned short* bmin, unsigned short* bmax) -{ - bmin[0] = items[imin].bmin[0]; - bmin[1] = items[imin].bmin[1]; - bmin[2] = items[imin].bmin[2]; - - bmax[0] = items[imin].bmax[0]; - bmax[1] = items[imin].bmax[1]; - bmax[2] = items[imin].bmax[2]; - - for (int i = imin+1; i < imax; ++i) - { - const BVItem& it = items[i]; - if (it.bmin[0] < bmin[0]) bmin[0] = it.bmin[0]; - if (it.bmin[1] < bmin[1]) bmin[1] = it.bmin[1]; - if (it.bmin[2] < bmin[2]) bmin[2] = it.bmin[2]; - - if (it.bmax[0] > bmax[0]) bmax[0] = it.bmax[0]; - if (it.bmax[1] > bmax[1]) bmax[1] = it.bmax[1]; - if (it.bmax[2] > bmax[2]) bmax[2] = it.bmax[2]; - } -} - -inline int longestAxis(unsigned short x, unsigned short y, unsigned short z) -{ - int axis = 0; - unsigned short maxVal = x; - if (y > maxVal) - { - axis = 1; - maxVal = y; - } - if (z > maxVal) - { - axis = 2; - maxVal = z; - } - return axis; -} - -static void subdivide(BVItem* items, int nitems, int imin, int imax, int& curNode, dtBVNode* nodes) -{ - int inum = imax - imin; - int icur = curNode; - - dtBVNode& node = nodes[curNode++]; - - if (inum == 1) - { - // Leaf - node.bmin[0] = items[imin].bmin[0]; - node.bmin[1] = items[imin].bmin[1]; - node.bmin[2] = items[imin].bmin[2]; - - node.bmax[0] = items[imin].bmax[0]; - node.bmax[1] = items[imin].bmax[1]; - node.bmax[2] = items[imin].bmax[2]; - - node.i = items[imin].i; - } - else - { - // Split - calcExtends(items, nitems, imin, imax, node.bmin, node.bmax); - - int axis = longestAxis(node.bmax[0] - node.bmin[0], - node.bmax[1] - node.bmin[1], - node.bmax[2] - node.bmin[2]); - - if (axis == 0) - { - // Sort along x-axis - qsort(items+imin, inum, sizeof(BVItem), compareItemX); - } - else if (axis == 1) - { - // Sort along y-axis - qsort(items+imin, inum, sizeof(BVItem), compareItemY); - } - else - { - // Sort along z-axis - qsort(items+imin, inum, sizeof(BVItem), compareItemZ); - } - - int isplit = imin+inum/2; - - // Left - subdivide(items, nitems, imin, isplit, curNode, nodes); - // Right - subdivide(items, nitems, isplit, imax, curNode, nodes); - - int iescape = curNode - icur; - // Negative index means escape. - node.i = -iescape; - } -} - -static int createBVTree(const unsigned short* verts, const int /*nverts*/, - const unsigned short* polys, const int npolys, const int nvp, - const float cs, const float ch, - const int /*nnodes*/, dtBVNode* nodes) -{ - // Build tree - BVItem* items = (BVItem*)dtAlloc(sizeof(BVItem)*npolys, DT_ALLOC_TEMP); - for (int i = 0; i < npolys; i++) - { - BVItem& it = items[i]; - it.i = i; - // Calc polygon bounds. - const unsigned short* p = &polys[i*nvp*2]; - it.bmin[0] = it.bmax[0] = verts[p[0]*3+0]; - it.bmin[1] = it.bmax[1] = verts[p[0]*3+1]; - it.bmin[2] = it.bmax[2] = verts[p[0]*3+2]; - - for (int j = 1; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - unsigned short x = verts[p[j]*3+0]; - unsigned short y = verts[p[j]*3+1]; - unsigned short z = verts[p[j]*3+2]; - - if (x < it.bmin[0]) it.bmin[0] = x; - if (y < it.bmin[1]) it.bmin[1] = y; - if (z < it.bmin[2]) it.bmin[2] = z; - - if (x > it.bmax[0]) it.bmax[0] = x; - if (y > it.bmax[1]) it.bmax[1] = y; - if (z > it.bmax[2]) it.bmax[2] = z; - } - // Remap y - it.bmin[1] = (unsigned short)floorf((float)it.bmin[1]*ch/cs); - it.bmax[1] = (unsigned short)ceilf((float)it.bmax[1]*ch/cs); - } - - int curNode = 0; - subdivide(items, npolys, 0, npolys, curNode, nodes); - - dtFree(items); - - return curNode; -} - -static unsigned char classifyOffMeshPoint(const float* pt, const float* bmin, const float* bmax) -{ - static const unsigned char XP = 1<<0; - static const unsigned char ZP = 1<<1; - static const unsigned char XM = 1<<2; - static const unsigned char ZM = 1<<3; - - unsigned char outcode = 0; - outcode |= (pt[0] >= bmax[0]) ? XP : 0; - outcode |= (pt[2] >= bmax[2]) ? ZP : 0; - outcode |= (pt[0] < bmin[0]) ? XM : 0; - outcode |= (pt[2] < bmin[2]) ? ZM : 0; - - switch (outcode) - { - case XP: return 0; - case XP|ZP: return 1; - case ZP: return 2; - case XM|ZP: return 3; - case XM: return 4; - case XM|ZM: return 5; - case ZM: return 6; - case XP|ZM: return 7; - }; - - return 0xff; -} - -// TODO: Better error handling. - -/// @par -/// -/// The output data array is allocated using the detour allocator (dtAlloc()). The method -/// used to free the memory will be determined by how the tile is added to the navigation -/// mesh. -/// -/// @see dtNavMesh, dtNavMesh::addTile() -bool dtCreateNavMeshData(dtNavMeshCreateParams* params, unsigned char** outData, int* outDataSize) -{ - if (params->nvp > DT_VERTS_PER_POLYGON) - return false; - if (params->vertCount >= 0xffff) - return false; - if (!params->vertCount || !params->verts) - return false; - if (!params->polyCount || !params->polys) - return false; - - const int nvp = params->nvp; - - // Classify off-mesh connection points. We store only the connections - // whose start point is inside the tile. - unsigned char* offMeshConClass = 0; - int storedOffMeshConCount = 0; - int offMeshConLinkCount = 0; - - if (params->offMeshConCount > 0) - { - offMeshConClass = (unsigned char*)dtAlloc(sizeof(unsigned char)*params->offMeshConCount*2, DT_ALLOC_TEMP); - if (!offMeshConClass) - return false; - - // Find tight heigh bounds, used for culling out off-mesh start locations. - float hmin = FLT_MAX; - float hmax = -FLT_MAX; - - if (params->detailVerts && params->detailVertsCount) - { - for (int i = 0; i < params->detailVertsCount; ++i) - { - const float h = params->detailVerts[i*3+1]; - hmin = dtMin(hmin,h); - hmax = dtMax(hmax,h); - } - } - else - { - for (int i = 0; i < params->vertCount; ++i) - { - const unsigned short* iv = ¶ms->verts[i*3]; - const float h = params->bmin[1] + iv[1] * params->ch; - hmin = dtMin(hmin,h); - hmax = dtMax(hmax,h); - } - } - hmin -= params->walkableClimb; - hmax += params->walkableClimb; - float bmin[3], bmax[3]; - dtVcopy(bmin, params->bmin); - dtVcopy(bmax, params->bmax); - bmin[1] = hmin; - bmax[1] = hmax; - - for (int i = 0; i < params->offMeshConCount; ++i) - { - const float* p0 = ¶ms->offMeshConVerts[(i*2+0)*3]; - const float* p1 = ¶ms->offMeshConVerts[(i*2+1)*3]; - offMeshConClass[i*2+0] = classifyOffMeshPoint(p0, bmin, bmax); - offMeshConClass[i*2+1] = classifyOffMeshPoint(p1, bmin, bmax); - - // Zero out off-mesh start positions which are not even potentially touching the mesh. - if (offMeshConClass[i*2+0] == 0xff) - { - if (p0[1] < bmin[1] || p0[1] > bmax[1]) - offMeshConClass[i*2+0] = 0; - } - - // Cound how many links should be allocated for off-mesh connections. - if (offMeshConClass[i*2+0] == 0xff) - offMeshConLinkCount++; - if (offMeshConClass[i*2+1] == 0xff) - offMeshConLinkCount++; - - if (offMeshConClass[i*2+0] == 0xff) - storedOffMeshConCount++; - } - } - - // Off-mesh connectionss are stored as polygons, adjust values. - const int totPolyCount = params->polyCount + storedOffMeshConCount; - const int totVertCount = params->vertCount + storedOffMeshConCount*2; - - // Find portal edges which are at tile borders. - int edgeCount = 0; - int portalCount = 0; - for (int i = 0; i < params->polyCount; ++i) - { - const unsigned short* p = ¶ms->polys[i*2*nvp]; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - edgeCount++; - - if (p[nvp+j] & 0x8000) - { - unsigned short dir = p[nvp+j] & 0xf; - if (dir != 0xf) - portalCount++; - } - } - } - - const int maxLinkCount = edgeCount + portalCount*2 + offMeshConLinkCount*2; - - // Find unique detail vertices. - int uniqueDetailVertCount = 0; - int detailTriCount = 0; - if (params->detailMeshes) - { - // Has detail mesh, count unique detail vertex count and use input detail tri count. - detailTriCount = params->detailTriCount; - for (int i = 0; i < params->polyCount; ++i) - { - const unsigned short* p = ¶ms->polys[i*nvp*2]; - int ndv = params->detailMeshes[i*4+1]; - int nv = 0; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - nv++; - } - ndv -= nv; - uniqueDetailVertCount += ndv; - } - } - else - { - // No input detail mesh, build detail mesh from nav polys. - uniqueDetailVertCount = 0; // No extra detail verts. - detailTriCount = 0; - for (int i = 0; i < params->polyCount; ++i) - { - const unsigned short* p = ¶ms->polys[i*nvp*2]; - int nv = 0; - for (int j = 0; j < nvp; ++j) - { - if (p[j] == MESH_NULL_IDX) break; - nv++; - } - detailTriCount += nv-2; - } - } - - // Calculate data size - const int headerSize = dtAlign4(sizeof(dtMeshHeader)); - const int vertsSize = dtAlign4(sizeof(float)*3*totVertCount); - const int polysSize = dtAlign4(sizeof(dtPoly)*totPolyCount); - const int linksSize = dtAlign4(sizeof(dtLink)*maxLinkCount); - const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*params->polyCount); - const int detailVertsSize = dtAlign4(sizeof(float)*3*uniqueDetailVertCount); - const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*detailTriCount); - const int bvTreeSize = params->buildBvTree ? dtAlign4(sizeof(dtBVNode)*params->polyCount*2) : 0; - const int offMeshConsSize = dtAlign4(sizeof(dtOffMeshConnection)*storedOffMeshConCount); - - const int dataSize = headerSize + vertsSize + polysSize + linksSize + - detailMeshesSize + detailVertsSize + detailTrisSize + - bvTreeSize + offMeshConsSize; - - unsigned char* data = (unsigned char*)dtAlloc(sizeof(unsigned char)*dataSize, DT_ALLOC_PERM); - if (!data) - { - dtFree(offMeshConClass); - return false; - } - memset(data, 0, dataSize); - - unsigned char* d = data; - dtMeshHeader* header = (dtMeshHeader*)d; d += headerSize; - float* navVerts = (float*)d; d += vertsSize; - dtPoly* navPolys = (dtPoly*)d; d += polysSize; - d += linksSize; - dtPolyDetail* navDMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - float* navDVerts = (float*)d; d += detailVertsSize; - unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize; - dtBVNode* navBvtree = (dtBVNode*)d; d += bvTreeSize; - dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshConsSize; - - - // Store header - header->magic = DT_NAVMESH_MAGIC; - header->version = DT_NAVMESH_VERSION; - header->x = params->tileX; - header->y = params->tileY; - header->layer = params->tileLayer; - header->userId = params->userId; - header->polyCount = totPolyCount; - header->vertCount = totVertCount; - header->maxLinkCount = maxLinkCount; - dtVcopy(header->bmin, params->bmin); - dtVcopy(header->bmax, params->bmax); - header->detailMeshCount = params->polyCount; - header->detailVertCount = uniqueDetailVertCount; - header->detailTriCount = detailTriCount; - header->bvQuantFactor = 1.0f / params->cs; - header->offMeshBase = params->polyCount; - header->walkableHeight = params->walkableHeight; - header->walkableRadius = params->walkableRadius; - header->walkableClimb = params->walkableClimb; - header->offMeshConCount = storedOffMeshConCount; - header->bvNodeCount = params->buildBvTree ? params->polyCount*2 : 0; - - const int offMeshVertsBase = params->vertCount; - const int offMeshPolyBase = params->polyCount; - - // Store vertices - // Mesh vertices - for (int i = 0; i < params->vertCount; ++i) - { - const unsigned short* iv = ¶ms->verts[i*3]; - float* v = &navVerts[i*3]; - v[0] = params->bmin[0] + iv[0] * params->cs; - v[1] = params->bmin[1] + iv[1] * params->ch; - v[2] = params->bmin[2] + iv[2] * params->cs; - } - // Off-mesh link vertices. - int n = 0; - for (int i = 0; i < params->offMeshConCount; ++i) - { - // Only store connections which start from this tile. - if (offMeshConClass[i*2+0] == 0xff) - { - const float* linkv = ¶ms->offMeshConVerts[i*2*3]; - float* v = &navVerts[(offMeshVertsBase + n*2)*3]; - dtVcopy(&v[0], &linkv[0]); - dtVcopy(&v[3], &linkv[3]); - n++; - } - } - - // Store polygons - // Mesh polys - const unsigned short* src = params->polys; - for (int i = 0; i < params->polyCount; ++i) - { - dtPoly* p = &navPolys[i]; - p->vertCount = 0; - p->flags = params->polyFlags[i]; - p->setArea(params->polyAreas[i]); - p->setType(DT_POLYTYPE_GROUND); - for (int j = 0; j < nvp; ++j) - { - if (src[j] == MESH_NULL_IDX) break; - p->verts[j] = src[j]; - if (src[nvp+j] & 0x8000) - { - // Border or portal edge. - unsigned short dir = src[nvp+j] & 0xf; - if (dir == 0xf) // Border - p->neis[j] = 0; - else if (dir == 0) // Portal x- - p->neis[j] = DT_EXT_LINK | 4; - else if (dir == 1) // Portal z+ - p->neis[j] = DT_EXT_LINK | 2; - else if (dir == 2) // Portal x+ - p->neis[j] = DT_EXT_LINK | 0; - else if (dir == 3) // Portal z- - p->neis[j] = DT_EXT_LINK | 6; - } - else - { - // Normal connection - p->neis[j] = src[nvp+j]+1; - } - - p->vertCount++; - } - src += nvp*2; - } - // Off-mesh connection vertices. - n = 0; - for (int i = 0; i < params->offMeshConCount; ++i) - { - // Only store connections which start from this tile. - if (offMeshConClass[i*2+0] == 0xff) - { - dtPoly* p = &navPolys[offMeshPolyBase+n]; - p->vertCount = 2; - p->verts[0] = (unsigned short)(offMeshVertsBase + n*2+0); - p->verts[1] = (unsigned short)(offMeshVertsBase + n*2+1); - p->flags = params->offMeshConFlags[i]; - p->setArea(params->offMeshConAreas[i]); - p->setType(DT_POLYTYPE_OFFMESH_CONNECTION); - n++; - } - } - - // Store detail meshes and vertices. - // The nav polygon vertices are stored as the first vertices on each mesh. - // We compress the mesh data by skipping them and using the navmesh coordinates. - if (params->detailMeshes) - { - unsigned short vbase = 0; - for (int i = 0; i < params->polyCount; ++i) - { - dtPolyDetail& dtl = navDMeshes[i]; - const int vb = (int)params->detailMeshes[i*4+0]; - const int ndv = (int)params->detailMeshes[i*4+1]; - const int nv = navPolys[i].vertCount; - dtl.vertBase = (unsigned int)vbase; - dtl.vertCount = (unsigned char)(ndv-nv); - dtl.triBase = (unsigned int)params->detailMeshes[i*4+2]; - dtl.triCount = (unsigned char)params->detailMeshes[i*4+3]; - // Copy vertices except the first 'nv' verts which are equal to nav poly verts. - if (ndv-nv) - { - memcpy(&navDVerts[vbase*3], ¶ms->detailVerts[(vb+nv)*3], sizeof(float)*3*(ndv-nv)); - vbase += (unsigned short)(ndv-nv); - } - } - // Store triangles. - memcpy(navDTris, params->detailTris, sizeof(unsigned char)*4*params->detailTriCount); - } - else - { - // Create dummy detail mesh by triangulating polys. - int tbase = 0; - for (int i = 0; i < params->polyCount; ++i) - { - dtPolyDetail& dtl = navDMeshes[i]; - const int nv = navPolys[i].vertCount; - dtl.vertBase = 0; - dtl.vertCount = 0; - dtl.triBase = (unsigned int)tbase; - dtl.triCount = (unsigned char)(nv-2); - // Triangulate polygon (local indices). - for (int j = 2; j < nv; ++j) - { - unsigned char* t = &navDTris[tbase*4]; - t[0] = 0; - t[1] = (unsigned char)(j-1); - t[2] = (unsigned char)j; - // Bit for each edge that belongs to poly boundary. - t[3] = (1<<2); - if (j == 2) t[3] |= (1<<0); - if (j == nv-1) t[3] |= (1<<4); - tbase++; - } - } - } - - // Store and create BVtree. - // TODO: take detail mesh into account! use byte per bbox extent? - if (params->buildBvTree) - { - createBVTree(params->verts, params->vertCount, params->polys, params->polyCount, - nvp, params->cs, params->ch, params->polyCount*2, navBvtree); - } - - // Store Off-Mesh connections. - n = 0; - for (int i = 0; i < params->offMeshConCount; ++i) - { - // Only store connections which start from this tile. - if (offMeshConClass[i*2+0] == 0xff) - { - dtOffMeshConnection* con = &offMeshCons[n]; - con->poly = (unsigned short)(offMeshPolyBase + n); - // Copy connection end-points. - const float* endPts = ¶ms->offMeshConVerts[i*2*3]; - dtVcopy(&con->pos[0], &endPts[0]); - dtVcopy(&con->pos[3], &endPts[3]); - con->rad = params->offMeshConRad[i]; - con->flags = params->offMeshConDir[i] ? DT_OFFMESH_CON_BIDIR : 0; - con->side = offMeshConClass[i*2+1]; - if (params->offMeshConUserID) - con->userId = params->offMeshConUserID[i]; - n++; - } - } - - dtFree(offMeshConClass); - - *outData = data; - *outDataSize = dataSize; - - return true; -} - -bool dtNavMeshHeaderSwapEndian(unsigned char* data, const int /*dataSize*/) -{ - dtMeshHeader* header = (dtMeshHeader*)data; - - int swappedMagic = DT_NAVMESH_MAGIC; - int swappedVersion = DT_NAVMESH_VERSION; - dtSwapEndian(&swappedMagic); - dtSwapEndian(&swappedVersion); - - if ((header->magic != DT_NAVMESH_MAGIC || header->version != DT_NAVMESH_VERSION) && - (header->magic != swappedMagic || header->version != swappedVersion)) - { - return false; - } - - dtSwapEndian(&header->magic); - dtSwapEndian(&header->version); - dtSwapEndian(&header->x); - dtSwapEndian(&header->y); - dtSwapEndian(&header->layer); - dtSwapEndian(&header->userId); - dtSwapEndian(&header->polyCount); - dtSwapEndian(&header->vertCount); - dtSwapEndian(&header->maxLinkCount); - dtSwapEndian(&header->detailMeshCount); - dtSwapEndian(&header->detailVertCount); - dtSwapEndian(&header->detailTriCount); - dtSwapEndian(&header->bvNodeCount); - dtSwapEndian(&header->offMeshConCount); - dtSwapEndian(&header->offMeshBase); - dtSwapEndian(&header->walkableHeight); - dtSwapEndian(&header->walkableRadius); - dtSwapEndian(&header->walkableClimb); - dtSwapEndian(&header->bmin[0]); - dtSwapEndian(&header->bmin[1]); - dtSwapEndian(&header->bmin[2]); - dtSwapEndian(&header->bmax[0]); - dtSwapEndian(&header->bmax[1]); - dtSwapEndian(&header->bmax[2]); - dtSwapEndian(&header->bvQuantFactor); - - // Freelist index and pointers are updated when tile is added, no need to swap. - - return true; -} - -/// @par -/// -/// @warning This function assumes that the header is in the correct endianess already. -/// Call #dtNavMeshHeaderSwapEndian() first on the data if the data is expected to be in wrong endianess -/// to start with. Call #dtNavMeshHeaderSwapEndian() after the data has been swapped if converting from -/// native to foreign endianess. -bool dtNavMeshDataSwapEndian(unsigned char* data, const int /*dataSize*/) -{ - // Make sure the data is in right format. - dtMeshHeader* header = (dtMeshHeader*)data; - if (header->magic != DT_NAVMESH_MAGIC) - return false; - if (header->version != DT_NAVMESH_VERSION) - return false; - - // Patch header pointers. - const int headerSize = dtAlign4(sizeof(dtMeshHeader)); - const int vertsSize = dtAlign4(sizeof(float)*3*header->vertCount); - const int polysSize = dtAlign4(sizeof(dtPoly)*header->polyCount); - const int linksSize = dtAlign4(sizeof(dtLink)*(header->maxLinkCount)); - const int detailMeshesSize = dtAlign4(sizeof(dtPolyDetail)*header->detailMeshCount); - const int detailVertsSize = dtAlign4(sizeof(float)*3*header->detailVertCount); - const int detailTrisSize = dtAlign4(sizeof(unsigned char)*4*header->detailTriCount); - const int bvtreeSize = dtAlign4(sizeof(dtBVNode)*header->bvNodeCount); - const int offMeshLinksSize = dtAlign4(sizeof(dtOffMeshConnection)*header->offMeshConCount); - - unsigned char* d = data + headerSize; - float* verts = (float*)d; d += vertsSize; - dtPoly* polys = (dtPoly*)d; d += polysSize; - /*dtLink* links = (dtLink*)d;*/ d += linksSize; - dtPolyDetail* detailMeshes = (dtPolyDetail*)d; d += detailMeshesSize; - float* detailVerts = (float*)d; d += detailVertsSize; - /*unsigned char* detailTris = (unsigned char*)d;*/ d += detailTrisSize; - dtBVNode* bvTree = (dtBVNode*)d; d += bvtreeSize; - dtOffMeshConnection* offMeshCons = (dtOffMeshConnection*)d; d += offMeshLinksSize; - - // Vertices - for (int i = 0; i < header->vertCount*3; ++i) - { - dtSwapEndian(&verts[i]); - } - - // Polys - for (int i = 0; i < header->polyCount; ++i) - { - dtPoly* p = &polys[i]; - // poly->firstLink is update when tile is added, no need to swap. - for (int j = 0; j < DT_VERTS_PER_POLYGON; ++j) - { - dtSwapEndian(&p->verts[j]); - dtSwapEndian(&p->neis[j]); - } - dtSwapEndian(&p->flags); - } - - // Links are rebuild when tile is added, no need to swap. - - // Detail meshes - for (int i = 0; i < header->detailMeshCount; ++i) - { - dtPolyDetail* pd = &detailMeshes[i]; - dtSwapEndian(&pd->vertBase); - dtSwapEndian(&pd->triBase); - } - - // Detail verts - for (int i = 0; i < header->detailVertCount*3; ++i) - { - dtSwapEndian(&detailVerts[i]); - } - - // BV-tree - for (int i = 0; i < header->bvNodeCount; ++i) - { - dtBVNode* node = &bvTree[i]; - for (int j = 0; j < 3; ++j) - { - dtSwapEndian(&node->bmin[j]); - dtSwapEndian(&node->bmax[j]); - } - dtSwapEndian(&node->i); - } - - // Off-mesh Connections. - for (int i = 0; i < header->offMeshConCount; ++i) - { - dtOffMeshConnection* con = &offMeshCons[i]; - for (int j = 0; j < 6; ++j) - dtSwapEndian(&con->pos[j]); - dtSwapEndian(&con->rad); - dtSwapEndian(&con->poly); - } - - return true; -} diff --git a/critterai/src/nav-rcn/Detour/Source/DetourNavMeshQuery.cpp b/critterai/src/nav-rcn/Detour/Source/DetourNavMeshQuery.cpp deleted file mode 100644 index 8b00fe5f..00000000 --- a/critterai/src/nav-rcn/Detour/Source/DetourNavMeshQuery.cpp +++ /dev/null @@ -1,3374 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include -#include -#include -#include "DetourNavMeshQuery.h" -#include "DetourNavMesh.h" -#include "DetourNode.h" -#include "DetourCommon.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include - -/// @class dtQueryFilter -/// -/// The Default Implementation -/// -/// At construction: All area costs default to 1.0. All flags are included -/// and none are excluded. -/// -/// If a polygon has both an include and an exclude flag, it will be excluded. -/// -/// The way filtering works, a navigation mesh polygon must have at least one flag -/// set to ever be considered by a query. So a polygon with no flags will never -/// be considered. -/// -/// Setting the include flags to 0 will result in all polygons being excluded. -/// -/// Custom Implementations -/// -/// DT_VIRTUAL_QUERYFILTER must be defined in order to extend this class. -/// -/// Implement a custom query filter by overriding the virtual passFilter() -/// and getCost() functions. If this is done, both functions should be as -/// fast as possible. Use cached local copies of data rather than accessing -/// your own objects where possible. -/// -/// Custom implementations do not need to adhere to the flags or cost logic -/// used by the default implementation. -/// -/// In order for A* searches to work properly, the cost should be proportional to -/// the travel distance. Implementing a cost modifier less than 1.0 is likely -/// to lead to problems during pathfinding. -/// -/// @see dtNavMeshQuery - -dtQueryFilter::dtQueryFilter() : - m_includeFlags(0xffff), - m_excludeFlags(0) -{ - for (int i = 0; i < DT_MAX_AREAS; ++i) - m_areaCost[i] = 1.0f; -} - -#ifdef DT_VIRTUAL_QUERYFILTER -bool dtQueryFilter::passFilter(const dtPolyRef /*ref*/, - const dtMeshTile* /*tile*/, - const dtPoly* poly) const -{ - return (poly->flags & m_includeFlags) != 0 && (poly->flags & m_excludeFlags) == 0; -} - -float dtQueryFilter::getCost(const float* pa, const float* pb, - const dtPolyRef /*prevRef*/, const dtMeshTile* /*prevTile*/, const dtPoly* /*prevPoly*/, - const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly, - const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const -{ - return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()]; -} -#else -inline bool dtQueryFilter::passFilter(const dtPolyRef /*ref*/, - const dtMeshTile* /*tile*/, - const dtPoly* poly) const -{ - return (poly->flags & m_includeFlags) != 0 && (poly->flags & m_excludeFlags) == 0; -} - -inline float dtQueryFilter::getCost(const float* pa, const float* pb, - const dtPolyRef /*prevRef*/, const dtMeshTile* /*prevTile*/, const dtPoly* /*prevPoly*/, - const dtPolyRef /*curRef*/, const dtMeshTile* /*curTile*/, const dtPoly* curPoly, - const dtPolyRef /*nextRef*/, const dtMeshTile* /*nextTile*/, const dtPoly* /*nextPoly*/) const -{ - return dtVdist(pa, pb) * m_areaCost[curPoly->getArea()]; -} -#endif - -static const float H_SCALE = 0.999f; // Search heuristic scale. - - -dtNavMeshQuery* dtAllocNavMeshQuery() -{ - void* mem = dtAlloc(sizeof(dtNavMeshQuery), DT_ALLOC_PERM); - if (!mem) return 0; - return new(mem) dtNavMeshQuery; -} - -void dtFreeNavMeshQuery(dtNavMeshQuery* navmesh) -{ - if (!navmesh) return; - navmesh->~dtNavMeshQuery(); - dtFree(navmesh); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -/// @class dtNavMeshQuery -/// -/// For methods that support undersized buffers, if the buffer is too small -/// to hold the entire result set the return status of the method will include -/// the #DT_BUFFER_TOO_SMALL flag. -/// -/// Constant member functions can be used by multiple clients without side -/// effects. (E.g. No change to the closed list. No impact on an in-progress -/// sliced path query. Etc.) -/// -/// Walls and portals: A @e wall is a polygon segment that is -/// considered impassable. A @e portal is a passable segment between polygons. -/// A portal may be treated as a wall based on the dtQueryFilter used for a query. -/// -/// @see dtNavMesh, dtQueryFilter, #dtAllocNavMeshQuery(), #dtAllocNavMeshQuery() - -dtNavMeshQuery::dtNavMeshQuery() : - m_nav(0), - m_tinyNodePool(0), - m_nodePool(0), - m_openList(0) -{ - memset(&m_query, 0, sizeof(dtQueryData)); -} - -dtNavMeshQuery::~dtNavMeshQuery() -{ - if (m_tinyNodePool) - m_tinyNodePool->~dtNodePool(); - if (m_nodePool) - m_nodePool->~dtNodePool(); - if (m_openList) - m_openList->~dtNodeQueue(); - dtFree(m_tinyNodePool); - dtFree(m_nodePool); - dtFree(m_openList); -} - -/// @par -/// -/// Must be the first function called after construction, before other -/// functions are used. -/// -/// This function can be used multiple times. -dtStatus dtNavMeshQuery::init(const dtNavMesh* nav, const int maxNodes) -{ - m_nav = nav; - - if (!m_nodePool || m_nodePool->getMaxNodes() < maxNodes) - { - if (m_nodePool) - { - m_nodePool->~dtNodePool(); - dtFree(m_nodePool); - m_nodePool = 0; - } - m_nodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(maxNodes, dtNextPow2(maxNodes/4)); - if (!m_nodePool) - return DT_FAILURE | DT_OUT_OF_MEMORY; - } - else - { - m_nodePool->clear(); - } - - if (!m_tinyNodePool) - { - m_tinyNodePool = new (dtAlloc(sizeof(dtNodePool), DT_ALLOC_PERM)) dtNodePool(64, 32); - if (!m_tinyNodePool) - return DT_FAILURE | DT_OUT_OF_MEMORY; - } - else - { - m_tinyNodePool->clear(); - } - - // TODO: check the open list size too. - if (!m_openList || m_openList->getCapacity() < maxNodes) - { - if (m_openList) - { - m_openList->~dtNodeQueue(); - dtFree(m_openList); - m_openList = 0; - } - m_openList = new (dtAlloc(sizeof(dtNodeQueue), DT_ALLOC_PERM)) dtNodeQueue(maxNodes); - if (!m_openList) - return DT_FAILURE | DT_OUT_OF_MEMORY; - } - else - { - m_openList->clear(); - } - - return DT_SUCCESS; -} - -dtStatus dtNavMeshQuery::findRandomPoint(const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const -{ - dtAssert(m_nav); - - // Randomly pick one tile. Assume that all tiles cover roughly the same area. - const dtMeshTile* tile = 0; - float tsum = 0.0f; - for (int i = 0; i < m_nav->getMaxTiles(); i++) - { - const dtMeshTile* t = m_nav->getTile(i); - if (!t || !t->header) continue; - - // Choose random tile using reservoi sampling. - const float area = 1.0f; // Could be tile area too. - tsum += area; - const float u = frand(); - if (u*tsum <= area) - tile = t; - } - if (!tile) - return DT_FAILURE; - - // Randomly pick one polygon weighted by polygon area. - const dtPoly* poly = 0; - dtPolyRef polyRef = 0; - const dtPolyRef base = m_nav->getPolyRefBase(tile); - - float areaSum = 0.0f; - for (int i = 0; i < tile->header->polyCount; ++i) - { - const dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() != DT_POLYTYPE_GROUND) - continue; - // Must pass filter - const dtPolyRef ref = base | (dtPolyRef)i; - if (!filter->passFilter(ref, tile, p)) - continue; - - // Calc area of the polygon. - float polyArea = 0.0f; - for (int j = 2; j < p->vertCount; ++j) - { - const float* va = &tile->verts[p->verts[0]*3]; - const float* vb = &tile->verts[p->verts[j-1]*3]; - const float* vc = &tile->verts[p->verts[j]*3]; - polyArea += dtTriArea2D(va,vb,vc); - } - - // Choose random polygon weighted by area, using reservoi sampling. - areaSum += polyArea; - const float u = frand(); - if (u*areaSum <= polyArea) - { - poly = p; - polyRef = ref; - } - } - - if (!poly) - return DT_FAILURE; - - // Randomly pick point on polygon. - const float* v = &tile->verts[poly->verts[0]*3]; - float verts[3*DT_VERTS_PER_POLYGON]; - float areas[DT_VERTS_PER_POLYGON]; - dtVcopy(&verts[0*3],v); - for (int j = 1; j < poly->vertCount; ++j) - { - v = &tile->verts[poly->verts[j]*3]; - dtVcopy(&verts[j*3],v); - } - - const float s = frand(); - const float t = frand(); - - float pt[3]; - dtRandomPointInConvexPoly(verts, poly->vertCount, areas, s, t, pt); - - float h = 0.0f; - dtStatus status = getPolyHeight(polyRef, pt, &h); - if (dtStatusFailed(status)) - return status; - pt[1] = h; - - dtVcopy(randomPt, pt); - *randomRef = polyRef; - - return DT_SUCCESS; -} - -dtStatus dtNavMeshQuery::findRandomPointAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, float (*frand)(), - dtPolyRef* randomRef, float* randomPt) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - const dtMeshTile* startTile = 0; - const dtPoly* startPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(startRef, &startTile, &startPoly); - if (!filter->passFilter(startRef, startTile, startPoly)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtStatus status = DT_SUCCESS; - - const float radiusSqr = dtSqr(radius); - float areaSum = 0.0f; - - const dtMeshTile* randomTile = 0; - const dtPoly* randomPoly = 0; - dtPolyRef randomPolyRef = 0; - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Place random locations on on ground. - if (bestPoly->getType() == DT_POLYTYPE_GROUND) - { - // Calc area of the polygon. - float polyArea = 0.0f; - for (int j = 2; j < bestPoly->vertCount; ++j) - { - const float* va = &bestTile->verts[bestPoly->verts[0]*3]; - const float* vb = &bestTile->verts[bestPoly->verts[j-1]*3]; - const float* vc = &bestTile->verts[bestPoly->verts[j]*3]; - polyArea += dtTriArea2D(va,vb,vc); - } - // Choose random polygon weighted by area, using reservoi sampling. - areaSum += polyArea; - const float u = frand(); - if (u*areaSum <= polyArea) - { - randomTile = bestTile; - randomPoly = bestPoly; - randomPolyRef = bestRef; - } - } - - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the circle is not touching the next polygon, skip it. - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - if (distSqr > radiusSqr) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - dtVlerp(neighbourNode->pos, va, vb, 0.5f); - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - neighbourNode->flags = DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - if (!randomPoly) - return DT_FAILURE; - - // Randomly pick point on polygon. - const float* v = &randomTile->verts[randomPoly->verts[0]*3]; - float verts[3*DT_VERTS_PER_POLYGON]; - float areas[DT_VERTS_PER_POLYGON]; - dtVcopy(&verts[0*3],v); - for (int j = 1; j < randomPoly->vertCount; ++j) - { - v = &randomTile->verts[randomPoly->verts[j]*3]; - dtVcopy(&verts[j*3],v); - } - - const float s = frand(); - const float t = frand(); - - float pt[3]; - dtRandomPointInConvexPoly(verts, randomPoly->vertCount, areas, s, t, pt); - - float h = 0.0f; - dtStatus stat = getPolyHeight(randomPolyRef, pt, &h); - if (dtStatusFailed(status)) - return stat; - pt[1] = h; - - dtVcopy(randomPt, pt); - *randomRef = randomPolyRef; - - return DT_SUCCESS; -} - - -////////////////////////////////////////////////////////////////////////////////////////// - -/// @par -/// -/// Uses the detail polygons to find the surface height. (Most accurate.) -/// -/// @p pos does not have to be within the bounds of the polygon or navigation mesh. -/// -/// See closestPointOnPolyBoundary() for a limited but faster option. -/// -dtStatus dtNavMeshQuery::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest) const -{ - dtAssert(m_nav); - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - if (!tile) - return DT_FAILURE | DT_INVALID_PARAM; - - closestPointOnPolyInTile(tile, poly, pos, closest); - - return DT_SUCCESS; -} - -void dtNavMeshQuery::closestPointOnPolyInTile(const dtMeshTile* tile, const dtPoly* poly, - const float* pos, float* closest) const -{ - // Off-mesh connections don't have detail polygons. - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - const float* v0 = &tile->verts[poly->verts[0]*3]; - const float* v1 = &tile->verts[poly->verts[1]*3]; - const float d0 = dtVdist(pos, v0); - const float d1 = dtVdist(pos, v1); - const float u = d0 / (d0+d1); - dtVlerp(closest, v0, v1, u); - return; - } - - const unsigned int ip = (unsigned int)(poly - tile->polys); - const dtPolyDetail* pd = &tile->detailMeshes[ip]; - - // Clamp point to be inside the polygon. - float verts[DT_VERTS_PER_POLYGON*3]; - float edged[DT_VERTS_PER_POLYGON]; - float edget[DT_VERTS_PER_POLYGON]; - const int nv = poly->vertCount; - for (int i = 0; i < nv; ++i) - dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]); - - dtVcopy(closest, pos); - if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) - { - // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) - { - if (edged[i] < dmin) - { - dmin = edged[i]; - imin = i; - } - } - const float* va = &verts[imin*3]; - const float* vb = &verts[((imin+1)%nv)*3]; - dtVlerp(closest, va, vb, edget[imin]); - } - - // Find height at the location. - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - float h; - if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) - { - closest[1] = h; - break; - } - } - -/* float closestDistSqr = FLT_MAX; - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - - float pt[3]; - dtClosestPtPointTriangle(pt, pos, v[0], v[1], v[2]); - float d = dtVdistSqr(pos, pt); - - if (d < closestDistSqr) - { - dtVcopy(closest, pt); - closestDistSqr = d; - } - }*/ -} - -/// @par -/// -/// Much faster than closestPointOnPoly(). -/// -/// If the provided position lies within the polygon's xz-bounds (above or below), -/// then @p pos and @p closest will be equal. -/// -/// The height of @p closest will be the polygon boundary. The height detail is not used. -/// -/// @p pos does not have to be within the bounds of the polybon or the navigation mesh. -/// -dtStatus dtNavMeshQuery::closestPointOnPolyBoundary(dtPolyRef ref, const float* pos, float* closest) const -{ - dtAssert(m_nav); - - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - - // Collect vertices. - float verts[DT_VERTS_PER_POLYGON*3]; - float edged[DT_VERTS_PER_POLYGON]; - float edget[DT_VERTS_PER_POLYGON]; - int nv = 0; - for (int i = 0; i < (int)poly->vertCount; ++i) - { - dtVcopy(&verts[nv*3], &tile->verts[poly->verts[i]*3]); - nv++; - } - - bool inside = dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget); - if (inside) - { - // Point is inside the polygon, return the point. - dtVcopy(closest, pos); - } - else - { - // Point is outside the polygon, dtClamp to nearest edge. - float dmin = FLT_MAX; - int imin = -1; - for (int i = 0; i < nv; ++i) - { - if (edged[i] < dmin) - { - dmin = edged[i]; - imin = i; - } - } - const float* va = &verts[imin*3]; - const float* vb = &verts[((imin+1)%nv)*3]; - dtVlerp(closest, va, vb, edget[imin]); - } - - return DT_SUCCESS; -} - -/// @par -/// -/// Will return #DT_FAILURE if the provided position is outside the xz-bounds -/// of the polygon. -/// -dtStatus dtNavMeshQuery::getPolyHeight(dtPolyRef ref, const float* pos, float* height) const -{ - dtAssert(m_nav); - - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - - if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - const float* v0 = &tile->verts[poly->verts[0]*3]; - const float* v1 = &tile->verts[poly->verts[1]*3]; - const float d0 = dtVdist(pos, v0); - const float d1 = dtVdist(pos, v1); - const float u = d0 / (d0+d1); - if (height) - *height = v0[1] + (v1[1] - v0[1]) * u; - return DT_SUCCESS; - } - else - { - const unsigned int ip = (unsigned int)(poly - tile->polys); - const dtPolyDetail* pd = &tile->detailMeshes[ip]; - for (int j = 0; j < pd->triCount; ++j) - { - const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; - const float* v[3]; - for (int k = 0; k < 3; ++k) - { - if (t[k] < poly->vertCount) - v[k] = &tile->verts[poly->verts[t[k]]*3]; - else - v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; - } - float h; - if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) - { - if (height) - *height = h; - return DT_SUCCESS; - } - } - } - - return DT_FAILURE | DT_INVALID_PARAM; -} - -/// @par -/// -/// @note If the search box does not intersect any polygons the search will -/// return #DT_SUCCESS, but @p nearestRef will be zero. So if in doubt, check -/// @p nearestRef before using @p nearestPt. -/// -/// @warning This function is not suitable for large area searches. If the search -/// extents overlaps more than 128 polygons it may return an invalid result. -/// -dtStatus dtNavMeshQuery::findNearestPoly(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* nearestRef, float* nearestPt) const -{ - dtAssert(m_nav); - - *nearestRef = 0; - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = 0; - if (dtStatusFailed(queryPolygons(center, extents, filter, polys, &polyCount, 128))) - return DT_FAILURE | DT_INVALID_PARAM; - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) - { - dtPolyRef ref = polys[i]; - float closestPtPoly[3]; - closestPointOnPoly(ref, center, closestPtPoly); - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) - { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; - } - } - - if (nearestRef) - *nearestRef = nearest; - - return DT_SUCCESS; -} - -dtPolyRef dtNavMeshQuery::findNearestPolyInTile(const dtMeshTile* tile, const float* center, const float* extents, - const dtQueryFilter* filter, float* nearestPt) const -{ - dtAssert(m_nav); - - float bmin[3], bmax[3]; - dtVsub(bmin, center, extents); - dtVadd(bmax, center, extents); - - // Get nearby polygons from proximity grid. - dtPolyRef polys[128]; - int polyCount = queryPolygonsInTile(tile, bmin, bmax, filter, polys, 128); - - // Find nearest polygon amongst the nearby polygons. - dtPolyRef nearest = 0; - float nearestDistanceSqr = FLT_MAX; - for (int i = 0; i < polyCount; ++i) - { - dtPolyRef ref = polys[i]; - const dtPoly* poly = &tile->polys[m_nav->decodePolyIdPoly(ref)]; - float closestPtPoly[3]; - closestPointOnPolyInTile(tile, poly, center, closestPtPoly); - - float d = dtVdistSqr(center, closestPtPoly); - if (d < nearestDistanceSqr) - { - if (nearestPt) - dtVcopy(nearestPt, closestPtPoly); - nearestDistanceSqr = d; - nearest = ref; - } - } - - return nearest; -} - -int dtNavMeshQuery::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, - const dtQueryFilter* filter, - dtPolyRef* polys, const int maxPolys) const -{ - dtAssert(m_nav); - - if (tile->bvTree) - { - const dtBVNode* node = &tile->bvTree[0]; - const dtBVNode* end = &tile->bvTree[tile->header->bvNodeCount]; - const float* tbmin = tile->header->bmin; - const float* tbmax = tile->header->bmax; - const float qfac = tile->header->bvQuantFactor; - - // Calculate quantized box - unsigned short bmin[3], bmax[3]; - // dtClamp query box to world box. - float minx = dtClamp(qmin[0], tbmin[0], tbmax[0]) - tbmin[0]; - float miny = dtClamp(qmin[1], tbmin[1], tbmax[1]) - tbmin[1]; - float minz = dtClamp(qmin[2], tbmin[2], tbmax[2]) - tbmin[2]; - float maxx = dtClamp(qmax[0], tbmin[0], tbmax[0]) - tbmin[0]; - float maxy = dtClamp(qmax[1], tbmin[1], tbmax[1]) - tbmin[1]; - float maxz = dtClamp(qmax[2], tbmin[2], tbmax[2]) - tbmin[2]; - // Quantize - bmin[0] = (unsigned short)(qfac * minx) & 0xfffe; - bmin[1] = (unsigned short)(qfac * miny) & 0xfffe; - bmin[2] = (unsigned short)(qfac * minz) & 0xfffe; - bmax[0] = (unsigned short)(qfac * maxx + 1) | 1; - bmax[1] = (unsigned short)(qfac * maxy + 1) | 1; - bmax[2] = (unsigned short)(qfac * maxz + 1) | 1; - - // Traverse tree - const dtPolyRef base = m_nav->getPolyRefBase(tile); - int n = 0; - while (node < end) - { - const bool overlap = dtOverlapQuantBounds(bmin, bmax, node->bmin, node->bmax); - const bool isLeafNode = node->i >= 0; - - if (isLeafNode && overlap) - { - dtPolyRef ref = base | (dtPolyRef)node->i; - if (filter->passFilter(ref, tile, &tile->polys[node->i])) - { - if (n < maxPolys) - polys[n++] = ref; - } - } - - if (overlap || isLeafNode) - node++; - else - { - const int escapeIndex = -node->i; - node += escapeIndex; - } - } - - return n; - } - else - { - float bmin[3], bmax[3]; - int n = 0; - const dtPolyRef base = m_nav->getPolyRefBase(tile); - for (int i = 0; i < tile->header->polyCount; ++i) - { - const dtPoly* p = &tile->polys[i]; - // Do not return off-mesh connection polygons. - if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - // Must pass filter - const dtPolyRef ref = base | (dtPolyRef)i; - if (!filter->passFilter(ref, tile, p)) - continue; - // Calc polygon bounds. - const float* v = &tile->verts[p->verts[0]*3]; - dtVcopy(bmin, v); - dtVcopy(bmax, v); - for (int j = 1; j < p->vertCount; ++j) - { - v = &tile->verts[p->verts[j]*3]; - dtVmin(bmin, v); - dtVmax(bmax, v); - } - if (dtOverlapBounds(qmin,qmax, bmin,bmax)) - { - if (n < maxPolys) - polys[n++] = ref; - } - } - return n; - } -} - -/// @par -/// -/// If no polygons are found, the function will return #DT_SUCCESS with a -/// @p polyCount of zero. -/// -/// If @p polys is too small to hold the entire result set, then the array will -/// be filled to capacity. The method of choosing which polygons from the -/// full set are included in the partial result set is undefined. -/// -dtStatus dtNavMeshQuery::queryPolygons(const float* center, const float* extents, - const dtQueryFilter* filter, - dtPolyRef* polys, int* polyCount, const int maxPolys) const -{ - dtAssert(m_nav); - - float bmin[3], bmax[3]; - dtVsub(bmin, center, extents); - dtVadd(bmax, center, extents); - - // Find tiles the query touches. - int minx, miny, maxx, maxy; - m_nav->calcTileLoc(bmin, &minx, &miny); - m_nav->calcTileLoc(bmax, &maxx, &maxy); - - static const int MAX_NEIS = 32; - const dtMeshTile* neis[MAX_NEIS]; - - int n = 0; - for (int y = miny; y <= maxy; ++y) - { - for (int x = minx; x <= maxx; ++x) - { - const int nneis = m_nav->getTilesAt(x,y,neis,MAX_NEIS); - for (int j = 0; j < nneis; ++j) - { - n += queryPolygonsInTile(neis[j], bmin, bmax, filter, polys+n, maxPolys-n); - if (n >= maxPolys) - { - *polyCount = n; - return DT_SUCCESS | DT_BUFFER_TOO_SMALL; - } - } - } - } - *polyCount = n; - - return DT_SUCCESS; -} - -/// @par -/// -/// If the end polygon cannot be reached through the navigation graph, -/// the last polygon in the path will be the nearest the end polygon. -/// -/// If the path array is to small to hold the full result, it will be filled as -/// far as possible from the start polygon toward the end polygon. -/// -/// The start and end positions are used to calculate traversal costs. -/// (The y-values impact the result.) -/// -dtStatus dtNavMeshQuery::findPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter, - dtPolyRef* path, int* pathCount, const int maxPath) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - *pathCount = 0; - - if (!startRef || !endRef) - return DT_FAILURE | DT_INVALID_PARAM; - - if (!maxPath) - return DT_FAILURE | DT_INVALID_PARAM; - - // Validate input - if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - if (startRef == endRef) - { - path[0] = startRef; - *pathCount = 1; - return DT_SUCCESS; - } - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, startPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = dtVdist(startPos, endPos) * H_SCALE; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtNode* lastBestNode = startNode; - float lastBestNodeCost = startNode->total; - - dtStatus status = DT_SUCCESS; - - while (!m_openList->empty()) - { - // Remove node from open list and put it in closed list. - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Reached the goal, stop searching. - if (bestNode->id == endRef) - { - lastBestNode = bestNode; - break; - } - - // Get current poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - dtPolyRef neighbourRef = bestTile->links[i].ref; - - // Skip invalid ids and do not expand back to where we came from. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Get neighbour poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - // If the node is visited the first time, calculate node position. - if (neighbourNode->flags == 0) - { - getEdgeMidPoint(bestRef, bestPoly, bestTile, - neighbourRef, neighbourPoly, neighbourTile, - neighbourNode->pos); - } - - // Calculate cost and heuristic. - float cost = 0; - float heuristic = 0; - - // Special case for last node. - if (neighbourRef == endRef) - { - // Cost - const float curCost = filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - const float endCost = filter->getCost(neighbourNode->pos, endPos, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly, - 0, 0, 0); - - cost = bestNode->cost + curCost + endCost; - heuristic = 0; - } - else - { - // Cost - const float curCost = filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - cost = bestNode->cost + curCost; - heuristic = dtVdist(neighbourNode->pos, endPos)*H_SCALE; - } - - const float total = cost + heuristic; - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - // The node is already visited and process, and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_CLOSED) && total >= neighbourNode->total) - continue; - - // Add or update the node. - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->cost = cost; - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - // Already in open, update node location. - m_openList->modify(neighbourNode); - } - else - { - // Put the node in open list. - neighbourNode->flags |= DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - - // Update nearest node to target so far. - if (heuristic < lastBestNodeCost) - { - lastBestNodeCost = heuristic; - lastBestNode = neighbourNode; - } - } - } - - if (lastBestNode->id != endRef) - status |= DT_PARTIAL_RESULT; - - // Reverse the path. - dtNode* prev = 0; - dtNode* node = lastBestNode; - do - { - dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); - node->pidx = m_nodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store path - node = prev; - int n = 0; - do - { - path[n++] = node->id; - if (n >= maxPath) - { - status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_nodePool->getNodeAtIdx(node->pidx); - } - while (node); - - *pathCount = n; - - return status; -} - -/// @par -/// -/// @warning Calling any non-slice methods before calling finalizeSlicedFindPath() -/// or finalizeSlicedFindPathPartial() may result in corrupted data! -/// -/// The @p filter pointer is stored and used for the duration of the sliced -/// path query. -/// -dtStatus dtNavMeshQuery::initSlicedFindPath(dtPolyRef startRef, dtPolyRef endRef, - const float* startPos, const float* endPos, - const dtQueryFilter* filter) -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - // Init path state. - memset(&m_query, 0, sizeof(dtQueryData)); - m_query.status = DT_FAILURE; - m_query.startRef = startRef; - m_query.endRef = endRef; - dtVcopy(m_query.startPos, startPos); - dtVcopy(m_query.endPos, endPos); - m_query.filter = filter; - - if (!startRef || !endRef) - return DT_FAILURE | DT_INVALID_PARAM; - - // Validate input - if (!m_nav->isValidPolyRef(startRef) || !m_nav->isValidPolyRef(endRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - if (startRef == endRef) - { - m_query.status = DT_SUCCESS; - return DT_SUCCESS; - } - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, startPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = dtVdist(startPos, endPos) * H_SCALE; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - m_query.status = DT_IN_PROGRESS; - m_query.lastBestNode = startNode; - m_query.lastBestNodeCost = startNode->total; - - return m_query.status; -} - -dtStatus dtNavMeshQuery::updateSlicedFindPath(const int maxIter, int* doneIters) -{ - if (!dtStatusInProgress(m_query.status)) - return m_query.status; - - // Make sure the request is still valid. - if (!m_nav->isValidPolyRef(m_query.startRef) || !m_nav->isValidPolyRef(m_query.endRef)) - { - m_query.status = DT_FAILURE; - return DT_FAILURE; - } - - int iter = 0; - while (iter < maxIter && !m_openList->empty()) - { - iter++; - - // Remove node from open list and put it in closed list. - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Reached the goal, stop searching. - if (bestNode->id == m_query.endRef) - { - m_query.lastBestNode = bestNode; - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - m_query.status = DT_SUCCESS | details; - if (doneIters) - *doneIters = iter; - return m_query.status; - } - - // Get current poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(bestRef, &bestTile, &bestPoly))) - { - // The polygon has disappeared during the sliced query, fail. - m_query.status = DT_FAILURE; - if (doneIters) - *doneIters = iter; - return m_query.status; - } - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - { - if (dtStatusFailed(m_nav->getTileAndPolyByRef(parentRef, &parentTile, &parentPoly))) - { - // The polygon has disappeared during the sliced query, fail. - m_query.status = DT_FAILURE; - if (doneIters) - *doneIters = iter; - return m_query.status; - } - } - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - dtPolyRef neighbourRef = bestTile->links[i].ref; - - // Skip invalid ids and do not expand back to where we came from. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Get neighbour poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - if (!m_query.filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - m_query.status |= DT_OUT_OF_NODES; - continue; - } - - // If the node is visited the first time, calculate node position. - if (neighbourNode->flags == 0) - { - getEdgeMidPoint(bestRef, bestPoly, bestTile, - neighbourRef, neighbourPoly, neighbourTile, - neighbourNode->pos); - } - - // Calculate cost and heuristic. - float cost = 0; - float heuristic = 0; - - // Special case for last node. - if (neighbourRef == m_query.endRef) - { - // Cost - const float curCost = m_query.filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - const float endCost = m_query.filter->getCost(neighbourNode->pos, m_query.endPos, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly, - 0, 0, 0); - - cost = bestNode->cost + curCost + endCost; - heuristic = 0; - } - else - { - // Cost - const float curCost = m_query.filter->getCost(bestNode->pos, neighbourNode->pos, - parentRef, parentTile, parentPoly, - bestRef, bestTile, bestPoly, - neighbourRef, neighbourTile, neighbourPoly); - cost = bestNode->cost + curCost; - heuristic = dtVdist(neighbourNode->pos, m_query.endPos)*H_SCALE; - } - - const float total = cost + heuristic; - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - // The node is already visited and process, and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_CLOSED) && total >= neighbourNode->total) - continue; - - // Add or update the node. - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->cost = cost; - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - // Already in open, update node location. - m_openList->modify(neighbourNode); - } - else - { - // Put the node in open list. - neighbourNode->flags |= DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - - // Update nearest node to target so far. - if (heuristic < m_query.lastBestNodeCost) - { - m_query.lastBestNodeCost = heuristic; - m_query.lastBestNode = neighbourNode; - } - } - } - - // Exhausted all nodes, but could not find path. - if (m_openList->empty()) - { - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - m_query.status = DT_SUCCESS | details; - } - - if (doneIters) - *doneIters = iter; - - return m_query.status; -} - -dtStatus dtNavMeshQuery::finalizeSlicedFindPath(dtPolyRef* path, int* pathCount, const int maxPath) -{ - *pathCount = 0; - - if (dtStatusFailed(m_query.status)) - { - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - return DT_FAILURE; - } - - int n = 0; - - if (m_query.startRef == m_query.endRef) - { - // Special case: the search starts and ends at same poly. - path[n++] = m_query.startRef; - } - else - { - // Reverse the path. - dtAssert(m_query.lastBestNode); - - if (m_query.lastBestNode->id != m_query.endRef) - m_query.status |= DT_PARTIAL_RESULT; - - dtNode* prev = 0; - dtNode* node = m_query.lastBestNode; - do - { - dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); - node->pidx = m_nodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store path - node = prev; - do - { - path[n++] = node->id; - if (n >= maxPath) - { - m_query.status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_nodePool->getNodeAtIdx(node->pidx); - } - while (node); - } - - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - - *pathCount = n; - - return DT_SUCCESS | details; -} - -dtStatus dtNavMeshQuery::finalizeSlicedFindPathPartial(const dtPolyRef* existing, const int existingSize, - dtPolyRef* path, int* pathCount, const int maxPath) -{ - *pathCount = 0; - - if (existingSize == 0) - { - return DT_FAILURE; - } - - if (dtStatusFailed(m_query.status)) - { - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - return DT_FAILURE; - } - - int n = 0; - - if (m_query.startRef == m_query.endRef) - { - // Special case: the search starts and ends at same poly. - path[n++] = m_query.startRef; - } - else - { - // Find furthest existing node that was visited. - dtNode* prev = 0; - dtNode* node = 0; - for (int i = existingSize-1; i >= 0; --i) - { - node = m_nodePool->findNode(existing[i]); - if (node) - break; - } - - if (!node) - { - m_query.status |= DT_PARTIAL_RESULT; - dtAssert(m_query.lastBestNode); - node = m_query.lastBestNode; - } - - // Reverse the path. - do - { - dtNode* next = m_nodePool->getNodeAtIdx(node->pidx); - node->pidx = m_nodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store path - node = prev; - do - { - path[n++] = node->id; - if (n >= maxPath) - { - m_query.status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_nodePool->getNodeAtIdx(node->pidx); - } - while (node); - } - - const dtStatus details = m_query.status & DT_STATUS_DETAIL_MASK; - - // Reset query. - memset(&m_query, 0, sizeof(dtQueryData)); - - *pathCount = n; - - return DT_SUCCESS | details; -} - - -dtStatus dtNavMeshQuery::appendVertex(const float* pos, const unsigned char flags, const dtPolyRef ref, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath) const -{ - if ((*straightPathCount) > 0 && dtVequal(&straightPath[((*straightPathCount)-1)*3], pos)) - { - // The vertices are equal, update flags and poly. - if (straightPathFlags) - straightPathFlags[(*straightPathCount)-1] = flags; - if (straightPathRefs) - straightPathRefs[(*straightPathCount)-1] = ref; - } - else - { - // Append new vertex. - dtVcopy(&straightPath[(*straightPathCount)*3], pos); - if (straightPathFlags) - straightPathFlags[(*straightPathCount)] = flags; - if (straightPathRefs) - straightPathRefs[(*straightPathCount)] = ref; - (*straightPathCount)++; - // If reached end of path or there is no space to append more vertices, return. - if (flags == DT_STRAIGHTPATH_END || (*straightPathCount) >= maxStraightPath) - { - return DT_SUCCESS | (((*straightPathCount) >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); - } - } - return DT_IN_PROGRESS; -} - -dtStatus dtNavMeshQuery::appendPortals(const int startIdx, const int endIdx, const float* endPos, const dtPolyRef* path, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath, const int options) const -{ - const float* startPos = &straightPath[(*straightPathCount-1)*3]; - // Append or update last vertex - dtStatus stat = 0; - for (int i = startIdx; i < endIdx; i++) - { - // Calculate portal - const dtPolyRef from = path[i]; - const dtMeshTile* fromTile = 0; - const dtPoly* fromPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - - const dtPolyRef to = path[i+1]; - const dtMeshTile* toTile = 0; - const dtPoly* toPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - - float left[3], right[3]; - if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right))) - break; - - if (options & DT_STRAIGHTPATH_AREA_CROSSINGS) - { - // Skip intersection if only area crossings are requested. - if (fromPoly->getArea() == toPoly->getArea()) - continue; - } - - // Append intersection - float s,t; - if (dtIntersectSegSeg2D(startPos, endPos, left, right, s, t)) - { - float pt[3]; - dtVlerp(pt, left,right, t); - - stat = appendVertex(pt, 0, path[i+1], - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; - } - } - return DT_IN_PROGRESS; -} - -/// @par -/// -/// This method peforms what is often called 'string pulling'. -/// -/// The start position is clamped to the first polygon in the path, and the -/// end position is clamped to the last. So the start and end positions should -/// normally be within or very near the first and last polygons respectively. -/// -/// The returned polygon references represent the reference id of the polygon -/// that is entered at the associated path position. The reference id associated -/// with the end point will always be zero. This allows, for example, matching -/// off-mesh link points to their representative polygons. -/// -/// If the provided result buffers are too small for the entire result set, -/// they will be filled as far as possible from the start toward the end -/// position. -/// -dtStatus dtNavMeshQuery::findStraightPath(const float* startPos, const float* endPos, - const dtPolyRef* path, const int pathSize, - float* straightPath, unsigned char* straightPathFlags, dtPolyRef* straightPathRefs, - int* straightPathCount, const int maxStraightPath, const int options) const -{ - dtAssert(m_nav); - - *straightPathCount = 0; - - if (!maxStraightPath) - return DT_FAILURE | DT_INVALID_PARAM; - - if (!path[0]) - return DT_FAILURE | DT_INVALID_PARAM; - - dtStatus stat = 0; - - // TODO: Should this be callers responsibility? - float closestStartPos[3]; - if (dtStatusFailed(closestPointOnPolyBoundary(path[0], startPos, closestStartPos))) - return DT_FAILURE | DT_INVALID_PARAM; - - float closestEndPos[3]; - if (dtStatusFailed(closestPointOnPolyBoundary(path[pathSize-1], endPos, closestEndPos))) - return DT_FAILURE | DT_INVALID_PARAM; - - // Add start point. - stat = appendVertex(closestStartPos, DT_STRAIGHTPATH_START, path[0], - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; - - if (pathSize > 1) - { - float portalApex[3], portalLeft[3], portalRight[3]; - dtVcopy(portalApex, closestStartPos); - dtVcopy(portalLeft, portalApex); - dtVcopy(portalRight, portalApex); - int apexIndex = 0; - int leftIndex = 0; - int rightIndex = 0; - - unsigned char leftPolyType = 0; - unsigned char rightPolyType = 0; - - dtPolyRef leftPolyRef = path[0]; - dtPolyRef rightPolyRef = path[0]; - - for (int i = 0; i < pathSize; ++i) - { - float left[3], right[3]; - unsigned char fromType, toType; - - if (i+1 < pathSize) - { - // Next portal. - if (dtStatusFailed(getPortalPoints(path[i], path[i+1], left, right, fromType, toType))) - { - // Failed to get portal points, in practice this means that path[i+1] is invalid polygon. - // Clamp the end point to path[i], and return the path so far. - - if (dtStatusFailed(closestPointOnPolyBoundary(path[i], endPos, closestEndPos))) - { - // This should only happen when the first polygon is invalid. - return DT_FAILURE | DT_INVALID_PARAM; - } - - // Apeend portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, i, closestEndPos, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - } - - stat = appendVertex(closestEndPos, 0, path[i], - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - - return DT_SUCCESS | DT_PARTIAL_RESULT | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); - } - - // If starting really close the portal, advance. - if (i == 0) - { - float t; - if (dtDistancePtSegSqr2D(portalApex, left, right, t) < dtSqr(0.001f)) - continue; - } - } - else - { - // End of the path. - dtVcopy(left, closestEndPos); - dtVcopy(right, closestEndPos); - - fromType = toType = DT_POLYTYPE_GROUND; - } - - // Right vertex. - if (dtTriArea2D(portalApex, portalRight, right) <= 0.0f) - { - if (dtVequal(portalApex, portalRight) || dtTriArea2D(portalApex, portalLeft, right) > 0.0f) - { - dtVcopy(portalRight, right); - rightPolyRef = (i+1 < pathSize) ? path[i+1] : 0; - rightPolyType = toType; - rightIndex = i; - } - else - { - // Append portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, leftIndex, portalLeft, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - if (stat != DT_IN_PROGRESS) - return stat; - } - - dtVcopy(portalApex, portalLeft); - apexIndex = leftIndex; - - unsigned char flags = 0; - if (!leftPolyRef) - flags = DT_STRAIGHTPATH_END; - else if (leftPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) - flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; - dtPolyRef ref = leftPolyRef; - - // Append or update vertex - stat = appendVertex(portalApex, flags, ref, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; - - dtVcopy(portalLeft, portalApex); - dtVcopy(portalRight, portalApex); - leftIndex = apexIndex; - rightIndex = apexIndex; - - // Restart - i = apexIndex; - - continue; - } - } - - // Left vertex. - if (dtTriArea2D(portalApex, portalLeft, left) >= 0.0f) - { - if (dtVequal(portalApex, portalLeft) || dtTriArea2D(portalApex, portalRight, left) < 0.0f) - { - dtVcopy(portalLeft, left); - leftPolyRef = (i+1 < pathSize) ? path[i+1] : 0; - leftPolyType = toType; - leftIndex = i; - } - else - { - // Append portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, rightIndex, portalRight, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - if (stat != DT_IN_PROGRESS) - return stat; - } - - dtVcopy(portalApex, portalRight); - apexIndex = rightIndex; - - unsigned char flags = 0; - if (!rightPolyRef) - flags = DT_STRAIGHTPATH_END; - else if (rightPolyType == DT_POLYTYPE_OFFMESH_CONNECTION) - flags = DT_STRAIGHTPATH_OFFMESH_CONNECTION; - dtPolyRef ref = rightPolyRef; - - // Append or update vertex - stat = appendVertex(portalApex, flags, ref, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - if (stat != DT_IN_PROGRESS) - return stat; - - dtVcopy(portalLeft, portalApex); - dtVcopy(portalRight, portalApex); - leftIndex = apexIndex; - rightIndex = apexIndex; - - // Restart - i = apexIndex; - - continue; - } - } - } - - // Append portals along the current straight path segment. - if (options & (DT_STRAIGHTPATH_AREA_CROSSINGS | DT_STRAIGHTPATH_ALL_CROSSINGS)) - { - stat = appendPortals(apexIndex, pathSize-1, closestEndPos, path, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath, options); - if (stat != DT_IN_PROGRESS) - return stat; - } - } - - stat = appendVertex(closestEndPos, DT_STRAIGHTPATH_END, 0, - straightPath, straightPathFlags, straightPathRefs, - straightPathCount, maxStraightPath); - - return DT_SUCCESS | ((*straightPathCount >= maxStraightPath) ? DT_BUFFER_TOO_SMALL : 0); -} - -/// @par -/// -/// This method is optimized for small delta movement and a small number of -/// polygons. If used for too great a distance, the result set will form an -/// incomplete path. -/// -/// @p resultPos will equal the @p endPos if the end is reached. -/// Otherwise the closest reachable position will be returned. -/// -/// @p resultPos is not projected onto the surface of the navigation -/// mesh. Use #getPolyHeight if this is needed. -/// -/// This method treats the end position in the same manner as -/// the #raycast method. (As a 2D point.) See that method's documentation -/// for details. -/// -/// If the @p visited array is too small to hold the entire result set, it will -/// be filled as far as possible from the start position toward the end -/// position. -/// -dtStatus dtNavMeshQuery::moveAlongSurface(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* resultPos, dtPolyRef* visited, int* visitedCount, const int maxVisitedSize) const -{ - dtAssert(m_nav); - dtAssert(m_tinyNodePool); - - *visitedCount = 0; - - // Validate input - if (!startRef) - return DT_FAILURE | DT_INVALID_PARAM; - if (!m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - dtStatus status = DT_SUCCESS; - - static const int MAX_STACK = 48; - dtNode* stack[MAX_STACK]; - int nstack = 0; - - m_tinyNodePool->clear(); - - dtNode* startNode = m_tinyNodePool->getNode(startRef); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_CLOSED; - stack[nstack++] = startNode; - - float bestPos[3]; - float bestDist = FLT_MAX; - dtNode* bestNode = 0; - dtVcopy(bestPos, startPos); - - // Search constraints - float searchPos[3], searchRadSqr; - dtVlerp(searchPos, startPos, endPos, 0.5f); - searchRadSqr = dtSqr(dtVdist(startPos, endPos)/2.0f + 0.001f); - - float verts[DT_VERTS_PER_POLYGON*3]; - - while (nstack) - { - // Pop front. - dtNode* curNode = stack[0]; - for (int i = 0; i < nstack-1; ++i) - stack[i] = stack[i+1]; - nstack--; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef curRef = curNode->id; - const dtMeshTile* curTile = 0; - const dtPoly* curPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(curRef, &curTile, &curPoly); - - // Collect vertices. - const int nverts = curPoly->vertCount; - for (int i = 0; i < nverts; ++i) - dtVcopy(&verts[i*3], &curTile->verts[curPoly->verts[i]*3]); - - // If target is inside the poly, stop search. - if (dtPointInPolygon(endPos, verts, nverts)) - { - bestNode = curNode; - dtVcopy(bestPos, endPos); - break; - } - - // Find wall edges and find nearest point inside the walls. - for (int i = 0, j = (int)curPoly->vertCount-1; i < (int)curPoly->vertCount; j = i++) - { - // Find links to neighbours. - static const int MAX_NEIS = 8; - int nneis = 0; - dtPolyRef neis[MAX_NEIS]; - - if (curPoly->neis[j] & DT_EXT_LINK) - { - // Tile border. - for (unsigned int k = curPoly->firstLink; k != DT_NULL_LINK; k = curTile->links[k].next) - { - const dtLink* link = &curTile->links[k]; - if (link->edge == j) - { - if (link->ref != 0) - { - const dtMeshTile* neiTile = 0; - const dtPoly* neiPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); - if (filter->passFilter(link->ref, neiTile, neiPoly)) - { - if (nneis < MAX_NEIS) - neis[nneis++] = link->ref; - } - } - } - } - } - else if (curPoly->neis[j]) - { - const unsigned int idx = (unsigned int)(curPoly->neis[j]-1); - const dtPolyRef ref = m_nav->getPolyRefBase(curTile) | idx; - if (filter->passFilter(ref, curTile, &curTile->polys[idx])) - { - // Internal edge, encode id. - neis[nneis++] = ref; - } - } - - if (!nneis) - { - // Wall edge, calc distance. - const float* vj = &verts[j*3]; - const float* vi = &verts[i*3]; - float tseg; - const float distSqr = dtDistancePtSegSqr2D(endPos, vj, vi, tseg); - if (distSqr < bestDist) - { - // Update nearest distance. - dtVlerp(bestPos, vj,vi, tseg); - bestDist = distSqr; - bestNode = curNode; - } - } - else - { - for (int k = 0; k < nneis; ++k) - { - // Skip if no node can be allocated. - dtNode* neighbourNode = m_tinyNodePool->getNode(neis[k]); - if (!neighbourNode) - continue; - // Skip if already visited. - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Skip the link if it is too far from search constraint. - // TODO: Maybe should use getPortalPoints(), but this one is way faster. - const float* vj = &verts[j*3]; - const float* vi = &verts[i*3]; - float tseg; - float distSqr = dtDistancePtSegSqr2D(searchPos, vj, vi, tseg); - if (distSqr > searchRadSqr) - continue; - - // Mark as the node as visited and push to queue. - if (nstack < MAX_STACK) - { - neighbourNode->pidx = m_tinyNodePool->getNodeIdx(curNode); - neighbourNode->flags |= DT_NODE_CLOSED; - stack[nstack++] = neighbourNode; - } - } - } - } - } - - int n = 0; - if (bestNode) - { - // Reverse the path. - dtNode* prev = 0; - dtNode* node = bestNode; - do - { - dtNode* next = m_tinyNodePool->getNodeAtIdx(node->pidx); - node->pidx = m_tinyNodePool->getNodeIdx(prev); - prev = node; - node = next; - } - while (node); - - // Store result - node = prev; - do - { - visited[n++] = node->id; - if (n >= maxVisitedSize) - { - status |= DT_BUFFER_TOO_SMALL; - break; - } - node = m_tinyNodePool->getNodeAtIdx(node->pidx); - } - while (node); - } - - dtVcopy(resultPos, bestPos); - - *visitedCount = n; - - return status; -} - - -dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, dtPolyRef to, float* left, float* right, - unsigned char& fromType, unsigned char& toType) const -{ - dtAssert(m_nav); - - const dtMeshTile* fromTile = 0; - const dtPoly* fromPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(from, &fromTile, &fromPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - fromType = fromPoly->getType(); - - const dtMeshTile* toTile = 0; - const dtPoly* toPoly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(to, &toTile, &toPoly))) - return DT_FAILURE | DT_INVALID_PARAM; - toType = toPoly->getType(); - - return getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right); -} - -// Returns portal points between two polygons. -dtStatus dtNavMeshQuery::getPortalPoints(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* left, float* right) const -{ - // Find the link that points to the 'to' polygon. - const dtLink* link = 0; - for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromTile->links[i].next) - { - if (fromTile->links[i].ref == to) - { - link = &fromTile->links[i]; - break; - } - } - if (!link) - return DT_FAILURE | DT_INVALID_PARAM; - - // Handle off-mesh connections. - if (fromPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - // Find link that points to first vertex. - for (unsigned int i = fromPoly->firstLink; i != DT_NULL_LINK; i = fromTile->links[i].next) - { - if (fromTile->links[i].ref == to) - { - const int v = fromTile->links[i].edge; - dtVcopy(left, &fromTile->verts[fromPoly->verts[v]*3]); - dtVcopy(right, &fromTile->verts[fromPoly->verts[v]*3]); - return DT_SUCCESS; - } - } - return DT_FAILURE | DT_INVALID_PARAM; - } - - if (toPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - { - for (unsigned int i = toPoly->firstLink; i != DT_NULL_LINK; i = toTile->links[i].next) - { - if (toTile->links[i].ref == from) - { - const int v = toTile->links[i].edge; - dtVcopy(left, &toTile->verts[toPoly->verts[v]*3]); - dtVcopy(right, &toTile->verts[toPoly->verts[v]*3]); - return DT_SUCCESS; - } - } - return DT_FAILURE | DT_INVALID_PARAM; - } - - // Find portal vertices. - const int v0 = fromPoly->verts[link->edge]; - const int v1 = fromPoly->verts[(link->edge+1) % (int)fromPoly->vertCount]; - dtVcopy(left, &fromTile->verts[v0*3]); - dtVcopy(right, &fromTile->verts[v1*3]); - - // If the link is at tile boundary, dtClamp the vertices to - // the link width. - if (link->side != 0xff) - { - // Unpack portal limits. - if (link->bmin != 0 || link->bmax != 255) - { - const float s = 1.0f/255.0f; - const float tmin = link->bmin*s; - const float tmax = link->bmax*s; - dtVlerp(left, &fromTile->verts[v0*3], &fromTile->verts[v1*3], tmin); - dtVlerp(right, &fromTile->verts[v0*3], &fromTile->verts[v1*3], tmax); - } - } - - return DT_SUCCESS; -} - -// Returns edge mid point between two polygons. -dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, dtPolyRef to, float* mid) const -{ - float left[3], right[3]; - unsigned char fromType, toType; - if (dtStatusFailed(getPortalPoints(from, to, left,right, fromType, toType))) - return DT_FAILURE | DT_INVALID_PARAM; - mid[0] = (left[0]+right[0])*0.5f; - mid[1] = (left[1]+right[1])*0.5f; - mid[2] = (left[2]+right[2])*0.5f; - return DT_SUCCESS; -} - -dtStatus dtNavMeshQuery::getEdgeMidPoint(dtPolyRef from, const dtPoly* fromPoly, const dtMeshTile* fromTile, - dtPolyRef to, const dtPoly* toPoly, const dtMeshTile* toTile, - float* mid) const -{ - float left[3], right[3]; - if (dtStatusFailed(getPortalPoints(from, fromPoly, fromTile, to, toPoly, toTile, left, right))) - return DT_FAILURE | DT_INVALID_PARAM; - mid[0] = (left[0]+right[0])*0.5f; - mid[1] = (left[1]+right[1])*0.5f; - mid[2] = (left[2]+right[2])*0.5f; - return DT_SUCCESS; -} - -/// @par -/// -/// This method is meant to be used for quick, short distance checks. -/// -/// If the path array is too small to hold the result, it will be filled as -/// far as possible from the start postion toward the end position. -/// -/// Using the Hit Parameter (t) -/// -/// If the hit parameter is a very high value (FLT_MAX), then the ray has hit -/// the end position. In this case the path represents a valid corridor to the -/// end position and the value of @p hitNormal is undefined. -/// -/// If the hit parameter is zero, then the start position is on the wall that -/// was hit and the value of @p hitNormal is undefined. -/// -/// If 0 < t < 1.0 then the following applies: -/// -/// @code -/// distanceToHitBorder = distanceToEndPosition * t -/// hitPoint = startPos + (endPos - startPos) * t -/// @endcode -/// -/// Use Case Restriction -/// -/// The raycast ignores the y-value of the end position. (2D check.) This -/// places significant limits on how it can be used. For example: -/// -/// Consider a scene where there is a main floor with a second floor balcony -/// that hangs over the main floor. So the first floor mesh extends below the -/// balcony mesh. The start position is somewhere on the first floor. The end -/// position is on the balcony. -/// -/// The raycast will search toward the end position along the first floor mesh. -/// If it reaches the end position's xz-coordinates it will indicate FLT_MAX -/// (no wall hit), meaning it reached the end position. This is one example of why -/// this method is meant for short distance checks. -/// -dtStatus dtNavMeshQuery::raycast(dtPolyRef startRef, const float* startPos, const float* endPos, - const dtQueryFilter* filter, - float* t, float* hitNormal, dtPolyRef* path, int* pathCount, const int maxPath) const -{ - dtAssert(m_nav); - - *t = 0; - if (pathCount) - *pathCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - dtPolyRef curRef = startRef; - float verts[DT_VERTS_PER_POLYGON*3]; - int n = 0; - - hitNormal[0] = 0; - hitNormal[1] = 0; - hitNormal[2] = 0; - - dtStatus status = DT_SUCCESS; - - while (curRef) - { - // Cast ray against current polygon. - - // The API input has been cheked already, skip checking internal data. - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - m_nav->getTileAndPolyByRefUnsafe(curRef, &tile, &poly); - - // Collect vertices. - int nv = 0; - for (int i = 0; i < (int)poly->vertCount; ++i) - { - dtVcopy(&verts[nv*3], &tile->verts[poly->verts[i]*3]); - nv++; - } - - float tmin, tmax; - int segMin, segMax; - if (!dtIntersectSegmentPoly2D(startPos, endPos, verts, nv, tmin, tmax, segMin, segMax)) - { - // Could not hit the polygon, keep the old t and report hit. - if (pathCount) - *pathCount = n; - return status; - } - // Keep track of furthest t so far. - if (tmax > *t) - *t = tmax; - - // Store visited polygons. - if (n < maxPath) - path[n++] = curRef; - else - status |= DT_BUFFER_TOO_SMALL; - - // Ray end is completely inside the polygon. - if (segMax == -1) - { - *t = FLT_MAX; - if (pathCount) - *pathCount = n; - return status; - } - - // Follow neighbours. - dtPolyRef nextRef = 0; - - for (unsigned int i = poly->firstLink; i != DT_NULL_LINK; i = tile->links[i].next) - { - const dtLink* link = &tile->links[i]; - - // Find link which contains this edge. - if ((int)link->edge != segMax) - continue; - - // Get pointer to the next polygon. - const dtMeshTile* nextTile = 0; - const dtPoly* nextPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &nextTile, &nextPoly); - - // Skip off-mesh connections. - if (nextPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Skip links based on filter. - if (!filter->passFilter(link->ref, nextTile, nextPoly)) - continue; - - // If the link is internal, just return the ref. - if (link->side == 0xff) - { - nextRef = link->ref; - break; - } - - // If the link is at tile boundary, - - // Check if the link spans the whole edge, and accept. - if (link->bmin == 0 && link->bmax == 255) - { - nextRef = link->ref; - break; - } - - // Check for partial edge links. - const int v0 = poly->verts[link->edge]; - const int v1 = poly->verts[(link->edge+1) % poly->vertCount]; - const float* left = &tile->verts[v0*3]; - const float* right = &tile->verts[v1*3]; - - // Check that the intersection lies inside the link portal. - if (link->side == 0 || link->side == 4) - { - // Calculate link size. - const float s = 1.0f/255.0f; - float lmin = left[2] + (right[2] - left[2])*(link->bmin*s); - float lmax = left[2] + (right[2] - left[2])*(link->bmax*s); - if (lmin > lmax) dtSwap(lmin, lmax); - - // Find Z intersection. - float z = startPos[2] + (endPos[2]-startPos[2])*tmax; - if (z >= lmin && z <= lmax) - { - nextRef = link->ref; - break; - } - } - else if (link->side == 2 || link->side == 6) - { - // Calculate link size. - const float s = 1.0f/255.0f; - float lmin = left[0] + (right[0] - left[0])*(link->bmin*s); - float lmax = left[0] + (right[0] - left[0])*(link->bmax*s); - if (lmin > lmax) dtSwap(lmin, lmax); - - // Find X intersection. - float x = startPos[0] + (endPos[0]-startPos[0])*tmax; - if (x >= lmin && x <= lmax) - { - nextRef = link->ref; - break; - } - } - } - - if (!nextRef) - { - // No neighbour, we hit a wall. - - // Calculate hit normal. - const int a = segMax; - const int b = segMax+1 < nv ? segMax+1 : 0; - const float* va = &verts[a*3]; - const float* vb = &verts[b*3]; - const float dx = vb[0] - va[0]; - const float dz = vb[2] - va[2]; - hitNormal[0] = dz; - hitNormal[1] = 0; - hitNormal[2] = -dx; - dtVnormalize(hitNormal); - - if (pathCount) - *pathCount = n; - return status; - } - - // No hit, advance to neighbour polygon. - curRef = nextRef; - } - - if (pathCount) - *pathCount = n; - - return status; -} - -/// @par -/// -/// At least one result array must be provided. -/// -/// The order of the result set is from least to highest cost to reach the polygon. -/// -/// A common use case for this method is to perform Dijkstra searches. -/// Candidate polygons are found by searching the graph beginning at the start polygon. -/// -/// If a polygon is not found via the graph search, even if it intersects the -/// search circle, it will not be included in the result set. For example: -/// -/// polyA is the start polygon. -/// polyB shares an edge with polyA. (Is adjacent.) -/// polyC shares an edge with polyB, but not with polyA -/// Even if the search circle overlaps polyC, it will not be included in the -/// result set unless polyB is also in the set. -/// -/// The value of the center point is used as the start position for cost -/// calculations. It is not projected onto the surface of the mesh, so its -/// y-value will effect the costs. -/// -/// Intersection tests occur in 2D. All polygons and the search circle are -/// projected onto the xz-plane. So the y-value of the center point does not -/// effect intersection tests. -/// -/// If the result arrays are to small to hold the entire result set, they will be -/// filled to capacity. -/// -dtStatus dtNavMeshQuery::findPolysAroundCircle(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - *resultCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtStatus status = DT_SUCCESS; - - int n = 0; - if (n < maxResult) - { - if (resultRef) - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - if (resultCost) - resultCost[n] = 0; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - const float radiusSqr = dtSqr(radius); - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the circle is not touching the next polygon, skip it. - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - if (distSqr > radiusSqr) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - dtVlerp(neighbourNode->pos, va, vb, 0.5f); - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - if (n < maxResult) - { - if (resultRef) - resultRef[n] = neighbourNode->id; - if (resultParent) - resultParent[n] = m_nodePool->getNodeAtIdx(neighbourNode->pidx)->id; - if (resultCost) - resultCost[n] = neighbourNode->total; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - neighbourNode->flags = DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - *resultCount = n; - - return status; -} - -/// @par -/// -/// The order of the result set is from least to highest cost. -/// -/// At least one result array must be provided. -/// -/// A common use case for this method is to perform Dijkstra searches. -/// Candidate polygons are found by searching the graph beginning at the start -/// polygon. -/// -/// The same intersection test restrictions that apply to findPolysAroundCircle() -/// method apply to this method. -/// -/// The 3D centroid of the search polygon is used as the start position for cost -/// calculations. -/// -/// Intersection tests occur in 2D. All polygons are projected onto the -/// xz-plane. So the y-values of the vertices do not effect intersection tests. -/// -/// If the result arrays are is too small to hold the entire result set, they will -/// be filled to capacity. -/// -dtStatus dtNavMeshQuery::findPolysAroundShape(dtPolyRef startRef, const float* verts, const int nverts, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, float* resultCost, - int* resultCount, const int maxResult) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - *resultCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - float centerPos[3] = {0,0,0}; - for (int i = 0; i < nverts; ++i) - dtVadd(centerPos,centerPos,&verts[i*3]); - dtVscale(centerPos,centerPos,1.0f/nverts); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - dtStatus status = DT_SUCCESS; - - int n = 0; - if (n < maxResult) - { - if (resultRef) - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - if (resultCost) - resultCost[n] = 0; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(bestRef, bestPoly, bestTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the poly is not touching the edge to the next polygon, skip the connection it. - float tmin, tmax; - int segMin, segMax; - if (!dtIntersectSegmentPoly2D(va, vb, verts, nverts, tmin, tmax, segMin, segMax)) - continue; - if (tmin > 1.0f || tmax < 0.0f) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - dtVlerp(neighbourNode->pos, va, vb, 0.5f); - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - if (n < maxResult) - { - if (resultRef) - resultRef[n] = neighbourNode->id; - if (resultParent) - resultParent[n] = m_nodePool->getNodeAtIdx(neighbourNode->pidx)->id; - if (resultCost) - resultCost[n] = neighbourNode->total; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - neighbourNode->flags = DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - *resultCount = n; - - return status; -} - -/// @par -/// -/// This method is optimized for a small search radius and small number of result -/// polygons. -/// -/// Candidate polygons are found by searching the navigation graph beginning at -/// the start polygon. -/// -/// The same intersection test restrictions that apply to the findPolysAroundCircle -/// mehtod applies to this method. -/// -/// The value of the center point is used as the start point for cost calculations. -/// It is not projected onto the surface of the mesh, so its y-value will effect -/// the costs. -/// -/// Intersection tests occur in 2D. All polygons and the search circle are -/// projected onto the xz-plane. So the y-value of the center point does not -/// effect intersection tests. -/// -/// If the result arrays are is too small to hold the entire result set, they will -/// be filled to capacity. -/// -dtStatus dtNavMeshQuery::findLocalNeighbourhood(dtPolyRef startRef, const float* centerPos, const float radius, - const dtQueryFilter* filter, - dtPolyRef* resultRef, dtPolyRef* resultParent, - int* resultCount, const int maxResult) const -{ - dtAssert(m_nav); - dtAssert(m_tinyNodePool); - - *resultCount = 0; - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - static const int MAX_STACK = 48; - dtNode* stack[MAX_STACK]; - int nstack = 0; - - m_tinyNodePool->clear(); - - dtNode* startNode = m_tinyNodePool->getNode(startRef); - startNode->pidx = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_CLOSED; - stack[nstack++] = startNode; - - const float radiusSqr = dtSqr(radius); - - float pa[DT_VERTS_PER_POLYGON*3]; - float pb[DT_VERTS_PER_POLYGON*3]; - - dtStatus status = DT_SUCCESS; - - int n = 0; - if (n < maxResult) - { - resultRef[n] = startNode->id; - if (resultParent) - resultParent[n] = 0; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - while (nstack) - { - // Pop front. - dtNode* curNode = stack[0]; - for (int i = 0; i < nstack-1; ++i) - stack[i] = stack[i+1]; - nstack--; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef curRef = curNode->id; - const dtMeshTile* curTile = 0; - const dtPoly* curPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(curRef, &curTile, &curPoly); - - for (unsigned int i = curPoly->firstLink; i != DT_NULL_LINK; i = curTile->links[i].next) - { - const dtLink* link = &curTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours. - if (!neighbourRef) - continue; - - // Skip if cannot alloca more nodes. - dtNode* neighbourNode = m_tinyNodePool->getNode(neighbourRef); - if (!neighbourNode) - continue; - // Skip visited. - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Expand to neighbour - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Skip off-mesh connections. - if (neighbourPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Do not advance if the polygon is excluded by the filter. - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - // Find edge and calc distance to the edge. - float va[3], vb[3]; - if (!getPortalPoints(curRef, curPoly, curTile, neighbourRef, neighbourPoly, neighbourTile, va, vb)) - continue; - - // If the circle is not touching the next polygon, skip it. - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - if (distSqr > radiusSqr) - continue; - - // Mark node visited, this is done before the overlap test so that - // we will not visit the poly again if the test fails. - neighbourNode->flags |= DT_NODE_CLOSED; - neighbourNode->pidx = m_tinyNodePool->getNodeIdx(curNode); - - // Check that the polygon does not collide with existing polygons. - - // Collect vertices of the neighbour poly. - const int npa = neighbourPoly->vertCount; - for (int k = 0; k < npa; ++k) - dtVcopy(&pa[k*3], &neighbourTile->verts[neighbourPoly->verts[k]*3]); - - bool overlap = false; - for (int j = 0; j < n; ++j) - { - dtPolyRef pastRef = resultRef[j]; - - // Connected polys do not overlap. - bool connected = false; - for (unsigned int k = curPoly->firstLink; k != DT_NULL_LINK; k = curTile->links[k].next) - { - if (curTile->links[k].ref == pastRef) - { - connected = true; - break; - } - } - if (connected) - continue; - - // Potentially overlapping. - const dtMeshTile* pastTile = 0; - const dtPoly* pastPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(pastRef, &pastTile, &pastPoly); - - // Get vertices and test overlap - const int npb = pastPoly->vertCount; - for (int k = 0; k < npb; ++k) - dtVcopy(&pb[k*3], &pastTile->verts[pastPoly->verts[k]*3]); - - if (dtOverlapPolyPoly2D(pa,npa, pb,npb)) - { - overlap = true; - break; - } - } - if (overlap) - continue; - - // This poly is fine, store and advance to the poly. - if (n < maxResult) - { - resultRef[n] = neighbourRef; - if (resultParent) - resultParent[n] = curRef; - ++n; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - if (nstack < MAX_STACK) - { - stack[nstack++] = neighbourNode; - } - } - } - - *resultCount = n; - - return status; -} - - -struct dtSegInterval -{ - dtPolyRef ref; - short tmin, tmax; -}; - -static void insertInterval(dtSegInterval* ints, int& nints, const int maxInts, - const short tmin, const short tmax, const dtPolyRef ref) -{ - if (nints+1 > maxInts) return; - // Find insertion point. - int idx = 0; - while (idx < nints) - { - if (tmax <= ints[idx].tmin) - break; - idx++; - } - // Move current results. - if (nints-idx) - memmove(ints+idx+1, ints+idx, sizeof(dtSegInterval)*(nints-idx)); - // Store - ints[idx].ref = ref; - ints[idx].tmin = tmin; - ints[idx].tmax = tmax; - nints++; -} - -/// @par -/// -/// If the @p segmentRefs parameter is provided, then all polygon segments will be returned. -/// Otherwise only the wall segments are returned. -/// -/// A segment that is normally a portal will be included in the result set as a -/// wall if the @p filter results in the neighbor polygon becoomming impassable. -/// -/// The @p segmentVerts and @p segmentRefs buffers should normally be sized for the -/// maximum segments per polygon of the source navigation mesh. -/// -dtStatus dtNavMeshQuery::getPolyWallSegments(dtPolyRef ref, const dtQueryFilter* filter, - float* segmentVerts, dtPolyRef* segmentRefs, int* segmentCount, - const int maxSegments) const -{ - dtAssert(m_nav); - - *segmentCount = 0; - - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - if (dtStatusFailed(m_nav->getTileAndPolyByRef(ref, &tile, &poly))) - return DT_FAILURE | DT_INVALID_PARAM; - - int n = 0; - static const int MAX_INTERVAL = 16; - dtSegInterval ints[MAX_INTERVAL]; - int nints; - - const bool storePortals = segmentRefs != 0; - - dtStatus status = DT_SUCCESS; - - for (int i = 0, j = (int)poly->vertCount-1; i < (int)poly->vertCount; j = i++) - { - // Skip non-solid edges. - nints = 0; - if (poly->neis[j] & DT_EXT_LINK) - { - // Tile border. - for (unsigned int k = poly->firstLink; k != DT_NULL_LINK; k = tile->links[k].next) - { - const dtLink* link = &tile->links[k]; - if (link->edge == j) - { - if (link->ref != 0) - { - const dtMeshTile* neiTile = 0; - const dtPoly* neiPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); - if (filter->passFilter(link->ref, neiTile, neiPoly)) - { - insertInterval(ints, nints, MAX_INTERVAL, link->bmin, link->bmax, link->ref); - } - } - } - } - } - else - { - // Internal edge - dtPolyRef neiRef = 0; - if (poly->neis[j]) - { - const unsigned int idx = (unsigned int)(poly->neis[j]-1); - neiRef = m_nav->getPolyRefBase(tile) | idx; - if (!filter->passFilter(neiRef, tile, &tile->polys[idx])) - neiRef = 0; - } - - // If the edge leads to another polygon and portals are not stored, skip. - if (neiRef != 0 && !storePortals) - continue; - - if (n < maxSegments) - { - const float* vj = &tile->verts[poly->verts[j]*3]; - const float* vi = &tile->verts[poly->verts[i]*3]; - float* seg = &segmentVerts[n*6]; - dtVcopy(seg+0, vj); - dtVcopy(seg+3, vi); - if (segmentRefs) - segmentRefs[n] = neiRef; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - - continue; - } - - // Add sentinels - insertInterval(ints, nints, MAX_INTERVAL, -1, 0, 0); - insertInterval(ints, nints, MAX_INTERVAL, 255, 256, 0); - - // Store segments. - const float* vj = &tile->verts[poly->verts[j]*3]; - const float* vi = &tile->verts[poly->verts[i]*3]; - for (int k = 1; k < nints; ++k) - { - // Portal segment. - if (storePortals && ints[k].ref) - { - const float tmin = ints[k].tmin/255.0f; - const float tmax = ints[k].tmax/255.0f; - if (n < maxSegments) - { - float* seg = &segmentVerts[n*6]; - dtVlerp(seg+0, vj,vi, tmin); - dtVlerp(seg+3, vj,vi, tmax); - if (segmentRefs) - segmentRefs[n] = ints[k].ref; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - } - - // Wall segment. - const int imin = ints[k-1].tmax; - const int imax = ints[k].tmin; - if (imin != imax) - { - const float tmin = imin/255.0f; - const float tmax = imax/255.0f; - if (n < maxSegments) - { - float* seg = &segmentVerts[n*6]; - dtVlerp(seg+0, vj,vi, tmin); - dtVlerp(seg+3, vj,vi, tmax); - if (segmentRefs) - segmentRefs[n] = 0; - n++; - } - else - { - status |= DT_BUFFER_TOO_SMALL; - } - } - } - } - - *segmentCount = n; - - return status; -} - -/// @par -/// -/// @p hitPos is not adjusted using the height detail data. -/// -/// @p hitDist will equal the search radius if there is no wall within the -/// radius. In this case the values of @p hitPos and @p hitNormal are -/// undefined. -/// -/// The normal will become unpredicable if @p hitDist is a very small number. -/// -dtStatus dtNavMeshQuery::findDistanceToWall(dtPolyRef startRef, const float* centerPos, const float maxRadius, - const dtQueryFilter* filter, - float* hitDist, float* hitPos, float* hitNormal) const -{ - dtAssert(m_nav); - dtAssert(m_nodePool); - dtAssert(m_openList); - - // Validate input - if (!startRef || !m_nav->isValidPolyRef(startRef)) - return DT_FAILURE | DT_INVALID_PARAM; - - m_nodePool->clear(); - m_openList->clear(); - - dtNode* startNode = m_nodePool->getNode(startRef); - dtVcopy(startNode->pos, centerPos); - startNode->pidx = 0; - startNode->cost = 0; - startNode->total = 0; - startNode->id = startRef; - startNode->flags = DT_NODE_OPEN; - m_openList->push(startNode); - - float radiusSqr = dtSqr(maxRadius); - - dtStatus status = DT_SUCCESS; - - while (!m_openList->empty()) - { - dtNode* bestNode = m_openList->pop(); - bestNode->flags &= ~DT_NODE_OPEN; - bestNode->flags |= DT_NODE_CLOSED; - - // Get poly and tile. - // The API input has been cheked already, skip checking internal data. - const dtPolyRef bestRef = bestNode->id; - const dtMeshTile* bestTile = 0; - const dtPoly* bestPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(bestRef, &bestTile, &bestPoly); - - // Get parent poly and tile. - dtPolyRef parentRef = 0; - const dtMeshTile* parentTile = 0; - const dtPoly* parentPoly = 0; - if (bestNode->pidx) - parentRef = m_nodePool->getNodeAtIdx(bestNode->pidx)->id; - if (parentRef) - m_nav->getTileAndPolyByRefUnsafe(parentRef, &parentTile, &parentPoly); - - // Hit test walls. - for (int i = 0, j = (int)bestPoly->vertCount-1; i < (int)bestPoly->vertCount; j = i++) - { - // Skip non-solid edges. - if (bestPoly->neis[j] & DT_EXT_LINK) - { - // Tile border. - bool solid = true; - for (unsigned int k = bestPoly->firstLink; k != DT_NULL_LINK; k = bestTile->links[k].next) - { - const dtLink* link = &bestTile->links[k]; - if (link->edge == j) - { - if (link->ref != 0) - { - const dtMeshTile* neiTile = 0; - const dtPoly* neiPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(link->ref, &neiTile, &neiPoly); - if (filter->passFilter(link->ref, neiTile, neiPoly)) - solid = false; - } - break; - } - } - if (!solid) continue; - } - else if (bestPoly->neis[j]) - { - // Internal edge - const unsigned int idx = (unsigned int)(bestPoly->neis[j]-1); - const dtPolyRef ref = m_nav->getPolyRefBase(bestTile) | idx; - if (filter->passFilter(ref, bestTile, &bestTile->polys[idx])) - continue; - } - - // Calc distance to the edge. - const float* vj = &bestTile->verts[bestPoly->verts[j]*3]; - const float* vi = &bestTile->verts[bestPoly->verts[i]*3]; - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, vj, vi, tseg); - - // Edge is too far, skip. - if (distSqr > radiusSqr) - continue; - - // Hit wall, update radius. - radiusSqr = distSqr; - // Calculate hit pos. - hitPos[0] = vj[0] + (vi[0] - vj[0])*tseg; - hitPos[1] = vj[1] + (vi[1] - vj[1])*tseg; - hitPos[2] = vj[2] + (vi[2] - vj[2])*tseg; - } - - for (unsigned int i = bestPoly->firstLink; i != DT_NULL_LINK; i = bestTile->links[i].next) - { - const dtLink* link = &bestTile->links[i]; - dtPolyRef neighbourRef = link->ref; - // Skip invalid neighbours and do not follow back to parent. - if (!neighbourRef || neighbourRef == parentRef) - continue; - - // Expand to neighbour. - const dtMeshTile* neighbourTile = 0; - const dtPoly* neighbourPoly = 0; - m_nav->getTileAndPolyByRefUnsafe(neighbourRef, &neighbourTile, &neighbourPoly); - - // Skip off-mesh connections. - if (neighbourPoly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) - continue; - - // Calc distance to the edge. - const float* va = &bestTile->verts[bestPoly->verts[link->edge]*3]; - const float* vb = &bestTile->verts[bestPoly->verts[(link->edge+1) % bestPoly->vertCount]*3]; - float tseg; - float distSqr = dtDistancePtSegSqr2D(centerPos, va, vb, tseg); - - // If the circle is not touching the next polygon, skip it. - if (distSqr > radiusSqr) - continue; - - if (!filter->passFilter(neighbourRef, neighbourTile, neighbourPoly)) - continue; - - dtNode* neighbourNode = m_nodePool->getNode(neighbourRef); - if (!neighbourNode) - { - status |= DT_OUT_OF_NODES; - continue; - } - - if (neighbourNode->flags & DT_NODE_CLOSED) - continue; - - // Cost - if (neighbourNode->flags == 0) - { - getEdgeMidPoint(bestRef, bestPoly, bestTile, - neighbourRef, neighbourPoly, neighbourTile, neighbourNode->pos); - } - - const float total = bestNode->total + dtVdist(bestNode->pos, neighbourNode->pos); - - // The node is already in open list and the new result is worse, skip. - if ((neighbourNode->flags & DT_NODE_OPEN) && total >= neighbourNode->total) - continue; - - neighbourNode->id = neighbourRef; - neighbourNode->flags = (neighbourNode->flags & ~DT_NODE_CLOSED); - neighbourNode->pidx = m_nodePool->getNodeIdx(bestNode); - neighbourNode->total = total; - - if (neighbourNode->flags & DT_NODE_OPEN) - { - m_openList->modify(neighbourNode); - } - else - { - neighbourNode->flags |= DT_NODE_OPEN; - m_openList->push(neighbourNode); - } - } - } - - // Calc hit normal. - dtVsub(hitNormal, centerPos, hitPos); - dtVnormalize(hitNormal); - - *hitDist = sqrtf(radiusSqr); - - return status; -} - -bool dtNavMeshQuery::isValidPolyRef(dtPolyRef ref, const dtQueryFilter* filter) const -{ - const dtMeshTile* tile = 0; - const dtPoly* poly = 0; - dtStatus status = m_nav->getTileAndPolyByRef(ref, &tile, &poly); - // If cannot get polygon, assume it does not exists and boundary is invalid. - if (dtStatusFailed(status)) - return false; - // If cannot pass filter, assume flags has changed and boundary is invalid. - if (!filter->passFilter(ref, tile, poly)) - return false; - return true; -} - -/// @par -/// -/// The closed list is the list of polygons that were fully evaluated during -/// the last navigation graph search. (A* or Dijkstra) -/// -bool dtNavMeshQuery::isInClosedList(dtPolyRef ref) const -{ - if (!m_nodePool) return false; - const dtNode* node = m_nodePool->findNode(ref); - return node && node->flags & DT_NODE_CLOSED; -} diff --git a/critterai/src/nav-rcn/Detour/Source/DetourNode.cpp b/critterai/src/nav-rcn/Detour/Source/DetourNode.cpp deleted file mode 100644 index de7b159b..00000000 --- a/critterai/src/nav-rcn/Detour/Source/DetourNode.cpp +++ /dev/null @@ -1,164 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#include "DetourNode.h" -#include "DetourAlloc.h" -#include "DetourAssert.h" -#include "DetourCommon.h" -#include - -inline unsigned int dtHashRef(dtPolyRef a) -{ - a += ~(a<<15); - a ^= (a>>10); - a += (a<<3); - a ^= (a>>6); - a += ~(a<<11); - a ^= (a>>16); - return (unsigned int)a; -} - -////////////////////////////////////////////////////////////////////////////////////////// -dtNodePool::dtNodePool(int maxNodes, int hashSize) : - m_nodes(0), - m_first(0), - m_next(0), - m_maxNodes(maxNodes), - m_hashSize(hashSize), - m_nodeCount(0) -{ - dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize); - dtAssert(m_maxNodes > 0); - - m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM); - m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM); - m_first = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*hashSize, DT_ALLOC_PERM); - - dtAssert(m_nodes); - dtAssert(m_next); - dtAssert(m_first); - - memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize); - memset(m_next, 0xff, sizeof(dtNodeIndex)*m_maxNodes); -} - -dtNodePool::~dtNodePool() -{ - dtFree(m_nodes); - dtFree(m_next); - dtFree(m_first); -} - -void dtNodePool::clear() -{ - memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize); - m_nodeCount = 0; -} - -dtNode* dtNodePool::findNode(dtPolyRef id) -{ - unsigned int bucket = dtHashRef(id) & (m_hashSize-1); - dtNodeIndex i = m_first[bucket]; - while (i != DT_NULL_IDX) - { - if (m_nodes[i].id == id) - return &m_nodes[i]; - i = m_next[i]; - } - return 0; -} - -dtNode* dtNodePool::getNode(dtPolyRef id) -{ - unsigned int bucket = dtHashRef(id) & (m_hashSize-1); - dtNodeIndex i = m_first[bucket]; - dtNode* node = 0; - while (i != DT_NULL_IDX) - { - if (m_nodes[i].id == id) - return &m_nodes[i]; - i = m_next[i]; - } - - if (m_nodeCount >= m_maxNodes) - return 0; - - i = (dtNodeIndex)m_nodeCount; - m_nodeCount++; - - // Init node - node = &m_nodes[i]; - node->pidx = 0; - node->cost = 0; - node->total = 0; - node->id = id; - node->flags = 0; - - m_next[i] = m_first[bucket]; - m_first[bucket] = i; - - return node; -} - - -////////////////////////////////////////////////////////////////////////////////////////// -dtNodeQueue::dtNodeQueue(int n) : - m_heap(0), - m_capacity(n), - m_size(0) -{ - dtAssert(m_capacity > 0); - - m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM); - dtAssert(m_heap); -} - -dtNodeQueue::~dtNodeQueue() -{ - dtFree(m_heap); -} - -void dtNodeQueue::bubbleUp(int i, dtNode* node) -{ - int parent = (i-1)/2; - // note: (index > 0) means there is a parent - while ((i > 0) && (m_heap[parent]->total > node->total)) - { - m_heap[i] = m_heap[parent]; - i = parent; - parent = (i-1)/2; - } - m_heap[i] = node; -} - -void dtNodeQueue::trickleDown(int i, dtNode* node) -{ - int child = (i*2)+1; - while (child < m_size) - { - if (((child+1) < m_size) && - (m_heap[child]->total > m_heap[child+1]->total)) - { - child++; - } - m_heap[i] = m_heap[child]; - i = child; - child = (i*2)+1; - } - bubbleUp(i, node); -} diff --git a/critterai/src/nav-rcn/DetourCrowd/Include/DetourCrowd.h b/critterai/src/nav-rcn/DetourCrowd/Include/DetourCrowd.h deleted file mode 100644 index e789fd34..00000000 --- a/critterai/src/nav-rcn/DetourCrowd/Include/DetourCrowd.h +++ /dev/null @@ -1,432 +0,0 @@ -// -// Copyright (c) 2009-2010 Mikko Mononen memon@inside.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. -// - -#ifndef DETOURCROWD_H -#define DETOURCROWD_H - -#include "DetourNavMeshQuery.h" -#include "DetourObstacleAvoidance.h" -#include "DetourLocalBoundary.h" -#include "DetourPathCorridor.h" -#include "DetourProximityGrid.h" -#include "DetourPathQueue.h" - -/// The maximum number of neighbors that a crowd agent can take into account -/// for steering decisions. -/// @ingroup crowd -static const int DT_CROWDAGENT_MAX_NEIGHBOURS = 6; - -/// The maximum number of corners a crowd agent will look ahead in the path. -/// This value is used for sizing the crowd agent corner buffers. -/// Due to the behavior of the crowd manager, the actual number of useful -/// corners will be one less than this number. -/// @ingroup crowd -static const int DT_CROWDAGENT_MAX_CORNERS = 4; - -/// The maximum number of crowd avoidance configurations supported by the -/// crowd manager. -/// @ingroup crowd -/// @see dtObstacleAvoidanceParams, dtCrowd::setObstacleAvoidanceParams(), dtCrowd::getObstacleAvoidanceParams(), -/// dtCrowdAgentParams::obstacleAvoidanceType -static const int DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS = 8; - -/// Provides neighbor data for agents managed by the crowd. -/// @ingroup crowd -/// @see dtCrowdAgent::neis, dtCrowd -struct dtCrowdNeighbour -{ - int idx; ///< The index of the neighbor in the crowd. - float dist; ///< The distance between the current agent and the neighbor. -}; - -/// The type of navigation mesh polygon the agent is currently traversing. -/// @ingroup crowd -enum CrowdAgentState -{ - DT_CROWDAGENT_STATE_INVALID, ///< The agent is not in a valid state. - DT_CROWDAGENT_STATE_WALKING, ///< The agent is traversing a normal navigation mesh polygon. - DT_CROWDAGENT_STATE_OFFMESH, ///< The agent is traversing an off-mesh connection. -}; - -/// Configuration parameters for a crowd agent. -/// @ingroup crowd -struct dtCrowdAgentParams -{ - float radius; ///< Agent radius. [Limit: >= 0] - float height; ///< Agent height. [Limit: > 0] - float maxAcceleration; ///< Maximum allowed acceleration. [Limit: >= 0] - float maxSpeed; ///< Maximum allowed speed. [Limit: >= 0] - - /// Defines how close a collision element must be before it is considered for steering behaviors. [Limits: > 0] - float collisionQueryRange; - - float pathOptimizationRange; ///< The path visibility optimization range. [Limit: > 0] - - /// How aggresive the agent manager should be at avoiding collisions with this agent. [Limit: >= 0] - float separationWeight; - - /// Flags that impact steering behavior. (See: #UpdateFlags) - unsigned char updateFlags; - - /// The index of the avoidance configuration to use for the agent. - /// [Limits: 0 <= value <= #DT_CROWD_MAX_OBSTAVOIDANCE_PARAMS] - unsigned char obstacleAvoidanceType; - - /// User defined data attached to the agent. - void* userData; -}; - -enum MoveRequestState -{ - DT_CROWDAGENT_TARGET_NONE = 0, - DT_CROWDAGENT_TARGET_FAILED, - DT_CROWDAGENT_TARGET_VALID, - DT_CROWDAGENT_TARGET_REQUESTING, - DT_CROWDAGENT_TARGET_WAITING_FOR_QUEUE, - DT_CROWDAGENT_TARGET_WAITING_FOR_PATH, - DT_CROWDAGENT_TARGET_VELOCITY, -}; - -/// Represents an agent managed by a #dtCrowd object. -/// @ingroup crowd -struct dtCrowdAgent -{ - /// 1 if the agent is active, or 0 if the agent is in an unused slot in the agent pool. - unsigned char active; - - /// The type of mesh polygon the agent is traversing. (See: #CrowdAgentState) - unsigned char state; - - /// The path corridor the agent is using. - dtPathCorridor corridor; - - /// The local boundary data for the agent. - dtLocalBoundary boundary; - - /// Time since the agent's path corridor was optimized. - float topologyOptTime; - - /// The known neighbors of the agent. - dtCrowdNeighbour neis[DT_CROWDAGENT_MAX_NEIGHBOURS]; - - /// The number of neighbors. - int nneis; - - /// The desired speed. - float desiredSpeed; - - float npos[3]; ///< The current agent position. [(x, y, z)] - float disp[3]; - float dvel[3]; ///< The desired velocity of the agent. [(x, y, z)] - float nvel[3]; - float vel[3]; ///< The actual velocity of the agent. [(x, y, z)] - - /// The agent's configuration parameters. - dtCrowdAgentParams params; - - /// The local path corridor corners for the agent. (Staight path.) [(x, y, z) * #ncorners] - float cornerVerts[DT_CROWDAGENT_MAX_CORNERS*3]; - - /// The local path corridor corner flags. (See: #dtStraightPathFlags) [(flags) * #ncorners] - unsigned char cornerFlags[DT_CROWDAGENT_MAX_CORNERS]; - - /// The reference id of the polygon being entered at the corner. [(polyRef) * #ncorners] - dtPolyRef cornerPolys[DT_CROWDAGENT_MAX_CORNERS]; - - /// The number of corners. - int ncorners; - - unsigned char targetState; ///< State of the movement request. - dtPolyRef targetRef; ///< Target polyref of the movement request. - float targetPos[3]; ///< Target position of the movement request (or velocity in case of DT_CROWDAGENT_TARGET_VELOCITY). - dtPathQueueRef targetPathqRef; ///< Path finder ref. - bool targetReplan; ///< Flag indicating that the current path is being replanned. - float targetReplanTime; ///