├── ProjectSettings
├── ProjectVersion.txt
├── ClusterInputManager.asset
├── PresetManager.asset
├── EditorBuildSettings.asset
├── XRSettings.asset
├── VersionControlSettings.asset
├── TimeManager.asset
├── VFXManager.asset
├── AudioManager.asset
├── TagManager.asset
├── EditorSettings.asset
├── UnityConnectSettings.asset
├── PackageManagerSettings.asset
├── DynamicsManager.asset
├── NavMeshAreas.asset
├── Physics2DSettings.asset
├── GraphicsSettings.asset
├── InputManager.asset
└── QualitySettings.asset
├── Assets
├── Cyclone.meta
├── CommonUnity.meta
├── Cyclone
│ ├── Core.meta
│ ├── Particles.meta
│ ├── Rigid.meta
│ ├── Rigid
│ │ ├── Forces.meta
│ │ ├── Collisions.meta
│ │ ├── Constraints.meta
│ │ ├── RigidBody.cs.meta
│ │ ├── RigidBodyEngine.cs.meta
│ │ ├── Forces
│ │ │ ├── RigidForce.cs.meta
│ │ │ ├── RigidForceArea.cs.meta
│ │ │ ├── RigidGravityForce.cs.meta
│ │ │ ├── RigidSpringForce.cs.meta
│ │ │ ├── RigidForceArea.cs
│ │ │ ├── RigidForce.cs
│ │ │ ├── RigidGravityForce.cs
│ │ │ └── RigidSpringForce.cs
│ │ ├── Collisions
│ │ │ ├── CollisionBox.cs.meta
│ │ │ ├── CollisionData.cs.meta
│ │ │ ├── CollisionPlane.cs.meta
│ │ │ ├── CollisionDetector.cs.meta
│ │ │ ├── CollisionPrimitive.cs.meta
│ │ │ ├── CollisionSphere.cs.meta
│ │ │ ├── IntersectionTests.cs.meta
│ │ │ ├── CollisionSphere.cs
│ │ │ ├── CollisionBox.cs
│ │ │ ├── CollisionPlane.cs
│ │ │ ├── CollisionPrimitive.cs
│ │ │ ├── CollisionData.cs
│ │ │ └── IntersectionTests.cs
│ │ ├── Constraints
│ │ │ ├── RidgeContact.cs.meta
│ │ │ ├── RigidConstraint.cs.meta
│ │ │ ├── CollisionConstraint.cs.meta
│ │ │ ├── RigidContactResolver.cs.meta
│ │ │ ├── RigidJointConstraint.cs.meta
│ │ │ ├── RigidConstraint.cs
│ │ │ ├── RigidJointConstraint.cs
│ │ │ ├── CollisionConstraint.cs
│ │ │ └── RigidContactResolver.cs
│ │ └── RigidBodyEngine.cs
│ ├── Particles
│ │ ├── Forces.meta
│ │ ├── Constraints.meta
│ │ ├── Particle.cs.meta
│ │ ├── ParticleEngine.cs.meta
│ │ ├── Forces
│ │ │ ├── ParticleForce.cs.meta
│ │ │ ├── ParticleDragForce.cs.meta
│ │ │ ├── ParticleForceArea.cs.meta
│ │ │ ├── ParticleSpringForce.cs.meta
│ │ │ ├── ParticleElasticForce.cs.meta
│ │ │ ├── ParticleGravityForce.cs.meta
│ │ │ ├── ParticleForceArea.cs
│ │ │ ├── ParticleForce.cs
│ │ │ ├── ParticleGravityForce.cs
│ │ │ ├── ParticleDragForce.cs
│ │ │ ├── ParticleSpringForce.cs
│ │ │ └── ParticleElasticForce.cs
│ │ ├── Constraints
│ │ │ ├── ParticleConstraint.cs.meta
│ │ │ ├── ParticleContact.cs.meta
│ │ │ ├── PlaneConstraint.cs.meta
│ │ │ ├── ParticleCableConstraint.cs.meta
│ │ │ ├── ParticleContactResolver.cs.meta
│ │ │ ├── ParticleRodConstraint.cs.meta
│ │ │ ├── ParticleConstraint.cs
│ │ │ ├── PlaneConstraint.cs
│ │ │ ├── ParticleCableConstraint.cs
│ │ │ ├── ParticleRodConstraint.cs
│ │ │ ├── ParticleContactResolver.cs
│ │ │ └── ParticleContact.cs
│ │ ├── Particle.cs
│ │ └── ParticleEngine.cs
│ └── Core
│ │ ├── DMath.cs.meta
│ │ ├── Matrix3.cs.meta
│ │ ├── Matrix4.cs.meta
│ │ ├── Quaternion.cs.meta
│ │ ├── Vector3d.cs.meta
│ │ ├── Quaternion.cs
│ │ ├── DMath.cs
│ │ ├── Matrix4.cs
│ │ └── Matrix3.cs
├── UnityTestScenes.meta
├── UnityTestScenes
│ ├── Scenes
│ │ ├── RigidTest.unity.meta
│ │ └── ParticleTest.unity.meta
│ ├── Scenes.meta
│ ├── Scripts.meta
│ └── Scripts
│ │ ├── RigidBox.cs.meta
│ │ ├── CollisionPlane.cs.meta
│ │ ├── MathExtensions.cs.meta
│ │ ├── ParticleRod.cs.meta
│ │ ├── ParticleSpring.cs.meta
│ │ ├── RigidSphere.cs.meta
│ │ ├── RigidPhysicsEngine.cs.meta
│ │ ├── ParticlePhysicsEngine.cs.meta
│ │ ├── CollisionPlane.cs
│ │ ├── ParticlePhysicsEngine.cs
│ │ ├── MathExtensions.cs
│ │ ├── RigidPhysicsEngine.cs
│ │ ├── RigidSphere.cs
│ │ ├── RigidBox.cs
│ │ ├── ParticleSpring.cs
│ │ └── ParticleRod.cs
└── CommonUnity
│ ├── Cameras.meta
│ ├── Drawing.meta
│ ├── Drawing
│ ├── BaseRenderer.cs.meta
│ ├── VextexRenderer.cs.meta
│ ├── SegmentRenderer.cs.meta
│ ├── BaseRenderer.cs
│ ├── VextexRenderer.cs
│ └── SegmentRenderer.cs
│ └── Cameras
│ ├── SimpleCameraController.cs.meta
│ └── SimpleCameraController.cs
├── README.md
├── LICENSE
├── .gitattributes
└── .gitignore
/ProjectSettings/ProjectVersion.txt:
--------------------------------------------------------------------------------
1 | m_EditorVersion: 2020.1.6f1
2 | m_EditorVersionWithRevision: 2020.1.6f1 (fc477ca6df10)
3 |
--------------------------------------------------------------------------------
/ProjectSettings/ClusterInputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!236 &1
4 | ClusterInputManager:
5 | m_ObjectHideFlags: 0
6 | m_Inputs: []
7 |
--------------------------------------------------------------------------------
/ProjectSettings/PresetManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1386491679 &1
4 | PresetManager:
5 | m_ObjectHideFlags: 0
6 | m_DefaultList: []
7 |
--------------------------------------------------------------------------------
/Assets/Cyclone.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e0d3096563f98264aa24df1520a2e643
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/CommonUnity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a51b948b600a5e845bfbbf8769d95921
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 74de1357ead1c3546a94f4c75031c8d6
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 03256bf897fd16d4d8b22688d2cc7944
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c3030cc44c893da4abccb2e3bc51293a
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a843e1952e00bf447a47aacbd54a5257
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scenes/RigidTest.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 500236e4f4768bf40bf17dee4a8c5978
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorBuildSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!1045 &1
4 | EditorBuildSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Scenes: []
8 | m_configObjects: {}
9 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Cameras.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b910f1ef0024e5241853b84a4b0fda2e
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Drawing.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: da173af6237ad3b4bb6d9ba9e64dd2a7
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 86cf8d717b4af474f8035be26d53503f
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scenes.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b1b95403cf711c34096b434367f6b3b4
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scenes/ParticleTest.unity.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 48f8feda1bedd7945a6fb0e126a217e9
3 | DefaultImporter:
4 | externalObjects: {}
5 | userData:
6 | assetBundleName:
7 | assetBundleVariant:
8 |
--------------------------------------------------------------------------------
/ProjectSettings/XRSettings.asset:
--------------------------------------------------------------------------------
1 | {
2 | "m_SettingKeys": [
3 | "VR Device Disabled",
4 | "VR Device User Alert"
5 | ],
6 | "m_SettingValues": [
7 | "False",
8 | "False"
9 | ]
10 | }
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b4b084e738be06440aca4577676f8834
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fb3f5991268b56d439a284f9f812e93c
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 120150dde02fea6449ab37006220ac64
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 23a4ef1660c4ddd4f9fdec4133ba5984
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 515f2489a6848c2489e577f6acd4c6fd
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/ProjectSettings/VersionControlSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!890905787 &1
4 | VersionControlSettings:
5 | m_ObjectHideFlags: 0
6 | m_Mode: Visible Meta Files
7 | m_CollabEditorSettings:
8 | inProgressEnabled: 1
9 |
--------------------------------------------------------------------------------
/ProjectSettings/TimeManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!5 &1
4 | TimeManager:
5 | m_ObjectHideFlags: 0
6 | Fixed Timestep: 0.02
7 | Maximum Allowed Timestep: 0.33333334
8 | m_TimeScale: 1
9 | Maximum Particle Timestep: 0.03
10 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/DMath.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a86099c31cbb72041a45d7dec3f4cb1d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/Matrix3.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3df2a6d748c86054d99559b54d876a5f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/Matrix4.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ab8f4871b2f80bb489985acc607e0683
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/Quaternion.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: f4a7b216f1ec4a14bbaa34c20f0acdc4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/Vector3d.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: cb4efd3fb205737478b2c77142aee19e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/RigidBody.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6bdf8590d028dcf48ac83151227ee8c0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Particle.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3a089280f746be041bfaefcee18da542
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/RigidBodyEngine.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3b8436c8c2be9fa4b94ba26244ab05d5
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Drawing/BaseRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2ee727f728c666844aa562a7d4069d8f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Drawing/VextexRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 51f9fa99b018b3642a0c6f6d5ab9e5df
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/ParticleEngine.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bd0db5cf58cfdbb45932863824560422
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bdcccf4146515f145975fc6594b79f1c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/RigidBox.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 37c37f89d10dc5a4d94eee148fc63ccf
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Drawing/SegmentRenderer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c640c95997cc21a438c60fef9bac06cd
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a67942514cd256d4aba1894356c7f2fe
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionBox.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 57bb3f7e7923c094aba6044d3108ecc5
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionData.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 41ec3d3a213d96f4d9d9fd9af936bb5c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionPlane.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9745db5df4412524a866f6f9b1314de4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/RidgeContact.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e4703b9a079e6134f89ca2c447f61987
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidForceArea.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e377d869fcaec594a95a31563c266caf
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidGravityForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bcd8eb788ef8f0b44bc303d96f6c8c02
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidSpringForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 699bd6c1592873540b0943ea86bb26ae
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/CollisionPlane.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 68a3c3f735fd80a4a9febd1fa2a75e3a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/MathExtensions.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: aea4976721edbdf479373dd0f12ce8f4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/ParticleRod.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 590ba1bac20ecb8439d3a49dde3ef523
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/ParticleSpring.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7a75735c6af91274a9b7a1bbd861fd1f
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/RigidSphere.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: ba137f3aa689b754dbfaebc8466738b8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Cameras/SimpleCameraController.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6d2223c8b8b0021418bdacd2ac82b8e6
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleDragForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: bb568f13cf415e04f8ff8c595605d87c
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleForceArea.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9403dfef7d62937429a6017c8b50d0b0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleSpringForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 863c88906fe883944948f469f3468a7e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionDetector.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 8486d955ade96da45818432b85a889a4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionPrimitive.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a7fd32e0b7d10e445960f3cae3acd066
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionSphere.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3eadb50b1276b1e46824ede749496fbb
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/IntersectionTests.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3a7599d0adb7f474382e9ac1992be7dc
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/RigidConstraint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eba4af340fb881e46a808f3ed2a7eee4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/RigidPhysicsEngine.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5c35f16c12354e8488e2d40f22d4b6b5
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleConstraint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 93789bc5226390247a0e9dd4f3e32e03
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleContact.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 48bcca9166ec1be43831be93aae05100
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/PlaneConstraint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 36b3108169456ca4bb3fd6b2dbf1c53e
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleElasticForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1692fad5ad90e14409be51ff070da053
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleGravityForce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a37ca47470d73d14eb1bca975d9d4774
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/CollisionConstraint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 89fdd984740e1d54182af7956a73c855
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/RigidContactResolver.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5cf29c7b2892fd7469e90c6ce6c60aa8
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/RigidJointConstraint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 50a21051baee33c438b4dba3581267f0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/ParticlePhysicsEngine.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 9d5e3a4e2c290644b87a312dd7cba50a
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/ProjectSettings/VFXManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!937362698 &1
4 | VFXManager:
5 | m_ObjectHideFlags: 0
6 | m_IndirectShader: {fileID: 0}
7 | m_CopyBufferShader: {fileID: 0}
8 | m_SortShader: {fileID: 0}
9 | m_RenderPipeSettingsPath:
10 | m_FixedTimeStep: 0.016666668
11 | m_MaxDeltaTime: 0.05
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleCableConstraint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 46432a5c91bce1f45ba62f4513a2b8f4
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleContactResolver.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 67d769851e45fc74c810551281ffcc80
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleRodConstraint.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5d0ffb5ed6cf6c54b8732afd5e183a76
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/ProjectSettings/AudioManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!11 &1
4 | AudioManager:
5 | m_ObjectHideFlags: 0
6 | m_Volume: 1
7 | Rolloff Scale: 1
8 | Doppler Factor: 1
9 | Default Speaker Mode: 2
10 | m_SampleRate: 0
11 | m_DSPBufferSize: 1024
12 | m_VirtualVoiceCount: 512
13 | m_RealVoiceCount: 32
14 | m_SpatializerPlugin:
15 | m_AmbisonicDecoderPlugin:
16 | m_DisableAudio: 0
17 | m_VirtualizeEffects: 1
18 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionSphere.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Rigid;
6 |
7 | namespace Cyclone.Rigid.Collisions
8 | {
9 | ///
10 | /// Represents a rigid body that can be treated as a sphere
11 | /// for collision detection.
12 | ///
13 | public class CollisionSphere : CollisionPrimitive
14 | {
15 | public double Radius;
16 |
17 | public CollisionSphere(double radius)
18 | {
19 | Radius = radius;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/ProjectSettings/TagManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!78 &1
4 | TagManager:
5 | serializedVersion: 2
6 | tags: []
7 | layers:
8 | - Default
9 | - TransparentFX
10 | - Ignore Raycast
11 | -
12 | - Water
13 | - UI
14 | -
15 | -
16 | -
17 | -
18 | -
19 | -
20 | -
21 | -
22 | -
23 | -
24 | -
25 | -
26 | -
27 | -
28 | -
29 | -
30 | -
31 | -
32 | -
33 | -
34 | -
35 | -
36 | -
37 | -
38 | -
39 | -
40 | m_SortingLayers:
41 | - name: Default
42 | uniqueID: 0
43 | locked: 0
44 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidForceArea.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Cyclone.Rigid.Forces
6 | {
7 | ///
8 | /// A force that applies to any body that enters the forces area.
9 | ///
10 | public abstract class RigidForceArea
11 | {
12 | ///
13 | /// Overload this in implementations of the interface to calculate
14 | /// and update the force applied to the body.
15 | ///
16 | public abstract void UpdateForce(RigidBody body, double dt);
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleForceArea.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Cyclone.Particles.Forces
6 | {
7 | ///
8 | /// A force that applies to any partice that enters the forces area.
9 | ///
10 | public abstract class ParticleForceArea
11 | {
12 | ///
13 | /// Overload this in implementations of the interface to calculate
14 | /// and update the force applied to the particle.
15 | ///
16 | public abstract void UpdateForce(Particle particle, double dt);
17 |
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/CollisionPlane.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Cyclone.Core;
6 |
7 | using PLANE = Cyclone.Rigid.Collisions.CollisionPlane;
8 |
9 | namespace CycloneUnityTestScenes
10 | {
11 | public class CollisionPlane : MonoBehaviour
12 | {
13 |
14 | private PLANE m_plane;
15 |
16 | void Start()
17 | {
18 | double y = transform.position.y;
19 |
20 | m_plane = new PLANE(Vector3d.UnitY, y);
21 |
22 | RigidPhysicsEngine.Instance.Collisions.Planes.Add(m_plane);
23 | }
24 |
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Rigid;
6 |
7 | namespace Cyclone.Rigid.Forces
8 | {
9 |
10 | ///
11 | /// A force that applies to one or more bodies
12 | /// during the duration of the simulation.
13 | ///
14 | public abstract class RigidForce
15 | {
16 | ///
17 | /// Overload this in implementations of the interface to calculate
18 | /// and update the force applied to the bodies.
19 | ///
20 | public abstract void UpdateForce(double dt);
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Forces
8 | {
9 |
10 | ///
11 | /// A force that applies to one or more particles
12 | /// during the duration of the simulation.
13 | ///
14 | public abstract class ParticleForce
15 | {
16 | ///
17 | /// Overload this in implementations of the interface to calculate
18 | /// and update the force applied to the particles.
19 | ///
20 | public abstract void UpdateForce(double dt);
21 |
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Collisions
7 | {
8 | ///
9 | /// Represents a rigid body that can be treated as an aligned bounding
10 | /// box for collision detection.
11 | ///
12 | public class CollisionBox : CollisionPrimitive
13 | {
14 | ///
15 | /// Holds the half-sizes of the box along each of its local axes.
16 | ///
17 | public Vector3d HalfSize;
18 |
19 | public CollisionBox(double halfSize)
20 | {
21 | HalfSize = new Vector3d(halfSize);
22 | }
23 |
24 | public CollisionBox(Vector3d halfSize)
25 | {
26 | HalfSize = halfSize;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ProjectSettings/EditorSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!159 &1
4 | EditorSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 7
7 | m_ExternalVersionControlSupport: Hidden Meta Files
8 | m_SerializationMode: 2
9 | m_LineEndingsForNewScripts: 2
10 | m_DefaultBehaviorMode: 0
11 | m_PrefabRegularEnvironment: {fileID: 0}
12 | m_PrefabUIEnvironment: {fileID: 0}
13 | m_SpritePackerMode: 0
14 | m_SpritePackerPaddingPower: 1
15 | m_EtcTextureCompressorBehavior: 1
16 | m_EtcTextureFastCompressor: 1
17 | m_EtcTextureNormalCompressor: 2
18 | m_EtcTextureBestCompressor: 4
19 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd;asmdef;rsp
20 | m_ProjectGenerationRootNamespace:
21 | m_CollabEditorSettings:
22 | inProgressEnabled: 1
23 | m_EnableTextureStreamingInEditMode: 1
24 | m_EnableTextureStreamingInPlayMode: 1
25 | m_AsyncShaderCompilation: 1
26 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/RigidConstraint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Constraints
7 | {
8 |
9 | ///
10 | /// This is the basic polymorphic interface for contact generators
11 | /// applying to rigid bodies.
12 | ///
13 | public abstract class RigidConstraint
14 | {
15 | ///
16 | /// Fills the given contact structure with the generated
17 | /// contact. The contact pointer should point to the first
18 | /// available contact in a contact array, where limit is the
19 | /// maximum number of contacts in the array that can be written
20 | /// to. The method returns the number of contacts that have
21 | /// been written.
22 | ///
23 | public abstract int AddContact(IList bodies, IList contacts, int next);
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionPlane.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Collisions
7 | {
8 | ///
9 | /// The plane is not a primitive: it doesn't represent another
10 | /// rigid body.It is used for contacts with the immovable
11 | /// world geometry.
12 | ///
13 | public class CollisionPlane
14 | {
15 | ///
16 | /// The plane normal
17 | ///
18 | public Vector3d Direction;
19 |
20 | ///
21 | /// The distance of the plane from the origin.
22 | ///
23 | public double Offset;
24 |
25 | ///
26 | ///
27 | ///
28 | public CollisionPlane(Vector3d direction, double offset)
29 | {
30 | Direction = direction;
31 | Offset = offset;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleGravityForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Forces
8 | {
9 | public class ParticleGravityForce : ParticleForceArea
10 | {
11 |
12 | private Vector3d m_gravity;
13 |
14 | public ParticleGravityForce(double gravity)
15 | {
16 | m_gravity = new Vector3d(0, gravity, 0);
17 | }
18 |
19 | public ParticleGravityForce(Vector3d gravity)
20 | {
21 | m_gravity = gravity;
22 | }
23 |
24 | public override void UpdateForce(Particle particle, double dt)
25 | {
26 | // Check that we do not have infinite mass
27 | if (!particle.HasFiniteMass) return;
28 |
29 | // Apply the mass-scaled force to the particle
30 | particle.AddForce(m_gravity * particle.GetMass());
31 | }
32 |
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleConstraint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Constraints
8 | {
9 | ///
10 | /// This is the basic polymorphic interface for contact generators
11 | /// applying to particles.
12 | ///
13 | public abstract class ParticleConstraint
14 | {
15 | ///
16 | /// Fills the given contact structure with the generated
17 | /// contact.The contact pointer should point to the first
18 | /// available contact in a contact array, where limit is the
19 | /// maximum number of contacts in the array that can be written
20 | /// to.The method returns the number of contacts that have
21 | /// been written.
22 | ///
23 | public abstract int AddContact(IList particles, IList contacts, int next);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/ProjectSettings/UnityConnectSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!310 &1
4 | UnityConnectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 1
7 | m_Enabled: 0
8 | m_TestMode: 0
9 | m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
10 | m_EventUrl: https://cdp.cloud.unity3d.com/v1/events
11 | m_ConfigUrl: https://config.uca.cloud.unity3d.com
12 | m_TestInitMode: 0
13 | CrashReportingSettings:
14 | m_EventUrl: https://perf-events.cloud.unity3d.com
15 | m_Enabled: 0
16 | m_LogBufferSize: 10
17 | m_CaptureEditorExceptions: 1
18 | UnityPurchasingSettings:
19 | m_Enabled: 0
20 | m_TestMode: 0
21 | UnityAnalyticsSettings:
22 | m_Enabled: 0
23 | m_TestMode: 0
24 | m_InitializeOnStartup: 1
25 | UnityAdsSettings:
26 | m_Enabled: 0
27 | m_InitializeOnStartup: 1
28 | m_TestMode: 0
29 | m_IosGameId:
30 | m_AndroidGameId:
31 | m_GameIds: {}
32 | m_GameId:
33 | PerformanceReportingSettings:
34 | m_Enabled: 0
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CyclonePhysicsEngine
2 | C# port of the [Cylcone physics engine](https://github.com/idmillington/cyclone-physics) based on the book Game Physics Engine Design.
3 |
4 | I have made some small changes and restructured the code a little.
5 |
6 | The projects uses Unity to create a few test scenes but the code (all the scripts in the Cyclone folder) is not connected to Unity in any way and can be used as a standonle project if required.
7 |
8 | List of physics projects
9 |
10 | [Position-Based-Dynamics](https://github.com/Scrawk/Position-Based-Dynamics)\
11 | [PBD-Fluid-in-Unity](https://github.com/Scrawk/PBD-Fluid-in-Unity)\
12 | [GPU-GEMS-NBody-Simulation](https://github.com/Scrawk/GPU-GEMS-NBody-Simulation)\
13 | [GPU-GEMS-2D-Fluid-Simulation](https://github.com/Scrawk/GPU-GEMS-2D-Fluid-Simulation)\
14 | [GPU-GEMS-3D-Fluid-Simulation](https://github.com/Scrawk/GPU-GEMS-3D-Fluid-Simulation)\
15 | [CyclonePhysicsEngine](https://github.com/Scrawk/CyclonePhysicsEngine)\
16 | [2D-Deformable-body-in-Unity](https://github.com/Scrawk/2D-Deformable-body-in-Unity)
17 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/ParticlePhysicsEngine.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Cyclone.Particles;
6 | using Cyclone.Particles.Forces;
7 | using Cyclone.Particles.Constraints;
8 |
9 | namespace CycloneUnityTestScenes
10 | {
11 |
12 | public class ParticlePhysicsEngine : MonoBehaviour
13 | {
14 | public int iterations = 0;
15 |
16 | public int maxContacts = 100;
17 |
18 | public static ParticleEngine Instance { get; private set; }
19 |
20 | private void Awake()
21 | {
22 | Instance = new ParticleEngine(maxContacts);
23 | Instance.Resolver.Iterations = iterations;
24 |
25 | Instance.ForceAreas.Add(new ParticleGravityForce(-9.81));
26 |
27 | //Instance.Constraints.Add(new PlaneConstraint(-2));
28 | }
29 |
30 | private void FixedUpdate()
31 | {
32 | double dt = Time.fixedDeltaTime;
33 |
34 | Instance.StartFrame();
35 | Instance.RunPhysics(dt);
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleDragForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Forces
8 | {
9 | public class ParticleDragForce : ParticleForceArea
10 | {
11 | //Holds the velocity drag coeffificent.
12 | private double k1;
13 |
14 | // Holds the velocity squared drag coeffificent.
15 | private double k2;
16 |
17 | public ParticleDragForce(double k1, double k2)
18 | {
19 | this.k1 = k1;
20 | this.k2 = k2;
21 | }
22 |
23 | public override void UpdateForce(Particle particle, double dt)
24 | {
25 | Vector3d force = particle.Velocity;
26 |
27 | // Calculate the total drag coefficient
28 | double dragCoeff = force.Magnitude;
29 | dragCoeff = k1 * dragCoeff + k2 * dragCoeff * dragCoeff;
30 |
31 | // Calculate the final force and apply it
32 | force.Normalize();
33 | force *= -dragCoeff;
34 | particle.AddForce(force);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/MathExtensions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Cyclone.Core;
6 | using QUATERNION = Cyclone.Core.Quaternion;
7 |
8 | namespace UnityEngine
9 | {
10 |
11 | public static class MathExtension
12 | {
13 |
14 | public static QUATERNION ToQuaternion(this Quaternion q)
15 | {
16 | return new QUATERNION(q.w, q.x, q.y, q.z);
17 | }
18 |
19 | public static Quaternion ToQuaternion(this QUATERNION q)
20 | {
21 | return new Quaternion((float)q.i, (float)q.j, (float)q.k, (float)q.r);
22 | }
23 |
24 | public static Vector3 ToVector3(this Vector3d v)
25 | {
26 | return new Vector3((float)v.x, (float)v.y, (float)v.z);
27 | }
28 |
29 | public static Vector4 ToVector4(this Vector3d v)
30 | {
31 | return new Vector4((float)v.x, (float)v.y, (float)v.z, 1);
32 | }
33 |
34 | public static Vector3d ToVector3d(this Vector3 v)
35 | {
36 | return new Vector3d(v.x, v.y, v.z);
37 | }
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/ProjectSettings/PackageManagerSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!114 &1
4 | MonoBehaviour:
5 | m_ObjectHideFlags: 61
6 | m_CorrespondingSourceObject: {fileID: 0}
7 | m_PrefabInstance: {fileID: 0}
8 | m_PrefabAsset: {fileID: 0}
9 | m_GameObject: {fileID: 0}
10 | m_Enabled: 1
11 | m_EditorHideFlags: 0
12 | m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0}
13 | m_Name:
14 | m_EditorClassIdentifier:
15 | m_EnablePreviewPackages: 0
16 | m_EnablePackageDependencies: 0
17 | m_AdvancedSettingsExpanded: 1
18 | m_ScopedRegistriesSettingsExpanded: 1
19 | oneTimeWarningShown: 0
20 | m_Registries:
21 | - m_Id: main
22 | m_Name:
23 | m_Url: https://packages.unity.com
24 | m_Scopes: []
25 | m_IsDefault: 1
26 | m_Capabilities: 7
27 | m_UserSelectedRegistryName:
28 | m_UserAddingNewScopedRegistry: 0
29 | m_RegistryInfoDraft:
30 | m_ErrorMessage:
31 | m_Original:
32 | m_Id:
33 | m_Name:
34 | m_Url:
35 | m_Scopes: []
36 | m_IsDefault: 0
37 | m_Capabilities: 0
38 | m_Modified: 0
39 | m_Name:
40 | m_Url:
41 | m_Scopes:
42 | -
43 | m_SelectedScopeIndex: 0
44 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidGravityForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Forces
7 | {
8 |
9 | ///
10 | /// A force generator that applies a gravitational force. One instance
11 | /// can be used for multiple rigid bodies.
12 | ///
13 | public class RigidGravityForce : RigidForceArea
14 | {
15 |
16 | ///
17 | /// Holds the acceleration due to gravity.
18 | ///
19 | Vector3d m_gravity;
20 |
21 | public RigidGravityForce(double gravity)
22 | {
23 | m_gravity = new Vector3d(0, gravity, 0);
24 | }
25 |
26 | public RigidGravityForce(Vector3d gravity)
27 | {
28 | m_gravity = gravity;
29 | }
30 |
31 | ///
32 | /// Applies the gravitational force to the given rigid body.
33 | ///
34 | public override void UpdateForce(RigidBody body, double dt)
35 | {
36 | // Check that we do not have infinite mass
37 | if (body.HasInfiniteMass) return;
38 |
39 | // Apply the mass-scaled force to the body
40 | body.AddForce(m_gravity * body.GetMass());
41 | }
42 | }
43 |
44 | }
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/RigidPhysicsEngine.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Cyclone.Rigid;
6 | using Cyclone.Rigid.Forces;
7 |
8 | namespace CycloneUnityTestScenes
9 | {
10 |
11 | public class RigidPhysicsEngine : MonoBehaviour
12 | {
13 | public int iterations = 0;
14 |
15 | public int maxContacts = 100;
16 |
17 | public double epsilon = 0.01;
18 |
19 | public static RigidBodyEngine Instance { get; private set; }
20 |
21 | private void Awake()
22 | {
23 | Instance = new RigidBodyEngine(maxContacts);
24 | Instance.Resolver.PositionIterations = iterations;
25 | Instance.Resolver.VelocityIterations = iterations;
26 | Instance.Resolver.PositionEpsilon = epsilon;
27 | Instance.Resolver.VelocityEpsilon = epsilon;
28 | Instance.Collisions.Restitution = 0;
29 | Instance.Collisions.Friction = 0.1;
30 |
31 | Instance.ForceAreas.Add(new RigidGravityForce(-9.81));
32 | }
33 |
34 | private void FixedUpdate()
35 | {
36 | double dt = Time.fixedDeltaTime;
37 |
38 | Instance.StartFrame();
39 | Instance.RunPhysics(dt);
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/ProjectSettings/DynamicsManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!55 &1
4 | PhysicsManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 11
7 | m_Gravity: {x: 0, y: -9.81, z: 0}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_BounceThreshold: 2
10 | m_SleepThreshold: 0.005
11 | m_DefaultContactOffset: 0.01
12 | m_DefaultSolverIterations: 6
13 | m_DefaultSolverVelocityIterations: 1
14 | m_QueriesHitBackfaces: 0
15 | m_QueriesHitTriggers: 1
16 | m_EnableAdaptiveForce: 0
17 | m_ClothInterCollisionDistance: 0
18 | m_ClothInterCollisionStiffness: 0
19 | m_ContactsGeneration: 1
20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
21 | m_AutoSimulation: 1
22 | m_AutoSyncTransforms: 0
23 | m_ReuseCollisionCallbacks: 1
24 | m_ClothInterCollisionSettingsToggle: 0
25 | m_ContactPairsMode: 0
26 | m_BroadphaseType: 0
27 | m_WorldBounds:
28 | m_Center: {x: 0, y: 0, z: 0}
29 | m_Extent: {x: 250, y: 250, z: 250}
30 | m_WorldSubdivisions: 8
31 | m_FrictionType: 0
32 | m_EnableEnhancedDeterminism: 0
33 | m_EnableUnifiedHeightmaps: 1
34 | m_DefaultMaxAngluarSpeed: 7
35 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/PlaneConstraint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Constraints
8 | {
9 | ///
10 | /// A contact generator that takes an STL vector of particle pointers and
11 | /// collides them against the ground.
12 | ///
13 | public class PlaneConstraint : ParticleConstraint
14 | {
15 |
16 | public Vector3d m_origin;
17 |
18 | public PlaneConstraint(double height)
19 | {
20 | m_origin = new Vector3d(0, height, 0);
21 | }
22 |
23 | public override int AddContact(IList particles, IList contacts, int next)
24 | {
25 | int count = 0;
26 | foreach(var p in particles)
27 | {
28 | double y = p.Position.y - m_origin.y;
29 | if (y < 0.0)
30 | {
31 | var contact = contacts[next];
32 |
33 | contact.ContactNormal = Vector3d.UnitY;
34 | contact.Particles[0] = p;
35 | contact.Particles[1] = null;
36 | contact.Penetration = -y;
37 | contact.Restitution = 0.2;
38 | next++;
39 | count++;
40 | }
41 |
42 | if (count >= contacts.Count) return count;
43 | }
44 |
45 | return count;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/RigidSphere.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Cyclone.Core;
6 | using Cyclone.Rigid;
7 | using Cyclone.Rigid.Constraints;
8 | using Cyclone.Rigid.Collisions;
9 |
10 | namespace CycloneUnityTestScenes
11 | {
12 |
13 | public class RigidSphere : MonoBehaviour
14 | {
15 | public double mass = 1;
16 |
17 | public double damping = 0.9;
18 |
19 | private RigidBody m_body;
20 |
21 | void Start()
22 | {
23 | var pos = transform.position.ToVector3d();
24 | var scale = transform.localScale.y * 0.5;
25 | var rot = transform.rotation.ToQuaternion();
26 |
27 | m_body = new RigidBody();
28 | m_body.Position = pos;
29 | m_body.Orientation = rot;
30 | m_body.LinearDamping = damping;
31 | m_body.AngularDamping = damping;
32 | m_body.SetMass(mass);
33 | m_body.SetAwake(true);
34 | m_body.SetCanSleep(true);
35 |
36 | var shape = new CollisionSphere(scale);
37 | shape.Body = m_body;
38 |
39 | RigidPhysicsEngine.Instance.Bodies.Add(m_body);
40 | RigidPhysicsEngine.Instance.Collisions.Primatives.Add(shape);
41 | }
42 |
43 | private void Update()
44 | {
45 | transform.position = m_body.Position.ToVector3();
46 | transform.rotation = m_body.Orientation.ToQuaternion();
47 | }
48 |
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/RigidBox.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Cyclone.Core;
6 | using Cyclone.Rigid;
7 | using Cyclone.Rigid.Constraints;
8 | using Cyclone.Rigid.Collisions;
9 |
10 | namespace CycloneUnityTestScenes
11 | {
12 |
13 | public class RigidBox : MonoBehaviour
14 | {
15 | public double mass = 1;
16 |
17 | public double damping = 0.9;
18 |
19 | private RigidBody m_body;
20 |
21 | void Start()
22 | {
23 | var pos = transform.position.ToVector3d();
24 | var scale = transform.localScale.ToVector3d() * 0.5;
25 | var rot = transform.rotation.ToQuaternion();
26 |
27 | m_body = new RigidBody();
28 | m_body.Position = pos;
29 | m_body.Orientation = rot;
30 | m_body.LinearDamping = damping;
31 | m_body.AngularDamping = damping;
32 | m_body.SetMass(mass);
33 | m_body.SetAwake(true);
34 | m_body.SetCanSleep(true);
35 |
36 | var shape = new CollisionBox(scale);
37 | shape.Body = m_body;
38 |
39 | RigidPhysicsEngine.Instance.Bodies.Add(m_body);
40 | RigidPhysicsEngine.Instance.Collisions.Primatives.Add(shape);
41 | }
42 |
43 | private void Update()
44 | {
45 | transform.position = m_body.Position.ToVector3();
46 | transform.rotation = m_body.Orientation.ToQuaternion();
47 | }
48 |
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/ProjectSettings/NavMeshAreas.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!126 &1
4 | NavMeshProjectSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | areas:
8 | - name: Walkable
9 | cost: 1
10 | - name: Not Walkable
11 | cost: 1
12 | - name: Jump
13 | cost: 2
14 | - name:
15 | cost: 1
16 | - name:
17 | cost: 1
18 | - name:
19 | cost: 1
20 | - name:
21 | cost: 1
22 | - name:
23 | cost: 1
24 | - name:
25 | cost: 1
26 | - name:
27 | cost: 1
28 | - name:
29 | cost: 1
30 | - name:
31 | cost: 1
32 | - name:
33 | cost: 1
34 | - name:
35 | cost: 1
36 | - name:
37 | cost: 1
38 | - name:
39 | cost: 1
40 | - name:
41 | cost: 1
42 | - name:
43 | cost: 1
44 | - name:
45 | cost: 1
46 | - name:
47 | cost: 1
48 | - name:
49 | cost: 1
50 | - name:
51 | cost: 1
52 | - name:
53 | cost: 1
54 | - name:
55 | cost: 1
56 | - name:
57 | cost: 1
58 | - name:
59 | cost: 1
60 | - name:
61 | cost: 1
62 | - name:
63 | cost: 1
64 | - name:
65 | cost: 1
66 | - name:
67 | cost: 1
68 | - name:
69 | cost: 1
70 | - name:
71 | cost: 1
72 | m_LastAgentTypeID: -887442657
73 | m_Settings:
74 | - serializedVersion: 2
75 | agentTypeID: 0
76 | agentRadius: 0.5
77 | agentHeight: 2
78 | agentSlope: 45
79 | agentClimb: 0.75
80 | ledgeDropHeight: 0
81 | maxJumpAcrossDistance: 0
82 | minRegionArea: 2
83 | manualCellSize: 0
84 | cellSize: 0.16666667
85 | manualTileSize: 0
86 | tileSize: 256
87 | accuratePlacement: 0
88 | debug:
89 | m_Flags: 0
90 | m_SettingNames:
91 | - Humanoid
92 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionPrimitive.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Collisions
7 | {
8 | ///
9 | /// Represents a primitive to detect collisions against.
10 | ///
11 | public abstract class CollisionPrimitive
12 | {
13 |
14 | ///
15 | /// The rigid body that is represented by this primitive.
16 | ///
17 | public RigidBody Body;
18 |
19 | ///
20 | /// The offset of this primitive from the given rigid body.
21 | ///
22 | //public Matrix4 Offset;
23 |
24 | ///
25 | /// The resultant transform of the primitive. This is
26 | /// calculated by combining the offset of the primitive
27 | /// with the transform of the rigid body.
28 | ///
29 | public Matrix4 Transform;
30 |
31 | ///
32 | ///
33 | ///
34 | public CollisionPrimitive()
35 | {
36 | Transform = Matrix4.Identity;
37 | }
38 |
39 | ///
40 | /// Calculates the internals for the primitive.
41 | ///
42 | public void CalculateInternals()
43 | {
44 | Transform = Body.Transform /* * Offset*/ ;
45 | }
46 |
47 | ///
48 | /// This is a convenience function to allow access to the
49 | /// axis vectors in the transform for this primitive.
50 | ///
51 | public Vector3d GetAxis(int index)
52 | {
53 | return Transform.GetAxisVector(index);
54 | }
55 |
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleSpringForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Forces
8 | {
9 | public class ParticleSpringForce : ParticleForce
10 | {
11 | ///
12 | /// The particle at the other end of the spring.
13 | ///
14 | private Particle m_particleA, m_particleB;
15 |
16 | ///
17 | /// Holds the sprint constant.
18 | ///
19 | private double m_springConstant;
20 |
21 | ///
22 | /// Holds the rest length of the spring.
23 | ///
24 | private double m_restLength;
25 |
26 | public ParticleSpringForce(Particle a, Particle b, double springConstant, double restLength)
27 | {
28 | m_particleA = a;
29 | m_particleB = b;
30 | m_springConstant = springConstant;
31 | m_restLength = restLength;
32 | }
33 |
34 | public override void UpdateForce(double dt)
35 | {
36 | UpdateForce(m_particleA, m_particleB);
37 | UpdateForce(m_particleB, m_particleA);
38 | }
39 |
40 | private void UpdateForce(Particle particle, Particle other)
41 | {
42 | if (particle.HasInfiniteMass) return;
43 |
44 | // Calculate the vector of the spring
45 | Vector3d force = particle.Position - other.Position;
46 |
47 | // Calculate the magnitude of the force
48 | double magnitude = force.Magnitude;
49 | // Calculate the magnitude of the force
50 | magnitude = (m_restLength - magnitude) * m_springConstant;
51 |
52 | // Calculate the final force and apply it
53 | force.Normalize();
54 | force *= magnitude;
55 | particle.AddForce(force);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Forces/ParticleElasticForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Forces
8 | {
9 | public class ParticleElasticForce : ParticleForce
10 | {
11 | ///
12 | /// The particle at the other end of the spring.
13 | ///
14 | private Particle m_particleA, m_particleB;
15 |
16 | ///
17 | /// Holds the sprint constant.
18 | ///
19 | private double m_springConstant;
20 |
21 | ///
22 | /// Holds the rest length of the spring.
23 | ///
24 | private double m_restLength;
25 |
26 | public ParticleElasticForce(Particle a, Particle b, double springConstant, double restLength)
27 | {
28 | m_particleA = a;
29 | m_particleB = b;
30 | m_springConstant = springConstant;
31 | m_restLength = restLength;
32 | }
33 |
34 | public override void UpdateForce(double dt)
35 | {
36 | UpdateForce(m_particleA, m_particleB);
37 | UpdateForce(m_particleB, m_particleA);
38 | }
39 |
40 | private void UpdateForce(Particle particle, Particle other)
41 | {
42 | if (particle.HasInfiniteMass) return;
43 |
44 | // Calculate the vector of the spring
45 | Vector3d force = particle.Position - other.Position;
46 |
47 | // Calculate the magnitude of the force
48 | double magnitude = force.Magnitude;
49 | if (magnitude <= m_restLength) return;
50 |
51 | // Calculate the magnitude of the force
52 | magnitude = (m_restLength - magnitude) * m_springConstant;
53 |
54 | // Calculate the final force and apply it
55 | force.Normalize();
56 | force *= magnitude;
57 | particle.AddForce(force);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/ProjectSettings/Physics2DSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!19 &1
4 | Physics2DSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 4
7 | m_Gravity: {x: 0, y: -9.81}
8 | m_DefaultMaterial: {fileID: 0}
9 | m_VelocityIterations: 8
10 | m_PositionIterations: 3
11 | m_VelocityThreshold: 1
12 | m_MaxLinearCorrection: 0.2
13 | m_MaxAngularCorrection: 8
14 | m_MaxTranslationSpeed: 100
15 | m_MaxRotationSpeed: 360
16 | m_BaumgarteScale: 0.2
17 | m_BaumgarteTimeOfImpactScale: 0.75
18 | m_TimeToSleep: 0.5
19 | m_LinearSleepTolerance: 0.01
20 | m_AngularSleepTolerance: 2
21 | m_DefaultContactOffset: 0.01
22 | m_JobOptions:
23 | serializedVersion: 2
24 | useMultithreading: 0
25 | useConsistencySorting: 0
26 | m_InterpolationPosesPerJob: 100
27 | m_NewContactsPerJob: 30
28 | m_CollideContactsPerJob: 100
29 | m_ClearFlagsPerJob: 200
30 | m_ClearBodyForcesPerJob: 200
31 | m_SyncDiscreteFixturesPerJob: 50
32 | m_SyncContinuousFixturesPerJob: 50
33 | m_FindNearestContactsPerJob: 100
34 | m_UpdateTriggerContactsPerJob: 100
35 | m_IslandSolverCostThreshold: 100
36 | m_IslandSolverBodyCostScale: 1
37 | m_IslandSolverContactCostScale: 10
38 | m_IslandSolverJointCostScale: 10
39 | m_IslandSolverBodiesPerJob: 50
40 | m_IslandSolverContactsPerJob: 50
41 | m_AutoSimulation: 1
42 | m_QueriesHitTriggers: 1
43 | m_QueriesStartInColliders: 1
44 | m_CallbacksOnDisable: 1
45 | m_ReuseCollisionCallbacks: 1
46 | m_AutoSyncTransforms: 0
47 | m_AlwaysShowColliders: 0
48 | m_ShowColliderSleep: 1
49 | m_ShowColliderContacts: 0
50 | m_ShowColliderAABB: 0
51 | m_ContactArrowScale: 0.2
52 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412}
53 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432}
54 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745}
55 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804}
56 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
57 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2003-2009 Ian Millington
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
23 | MIT License
24 |
25 | Copyright (c) 2019 Justin
26 |
27 | Permission is hereby granted, free of charge, to any person obtaining a copy
28 | of this software and associated documentation files (the "Software"), to deal
29 | in the Software without restriction, including without limitation the rights
30 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31 | copies of the Software, and to permit persons to whom the Software is
32 | furnished to do so, subject to the following conditions:
33 |
34 | The above copyright notice and this permission notice shall be included in all
35 | copies or substantial portions of the Software.
36 |
37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
40 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
43 | SOFTWARE.
44 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleCableConstraint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Particles.Constraints
7 | {
8 |
9 | ///
10 | /// Cables link a pair of particles, generating a contact if they
11 | /// stray too far apart.
12 | ///
13 | public class ParticleCableConstraint : ParticleConstraint
14 | {
15 |
16 | ///
17 | /// The particle at the other end of the cable.
18 | ///
19 | private Particle m_particleA, m_particleB;
20 |
21 | ///
22 | /// Holds the maximum length of the cable.
23 | ///
24 | private double m_maxLength;
25 |
26 | ///
27 | /// Holds the restitution (bounciness) of the cable.
28 | ///
29 | private double m_restitution;
30 |
31 | public ParticleCableConstraint(Particle a, Particle b, double maxLength, double restitution = 0)
32 | {
33 | m_particleA = a;
34 | m_particleB = b;
35 | m_maxLength = maxLength;
36 | m_restitution = restitution;
37 | }
38 |
39 | ///
40 | /// Fills the given contact structure with the contact needed
41 | /// to keep the cable from over-extending.
42 | ///
43 | public override int AddContact(IList particles, IList contacts, int next)
44 | {
45 | // Find the length of the cable
46 | double length = Vector3d.Distance(m_particleA.Position, m_particleB.Position);
47 |
48 | // Check if we're over-extended
49 | if (length < m_maxLength) return 0;
50 |
51 | var contact = contacts[next];
52 |
53 | // Otherwise return the contact
54 | contact.Particles[0] = m_particleA;
55 | contact.Particles[1] = m_particleB;
56 |
57 | // Calculate the normal
58 | Vector3d normal = m_particleB.Position - m_particleA.Position;
59 | normal.Normalize();
60 | contact.ContactNormal = normal;
61 |
62 | contact.Penetration = length - m_maxLength;
63 | contact.Restitution = m_restitution;
64 |
65 | return 1;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/ParticleSpring.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Common.Unity.Drawing;
6 | using Cyclone.Core;
7 | using Cyclone.Particles;
8 | using Cyclone.Particles.Forces;
9 | using Cyclone.Particles.Constraints;
10 |
11 | namespace CycloneUnityTestScenes
12 | {
13 |
14 | public class ParticleSpring : MonoBehaviour
15 | {
16 |
17 | List m_particles;
18 |
19 | SegmentRenderer m_lines;
20 |
21 | VertexRenderer m_verts;
22 |
23 | void Start()
24 | {
25 | m_lines = new SegmentRenderer();
26 | m_lines.Color = Color.red;
27 |
28 | m_verts = new VertexRenderer(0.05f);
29 | m_verts.Color = Color.yellow;
30 |
31 | CreateParticles();
32 | }
33 |
34 | private void CreateParticles()
35 | {
36 | double mass = 1;
37 | double damping = 0.5;
38 | double len = 1;
39 | double springStrength = 4;
40 |
41 | var pos = transform.position.ToVector3d();
42 |
43 | var p0 = new Particle();
44 | p0.Position = pos + new Vector3d(0, 0, 0);
45 | p0.SetMass(0);
46 | p0.Damping = damping;
47 |
48 | var p1 = new Particle();
49 | p1.Position = new Vector3d(-1, 0, 0);
50 | p1.SetMass(mass);
51 | p1.Damping = damping;
52 |
53 | m_particles = new List();
54 | m_particles.Add(p0);
55 | m_particles.Add(p1);
56 |
57 | ParticlePhysicsEngine.Instance.Particles.AddRange(m_particles);
58 | ParticlePhysicsEngine.Instance.Forces.Add(new ParticleSpringForce(p0, p1, springStrength, len));
59 | }
60 |
61 | private void OnRenderObject()
62 | {
63 | var cam = Camera.current;
64 | if (cam == null) return;
65 |
66 | var points = new List();
67 | foreach (var p in m_particles)
68 | points.Add(p.Position);
69 |
70 | m_lines.Clear();
71 | m_lines.Load(points);
72 |
73 | m_verts.Clear();
74 | m_verts.Load(points);
75 |
76 | m_lines.Draw(cam);
77 | m_verts.Draw(cam);
78 | }
79 |
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/ProjectSettings/GraphicsSettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!30 &1
4 | GraphicsSettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 12
7 | m_Deferred:
8 | m_Mode: 1
9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0}
10 | m_DeferredReflections:
11 | m_Mode: 1
12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0}
13 | m_ScreenSpaceShadows:
14 | m_Mode: 1
15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0}
16 | m_LegacyDeferred:
17 | m_Mode: 1
18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0}
19 | m_DepthNormals:
20 | m_Mode: 1
21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0}
22 | m_MotionVectors:
23 | m_Mode: 1
24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0}
25 | m_LightHalo:
26 | m_Mode: 1
27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0}
28 | m_LensFlare:
29 | m_Mode: 1
30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0}
31 | m_AlwaysIncludedShaders:
32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0}
33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0}
34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0}
35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0}
36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0}
38 | m_PreloadedShaders: []
39 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000,
40 | type: 0}
41 | m_CustomRenderPipeline: {fileID: 0}
42 | m_TransparencySortMode: 0
43 | m_TransparencySortAxis: {x: 0, y: 0, z: 1}
44 | m_DefaultRenderingPath: 1
45 | m_DefaultMobileRenderingPath: 1
46 | m_TierSettings: []
47 | m_LightmapStripping: 0
48 | m_FogStripping: 0
49 | m_InstancingStripping: 0
50 | m_LightmapKeepPlain: 1
51 | m_LightmapKeepDirCombined: 1
52 | m_LightmapKeepDynamicPlain: 1
53 | m_LightmapKeepDynamicDirCombined: 1
54 | m_LightmapKeepShadowMask: 1
55 | m_LightmapKeepSubtractive: 1
56 | m_FogKeepLinear: 1
57 | m_FogKeepExp: 1
58 | m_FogKeepExp2: 1
59 | m_AlbedoSwatchInfos: []
60 | m_LightsUseLinearIntensity: 0
61 | m_LightsUseColorTemperature: 0
62 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleRodConstraint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Particles.Constraints
7 | {
8 | ///
9 | /// Rods link a pair of particles, generating a contact if they
10 | /// stray too far apart or too close.
11 | ///
12 | public class ParticleRodConstraint : ParticleConstraint
13 | {
14 |
15 | ///
16 | /// The particle at the other end of the rod.
17 | ///
18 | private Particle m_particleA, m_particleB;
19 |
20 | ///
21 | /// Holds the length of the rod.
22 | ///
23 | private double m_length;
24 |
25 | public ParticleRodConstraint(Particle a, Particle b, double length)
26 | {
27 | m_particleA = a;
28 | m_particleB = b;
29 | m_length = length;
30 | }
31 |
32 | ///
33 | /// Fills the given contact structure with the contact needed
34 | /// to keep the rod from extending or compressing.
35 | ///
36 | public override int AddContact(IList particles, IList contacts, int next)
37 | {
38 | // Find the length of the cable
39 | double currentLen = Vector3d.Distance(m_particleA.Position, m_particleB.Position);
40 |
41 | // Check if we're over-extended
42 | if (currentLen == m_length) return 0;
43 |
44 | var contact = contacts[next];
45 |
46 | // Otherwise return the contact
47 | contact.Particles[0] = m_particleA;
48 | contact.Particles[1] = m_particleB;
49 |
50 | // Calculate the normal
51 | Vector3d normal = m_particleB.Position - m_particleA.Position;
52 | normal.Normalize();
53 |
54 | // The contact normal depends on whether we're extending or compressing
55 | if (currentLen > m_length)
56 | {
57 | contact.ContactNormal = normal;
58 | contact.Penetration = currentLen - m_length;
59 | }
60 | else
61 | {
62 | contact.ContactNormal = normal * -1;
63 | contact.Penetration = m_length - currentLen;
64 | }
65 |
66 | // Always use zero restitution (no bounciness)
67 | contact.Restitution = 0;
68 |
69 | return 1;
70 | }
71 |
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Drawing/BaseRenderer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 | using UnityEngine.Rendering;
5 |
6 | namespace Common.Unity.Drawing
7 | {
8 |
9 | public enum DRAW_ORIENTATION { XY, XZ };
10 |
11 | public abstract class BaseRenderer
12 | {
13 | public static readonly IList CUBE_INDICES = new int[]
14 | {
15 | 0, 1, 1, 2, 2, 3, 3, 0,
16 | 4, 5, 5, 6, 6, 7, 7, 4,
17 | 0, 4, 1, 5, 2, 6, 3, 7
18 | };
19 |
20 | public static readonly IList SQUARE_INDICES = new int[]
21 | {
22 | 0, 1, 1, 2, 2, 3, 3, 0
23 | };
24 |
25 | protected List m_vertices = new List();
26 |
27 | protected List m_indices = new List();
28 |
29 | public BaseRenderer()
30 | {
31 | LocalToWorld = Matrix4x4.identity;
32 | Orientation = DRAW_ORIENTATION.XY;
33 | Color = Color.white;
34 | Material = new Material(Shader.Find("Hidden/Internal-Colored"));
35 | }
36 |
37 | public Matrix4x4 LocalToWorld { get; set; }
38 |
39 | public DRAW_ORIENTATION Orientation { get; set; }
40 |
41 | public Color Color { get; set; }
42 |
43 | public CompareFunction ZTest
44 | {
45 | get { return (CompareFunction)Material.GetInt("_ZTest"); }
46 | set { Material.SetInt("_ZTest", (int)CompareFunction.Always); }
47 | }
48 |
49 | protected Material Material { get; set; }
50 |
51 | public virtual void Clear()
52 | {
53 | m_vertices.Clear();
54 | m_indices.Clear();
55 | }
56 |
57 | public void SetIndices(int vertexCount, IList indices)
58 | {
59 | int current = m_vertices.Count;
60 |
61 | if (indices == null)
62 | {
63 | for (int i = 0; i < vertexCount - 1; i++)
64 | {
65 | m_indices.Add(i + current);
66 | m_indices.Add(i + 1 + current);
67 | }
68 | }
69 | else
70 | {
71 | for (int i = 0; i < indices.Count; i++)
72 | m_indices.Add(indices[i] + current);
73 | }
74 |
75 | }
76 |
77 | public void Draw(Camera camera)
78 | {
79 | Draw(camera, Matrix4x4.identity);
80 | }
81 |
82 | public abstract void Draw(Camera camera, Matrix4x4 localToWorld);
83 |
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Forces/RigidSpringForce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Forces
7 | {
8 |
9 | ///
10 | ///
11 | ///
12 | public class RigidSpringForce : RigidForce
13 | {
14 |
15 | ///
16 | /// The bodies at the other end of the spring.
17 | ///
18 | private RigidBody m_bodyA, m_bodyB;
19 |
20 | ///
21 | /// The point of connection of the spring, in local coordinates.
22 | ///
23 | private Vector3d m_connectionA, m_connectionB;
24 |
25 | ///
26 | /// Holds the sprint constant
27 | ///
28 | private double m_springConstant;
29 |
30 | ///
31 | /// Holds the rest length of the spring
32 | ///
33 | private double m_restLength;
34 |
35 | ///
36 | ///
37 | ///
38 | public RigidSpringForce(RigidBody a, RigidBody b, Vector3d connectionA, Vector3d connectionB, double springConstant, double restLength)
39 | {
40 | m_bodyA = a;
41 | m_bodyB = b;
42 | m_connectionA = connectionA;
43 | m_connectionB = connectionB;
44 | m_springConstant = springConstant;
45 | m_restLength = restLength;
46 | }
47 |
48 | public override void UpdateForce(double dt)
49 | {
50 | UpdateForce(m_bodyA, m_bodyB, m_connectionA, m_connectionB, dt);
51 | UpdateForce(m_bodyB, m_bodyA, m_connectionB, m_connectionA, dt);
52 | }
53 |
54 | private void UpdateForce(RigidBody body, RigidBody other, Vector3d connection, Vector3d otherConnection, double dt)
55 | {
56 | if (body.HasInfiniteMass) return;
57 |
58 | // Calculate the two ends in world space
59 | Vector3d lws = body.GetPointInWorldSpace(connection);
60 | Vector3d ows = other.GetPointInWorldSpace(otherConnection);
61 |
62 | // Calculate the vector of the spring
63 | Vector3d force = lws - ows;
64 |
65 | // Calculate the magnitude of the force
66 | double magnitude = force.Magnitude;
67 | // Calculate the magnitude of the force
68 | magnitude = (m_restLength - magnitude) * m_springConstant;
69 |
70 | // Calculate the final force and apply it
71 | force.Normalize();
72 | force *= magnitude;
73 | body.AddForceAtPoint(force, lws);
74 |
75 | }
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/Assets/UnityTestScenes/Scripts/ParticleRod.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Common.Unity.Drawing;
6 | using Cyclone.Core;
7 | using Cyclone.Particles;
8 | using Cyclone.Particles.Forces;
9 | using Cyclone.Particles.Constraints;
10 |
11 | namespace CycloneUnityTestScenes
12 | {
13 |
14 | public class ParticleRod : MonoBehaviour
15 | {
16 |
17 | List m_particles;
18 |
19 | SegmentRenderer m_lines;
20 |
21 | VertexRenderer m_verts;
22 |
23 | void Start()
24 | {
25 | m_lines = new SegmentRenderer();
26 | m_lines.Color = Color.red;
27 |
28 | m_verts = new VertexRenderer(0.05f);
29 | m_verts.Color = Color.yellow;
30 |
31 | CreateParticles();
32 | }
33 |
34 | private void CreateParticles()
35 | {
36 | double mass = 1;
37 | double damping = 0.5;
38 | double len = 1;
39 |
40 | var pos = transform.position.ToVector3d();
41 |
42 | var p0 = new Particle();
43 | p0.Position = pos + new Vector3d(0,0,0);
44 | p0.SetMass(0);
45 | p0.Damping = damping;
46 |
47 | var p1 = new Particle();
48 | p1.Position = pos + new Vector3d(1, 0, 0);
49 | p1.SetMass(mass);
50 | p1.Damping = damping;
51 |
52 | var p2 = new Particle();
53 | p2.Position = pos + new Vector3d(3, 0, 0);
54 | p2.SetMass(mass);
55 | p2.Damping = damping;
56 |
57 | var p3 = new Particle();
58 | p3.Position = pos + new Vector3d(3, 0, 0);
59 | p3.SetMass(mass);
60 | p3.Damping = damping;
61 |
62 | m_particles = new List();
63 | m_particles.Add(p0);
64 | m_particles.Add(p1);
65 | m_particles.Add(p2);
66 | m_particles.Add(p3);
67 |
68 | ParticlePhysicsEngine.Instance.Particles.AddRange(m_particles);
69 | ParticlePhysicsEngine.Instance.Constraints.Add(new ParticleRodConstraint(p0, p1, len));
70 | ParticlePhysicsEngine.Instance.Constraints.Add(new ParticleRodConstraint(p1, p2, len));
71 | ParticlePhysicsEngine.Instance.Constraints.Add(new ParticleRodConstraint(p2, p3, len));
72 | }
73 |
74 | private void OnRenderObject()
75 | {
76 | var cam = Camera.current;
77 | if (cam == null) return;
78 |
79 | var points = new List();
80 | foreach (var p in m_particles)
81 | points.Add(p.Position);
82 |
83 | m_lines.Clear();
84 | m_lines.Load(points);
85 |
86 | m_verts.Clear();
87 | m_verts.Load(points);
88 |
89 | m_lines.Draw(cam);
90 | m_verts.Draw(cam);
91 | }
92 |
93 | }
94 |
95 | }
96 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/CollisionData.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Rigid.Constraints;
5 |
6 | namespace Cyclone.Rigid.Collisions
7 | {
8 |
9 | ///
10 | /// A helper structure that contains information for the detector to use
11 | /// in building its contact data.
12 | ///
13 | public class CollisionData
14 | {
15 | ///
16 | /// Holds the contact array to write into.
17 | ///
18 | public IList Contacts;
19 |
20 | ///
21 | /// Holds the maximum number of contacts the array can take.
22 | ///
23 | public int ContactsLeft { get; private set; }
24 |
25 | ///
26 | /// Holds the number of contacts found so far.
27 | ///
28 | public int ContactCount { get; private set; }
29 |
30 | ///
31 | /// Holds the friction value to write into any collisions.
32 | ///
33 | public double Friction;
34 |
35 | ///
36 | /// Holds the restitution value to write into any collisions.
37 | ///
38 | public double Restitution;
39 |
40 | ///
41 | /// Holds the collision tolerance, even uncolliding objects this
42 | /// close should have collisions generated.
43 | ///
44 | public double Tolerance;
45 |
46 | ///
47 | /// Checks if there are more contacts.
48 | ///
49 | public bool HasMoreContacts()
50 | {
51 | return ContactsLeft > 0;
52 | }
53 |
54 | ///
55 | /// Checks if there are no more contacts.
56 | ///
57 | public bool NoMoreContacts()
58 | {
59 | return ContactsLeft <= 0;
60 | }
61 |
62 | ///
63 | /// Resets the data so that it has no used contacts recorded.
64 | ///
65 | public void Reset(int start)
66 | {
67 | ContactsLeft = Contacts.Count - start;
68 | ContactCount = start;
69 | }
70 |
71 | ///
72 | /// Notifies the data that the given number of contacts have
73 | /// been added.
74 | ///
75 | private void AddContacts(int count)
76 | {
77 | // Reduce the number of contacts remaining, add number used
78 | ContactsLeft -= count;
79 | ContactCount += count;
80 | }
81 |
82 | ///
83 | ///
84 | ///
85 | ///
86 | public RigidContact GetContact()
87 | {
88 | if (NoMoreContacts())
89 | throw new InvalidOperationException("No more contacts.");
90 |
91 | var contact = Contacts[ContactCount];
92 | AddContacts(1);
93 | return contact;
94 | }
95 | }
96 |
97 | }
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/RigidJointConstraint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Constraints
7 | {
8 |
9 | ///
10 | /// Joints link together two rigid bodies and make sure they do not
11 | /// separate. In a general phyiscs engine there may be many
12 | /// different types of joint, that reduce the number of relative
13 | /// degrees of freedom between two objects. This joint is a common
14 | /// position joint: each object has a location (given in
15 | /// body-coordinates) that will be kept at the same point in the
16 | /// simulation.
17 | ///
18 | public class RigidJointConstraint : RigidConstraint
19 | {
20 |
21 | ///
22 | /// Holds the two rigid bodies that are connected by this joint.
23 | ///
24 | private RigidBody[] m_body;
25 |
26 | ///
27 | /// Holds the relative location of the connection for each
28 | /// body, given in local coordinates.
29 | ///
30 | private Vector3d[] m_position;
31 |
32 | ///
33 | /// Holds the maximum displacement at the joint before the
34 | /// joint is considered to be violated. This is normally a
35 | /// small, epsilon value. It can be larger, however, in which
36 | /// case the joint will behave as if an inelastic cable joined
37 | /// the bodies at their joint locations.
38 | ///
39 | private double m_error;
40 |
41 | ///
42 | /// Configures the joint in one go.
43 | ///
44 | public RigidJointConstraint(RigidBody a, Vector3d posA, RigidBody b, Vector3d posB, double error)
45 | {
46 | m_body = new RigidBody[] { a, b };
47 | m_position = new Vector3d[] { posA, posB };
48 | m_error = error;
49 | }
50 |
51 | ///
52 | /// Generates the contacts required to restore the joint if it
53 | /// has been violated.
54 | ///
55 | public override int AddContact(IList bodies, IList contacts, int next)
56 | {
57 | // Calculate the position of each connection point in world coordinates
58 | Vector3d a_pos_world = m_body[0].GetPointInWorldSpace(m_position[0]);
59 | Vector3d b_pos_world = m_body[1].GetPointInWorldSpace(m_position[1]);
60 |
61 | // Calculate the length of the joint
62 | Vector3d a_to_b = b_pos_world - a_pos_world;
63 | Vector3d normal = a_to_b;
64 | normal.Normalize();
65 | double length = a_to_b.Magnitude;
66 |
67 | // Check if it is violated
68 | if (Math.Abs(length) > m_error)
69 | {
70 | var contact = contacts[next];
71 | contact.Body[0] = m_body[0];
72 | contact.Body[1] = m_body[1];
73 | contact.ContactNormal = normal;
74 | contact.ContactPoint = (a_pos_world + b_pos_world) * 0.5;
75 | contact.Penetration = length - m_error;
76 | contact.Friction = 1.0;
77 | contact.Restitution = 0;
78 | return 1;
79 | }
80 |
81 | return 0;
82 | }
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/Assets/CommonUnity/Drawing/VextexRenderer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | using Cyclone.Core;
6 |
7 | namespace Common.Unity.Drawing
8 | {
9 |
10 | public class VertexRenderer : BaseRenderer
11 | {
12 |
13 | public VertexRenderer(float size)
14 | {
15 | Size = size;
16 | }
17 |
18 | public VertexRenderer(float size, DRAW_ORIENTATION orientation)
19 | {
20 | Size = size;
21 | Orientation = DRAW_ORIENTATION.XY;
22 | }
23 |
24 | public float Size = 0.1f;
25 |
26 | #region DOUBLE
27 | public void Load(IEnumerable vertices)
28 | {
29 | foreach (var v in vertices)
30 | {
31 | m_vertices.Add(v.ToVector4());
32 | }
33 | }
34 |
35 | public void Load(Vector3d vertex)
36 | {
37 | m_vertices.Add(vertex.ToVector4());
38 | }
39 |
40 | #endregion
41 |
42 | #region UNITY
43 | public void Load(IEnumerable vertices)
44 | {
45 | foreach (var v in vertices)
46 | {
47 | m_vertices.Add(v);
48 | }
49 | }
50 |
51 | public void Load(IEnumerable vertices)
52 | {
53 | foreach (var v in vertices)
54 | {
55 | m_vertices.Add(v);
56 | }
57 | }
58 | #endregion
59 |
60 | #region DRAW
61 | public override void Draw(Camera camera, Matrix4x4 localToWorld)
62 | {
63 | GL.PushMatrix();
64 |
65 | GL.LoadIdentity();
66 | GL.modelview = camera.worldToCameraMatrix * LocalToWorld;
67 | GL.LoadProjectionMatrix(camera.projectionMatrix);
68 |
69 | Material.SetPass(0);
70 | GL.Begin(GL.QUADS);
71 | GL.Color(Color);
72 |
73 | switch (Orientation)
74 | {
75 | case DRAW_ORIENTATION.XY:
76 | DrawXY();
77 | break;
78 |
79 | case DRAW_ORIENTATION.XZ:
80 | DrawXZ();
81 | break;
82 | }
83 |
84 | GL.End();
85 |
86 | GL.PopMatrix();
87 | }
88 |
89 | private void DrawXY()
90 | {
91 | float half = Size * 0.5f;
92 | for (int i = 0; i < m_vertices.Count; i++)
93 | {
94 | float x = m_vertices[i].x;
95 | float y = m_vertices[i].y;
96 | float z = m_vertices[i].z;
97 |
98 | GL.Vertex3(x + half, y + half, z);
99 | GL.Vertex3(x + half, y - half, z);
100 | GL.Vertex3(x - half, y - half, z);
101 | GL.Vertex3(x - half, y + half, z);
102 | }
103 | }
104 |
105 | private void DrawXZ()
106 | {
107 | float half = Size * 0.5f;
108 | for (int i = 0; i < m_vertices.Count; i++)
109 | {
110 | float x = m_vertices[i].x;
111 | float y = m_vertices[i].y;
112 | float z = m_vertices[i].z;
113 |
114 | GL.Vertex3(x + half, y, z + half);
115 | GL.Vertex3(x + half, y, z - half);
116 | GL.Vertex3(x - half, y, z - half);
117 | GL.Vertex3(x - half, y, z + half);
118 | }
119 | }
120 | #endregion
121 | }
122 |
123 | }
124 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/CollisionConstraint.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Rigid.Collisions;
6 |
7 | namespace Cyclone.Rigid.Constraints
8 | {
9 |
10 | ///
11 | /// Find all collisions between objects by directly testing each object
12 | /// against all others in a O(N^2) operation with no broad phase
13 | /// or any other optimization. Simple but slow.
14 | ///
15 | public class CollisionConstraint : RigidConstraint
16 | {
17 |
18 | ///
19 | /// Holds the friction value to write into any collisions.
20 | ///
21 | public double Friction;
22 |
23 | ///
24 | /// Holds the restitution value to write into any collisions.
25 | ///
26 | public double Restitution;
27 |
28 | ///
29 | /// Holds the collision tolerance, even uncolliding objects this
30 | /// close should have collisions generated.
31 | ///
32 | public double Tolerance;
33 |
34 | public List Planes;
35 |
36 | public List Primatives;
37 |
38 | public CollisionConstraint()
39 | {
40 | Planes = new List();
41 | Primatives = new List();
42 | }
43 |
44 | public override int AddContact(IList bodies, IList contacts, int next)
45 | {
46 | var data = new CollisionData();
47 | data.Contacts = contacts;
48 | data.Reset(next);
49 | data.Friction = Friction;
50 | data.Restitution = Restitution;
51 | data.Tolerance = Tolerance;
52 |
53 | foreach (var primative in Primatives)
54 | primative.CalculateInternals();
55 |
56 | foreach(var primative in Primatives)
57 | {
58 | if (data.NoMoreContacts()) break;
59 |
60 | switch(primative)
61 | {
62 | case CollisionSphere sphere:
63 | DetectCollisions(sphere, data);
64 | break;
65 |
66 | case CollisionBox box:
67 | DetectCollisions(box, data);
68 | break;
69 | }
70 | }
71 |
72 | return data.ContactCount;
73 | }
74 |
75 | private void DetectCollisions(CollisionSphere sphere, CollisionData data)
76 | {
77 | foreach (var plane in Planes)
78 | CollisionDetector.SphereAndHalfSpace(sphere, plane, data);
79 |
80 | foreach (var primative in Primatives)
81 | {
82 | if (primative == sphere) continue;
83 | if (data.NoMoreContacts()) break;
84 |
85 | switch (primative)
86 | {
87 | case CollisionSphere sphere2:
88 | CollisionDetector.SphereAndSphere(sphere, sphere2, data);
89 | break;
90 |
91 | case CollisionBox box:
92 | CollisionDetector.BoxAndSphere(box, sphere, data);
93 | break;
94 | }
95 | }
96 | }
97 |
98 | private void DetectCollisions(CollisionBox box, CollisionData data)
99 | {
100 | foreach (var plane in Planes)
101 | CollisionDetector.BoxAndHalfSpace(box, plane, data);
102 |
103 | foreach (var primative in Primatives)
104 | {
105 | if (primative == box) continue;
106 | if (data.NoMoreContacts()) break;
107 |
108 | switch (primative)
109 | {
110 | case CollisionSphere sphere:
111 | CollisionDetector.BoxAndSphere(box, sphere, data);
112 | break;
113 |
114 | case CollisionBox box2:
115 | CollisionDetector.BoxAndBox(box, box2, data);
116 | break;
117 | }
118 | }
119 | }
120 |
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Particle.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Particles
7 | {
8 | public class Particle
9 | {
10 | ///
11 | /// Holds the inverse of the mass of the particle. It
12 | /// is more useful to hold the inverse mass because
13 | /// integration is simpler, and because in real time
14 | /// simulation it is more useful to have objects with
15 | /// infinite mass(immovable) than zero mass
16 | /// (completely unstable in numerical simulation).
17 | ///
18 | public double InverseMass;
19 |
20 | ///
21 | /// Returns true if the mass of the particle is finite.
22 | ///
23 | public bool HasFiniteMass => InverseMass != 0;
24 |
25 | ///
26 | /// Returns true if the mass of the particle is infinite.
27 | ///
28 | public bool HasInfiniteMass => InverseMass == 0;
29 |
30 | ///
31 | /// Holds the amount of damping applied to linear
32 | /// motion. Damping is required to remove energy added
33 | /// through numerical instability in the integrator.
34 | ///
35 | public double Damping = 0.99;
36 |
37 | ///
38 | /// Holds the linear position of the particle in
39 | /// world space.
40 | ///
41 | public Vector3d Position;
42 |
43 | ///
44 | /// Holds the linear velocity of the particle in
45 | /// world space.
46 | ///
47 | public Vector3d Velocity;
48 |
49 | ///
50 | /// Holds the accumulated force to be applied at the next
51 | /// simulation iteration only.This value is zeroed at each
52 | /// integration step.
53 | ///
54 | public Vector3d ForceAccum;
55 |
56 | ///
57 | /// Holds the acceleration of the particle. This value
58 | /// can be used to set acceleration due to gravity(its primary
59 | /// use), or any other constant acceleration.
60 | ///
61 | public Vector3d Acceleration;
62 |
63 | ///
64 | /// Get the mass of the particle.
65 | ///
66 | ///
67 | public double GetMass()
68 | {
69 | if (InverseMass == 0)
70 | return double.PositiveInfinity;
71 | else
72 | return 1.0 / InverseMass;
73 | }
74 |
75 | ///
76 | /// Set the mass of the particle.
77 | ///
78 | public void SetMass(double mass)
79 | {
80 | if (mass <= 0)
81 | InverseMass = 0;
82 | else
83 | InverseMass = 1.0 / mass;
84 | }
85 |
86 | ///
87 | /// Accumalate force.
88 | ///
89 | public void AddForce(Vector3d force)
90 | {
91 | ForceAccum += force;
92 | }
93 |
94 | ///
95 | /// Clears the forces applied to the particle. This will be
96 | /// called automatically after each integration step.
97 | ///
98 | public void ClearAccumulator()
99 | {
100 | ForceAccum = Vector3d.Zero;
101 | }
102 |
103 | ///
104 | /// Integrates the particle forward in time by the given amount.
105 | /// This function uses a Newton-Euler integration method, which is a
106 | /// linear approximation to the correct integral. For this reason it
107 | /// may be inaccurate in some cases.
108 | ///
109 | public void Integrate(double dt)
110 | {
111 | // We don't integrate things with zero mass.
112 | if (InverseMass <= 0.0) return;
113 | if (dt <= 0) return;
114 |
115 | // Update linear position.
116 | Position += Velocity * dt;
117 |
118 | // Work out the acceleration from the force
119 | Vector3d resultingAcc = Acceleration;
120 | resultingAcc += ForceAccum * InverseMass;
121 |
122 | // Update linear velocity from the acceleration.
123 | Velocity += resultingAcc * dt;
124 |
125 | // Impose drag.
126 | Velocity *= Math.Pow(Damping, dt);
127 |
128 | // Clear the forces.
129 | ClearAccumulator();
130 | }
131 |
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Collisions/IntersectionTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Rigid;
6 |
7 | namespace Cyclone.Rigid.Collisions
8 | {
9 | ///
10 | /// A wrapper class that holds fast intersection tests. These
11 | /// can be used to drive the coarse collision detection system or
12 | /// as an early out in the full collision tests below.
13 | ///
14 | public static class IntersectionTests
15 | {
16 | public static bool SphereAndHalfSpace(CollisionSphere sphere, CollisionPlane plane)
17 | {
18 | // Find the distance from the origin
19 | double ballDistance = Vector3d.Dot(plane.Direction, sphere.GetAxis(3)) - sphere.Radius;
20 |
21 | // Check for the intersection
22 | return ballDistance <= plane.Offset;
23 | }
24 |
25 | public static bool SphereAndSphere(CollisionSphere one, CollisionSphere two)
26 | {
27 | // Find the vector between the objects
28 | Vector3d midline = one.GetAxis(3) - two.GetAxis(3);
29 |
30 | // See if it is large enough.
31 | return midline.SqrMagnitude < (one.Radius + two.Radius) * (one.Radius + two.Radius);
32 | }
33 |
34 | public static bool BoxAndBox(CollisionBox one, CollisionBox two)
35 | {
36 | // Find the vector between the two centres
37 | Vector3d toCentre = two.GetAxis(3) - one.GetAxis(3);
38 |
39 | if (!OverlapOnAxis(one, two, one.GetAxis(0), toCentre)) return false;
40 | if (!OverlapOnAxis(one, two, one.GetAxis(1), toCentre)) return false;
41 | if (!OverlapOnAxis(one, two, one.GetAxis(2), toCentre)) return false;
42 |
43 | if (!OverlapOnAxis(one, two, two.GetAxis(0), toCentre)) return false;
44 | if (!OverlapOnAxis(one, two, two.GetAxis(1), toCentre)) return false;
45 | if (!OverlapOnAxis(one, two, two.GetAxis(2), toCentre)) return false;
46 |
47 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(0), two.GetAxis(0)), toCentre)) return false;
48 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(0), two.GetAxis(1)), toCentre)) return false;
49 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(0), two.GetAxis(2)), toCentre)) return false;
50 |
51 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(1), two.GetAxis(0)), toCentre)) return false;
52 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(1), two.GetAxis(1)), toCentre)) return false;
53 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(1), two.GetAxis(2)), toCentre)) return false;
54 |
55 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(2), two.GetAxis(0)), toCentre)) return false;
56 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(2), two.GetAxis(1)), toCentre)) return false;
57 | if (!OverlapOnAxis(one, two, Vector3d.Cross(one.GetAxis(2), two.GetAxis(2)), toCentre)) return false;
58 |
59 | return true;
60 | }
61 |
62 | public static bool BoxAndHalfSpace(CollisionBox box, CollisionPlane plane)
63 | {
64 | // Work out the projected radius of the box onto the plane direction
65 | double projectedRadius = TransformToAxis(box, plane.Direction);
66 |
67 | // Work out how far the box is from the origin
68 | double boxDistance = Vector3d.Dot(plane.Direction, box.GetAxis(3)) - projectedRadius;
69 |
70 | // Check for the intersection
71 | return boxDistance <= plane.Offset;
72 | }
73 |
74 | ///
75 | /// This function checks if the two boxes overlap
76 | /// along the given axis.The final parameter toCentre
77 | /// is used to pass in the vector between the boxes centre
78 | /// points, to avoid having to recalculate it each time.
79 | ///
80 | private static bool OverlapOnAxis(CollisionBox one, CollisionBox two, Vector3d axis, Vector3d toCentre)
81 | {
82 | // Project the half-size of one onto axis
83 | double oneProject = TransformToAxis(one, axis);
84 | double twoProject = TransformToAxis(two, axis);
85 |
86 | // Project this onto the axis
87 | double distance = Vector3d.AbsDot(toCentre, axis);
88 |
89 | // Check for overlap
90 | return distance < oneProject + twoProject;
91 | }
92 |
93 | private static double TransformToAxis(CollisionBox box, Vector3d axis)
94 | {
95 | return
96 | box.HalfSize.x * Vector3d.AbsDot(axis, box.GetAxis(0)) +
97 | box.HalfSize.y * Vector3d.AbsDot(axis, box.GetAxis(1)) +
98 | box.HalfSize.z * Vector3d.AbsDot(axis, box.GetAxis(2));
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleContactResolver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Constraints
8 | {
9 | ///
10 | /// The contact resolution routine for particle contacts. One
11 | /// resolver instance can be shared for the whole simulation.
12 | ///
13 | /// The resolver uses an iterative satisfaction algorithm; it loops
14 | /// through each contact and tries to resolve it.This is a very fast
15 | /// algorithm but can be unstable when the contacts are highly
16 | /// inter-related.
17 | ///
18 | public class ParticleContactResolver
19 | {
20 |
21 | ///
22 | ///
23 | ///
24 | public ParticleContactResolver(int iterations = 0)
25 | {
26 | Iterations = iterations;
27 | }
28 |
29 | ///
30 | /// The number of iterations through the
31 | /// resolution algorithm.This should be at least the number of
32 | /// contacts (otherwise some constraints will not be resolved -
33 | /// although sometimes this is not noticable). If the
34 | /// iterations are not needed they will not be used, so adding
35 | /// more iterations may not make any difference.But in some
36 | /// cases you would need millions of iterations.Think about
37 | /// the number of iterations as a bound: if you specify a large
38 | /// number, sometimes the algorithm WILL use it, and you may
39 | /// drop frames.
40 | ///
41 | public int Iterations;
42 |
43 | ///
44 | /// This is a performance tracking value - we keep a record
45 | /// of the actual number of iterations used.
46 | ///
47 | public int IterationsUsed;
48 |
49 | ///
50 | /// Resolves a set of particle contacts for both penetration
51 | /// and velocity.
52 | ///
53 | /// Contacts that cannot interact with each other should be
54 | /// passed to separate calls to resolveContacts, as the
55 | /// resolution algorithm takes much longer for lots of contacts
56 | /// than it does for the same number of contacts in small sets.
57 | ///
58 | ///
59 | ///
60 | public void ResolveContacts(IList contacts, int numContacts, double dt)
61 | {
62 | if (numContacts == 0) return;
63 |
64 | if (Iterations <= 0)
65 | Iterations = numContacts * 2;
66 |
67 | IterationsUsed = 0;
68 | while (IterationsUsed < Iterations)
69 | {
70 | // Find the contact with the largest closing velocity.
71 | double max = double.PositiveInfinity;
72 | int maxIndex = numContacts;
73 | for (int i = 0; i < numContacts; i++)
74 | {
75 | double sepVel = contacts[i].CalculateSeparatingVelocity();
76 | if (sepVel < max && (sepVel < 0 || contacts[i].Penetration > 0))
77 | {
78 | max = sepVel;
79 | maxIndex = i;
80 | }
81 | }
82 |
83 | // Do we have anything worth resolving?
84 | if (maxIndex == numContacts) break;
85 |
86 | // Resolve this contact
87 | contacts[maxIndex].Resolve(dt);
88 |
89 | // Update the interpenetrations for all particles
90 | Vector3d[] move = contacts[maxIndex].ParticlesMovement;
91 | for (int i = 0; i < numContacts; i++)
92 | {
93 | if (contacts[i].Particles[0] == contacts[maxIndex].Particles[0])
94 | {
95 | contacts[i].Penetration -= Vector3d.Dot(move[0], contacts[i].ContactNormal);
96 | }
97 | else if (contacts[i].Particles[0] == contacts[maxIndex].Particles[1])
98 | {
99 | contacts[i].Penetration -= Vector3d.Dot(move[1], contacts[i].ContactNormal);
100 | }
101 |
102 | if (contacts[i].Particles[1] != null)
103 | {
104 | if (contacts[i].Particles[1] == contacts[maxIndex].Particles[0])
105 | {
106 | contacts[i].Penetration += Vector3d.Dot(move[0], contacts[i].ContactNormal);
107 | }
108 | else if (contacts[i].Particles[1] == contacts[maxIndex].Particles[1])
109 | {
110 | contacts[i].Penetration += Vector3d.Dot(move[1], contacts[i].ContactNormal);
111 | }
112 | }
113 | }
114 |
115 | IterationsUsed++;
116 | }
117 | }
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/Quaternion.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Cyclone.Core
5 | {
6 | ///
7 | /// Holds a three degree of freedom orientation.
8 | ///
9 | /// Quaternions have
10 | /// several mathematical properties that make them useful for
11 | /// representing orientations, but require four items of data to
12 | /// hold the three degrees of freedom.These four items of data can
13 | /// be viewed as the coefficients of a complex number with three
14 | /// imaginary parts.The mathematics of the quaternion is then
15 | /// defined and is roughly correspondent to the math of 3D
16 | /// rotations.A quaternion is only a valid rotation if it is
17 | /// normalised: i.e.it has a length of 1.
18 | ///
19 | /// @note Angular velocity and acceleration can be correctly
20 | /// represented as vectors. Quaternions are only needed for
21 | /// orientation.
22 | ///
23 | public struct Quaternion
24 | {
25 | ///
26 | /// Holds the real component of the quaternion.
27 | ///
28 | public double r;
29 |
30 | ///
31 | /// Holds the first complex component of the quaternion.
32 | ///
33 | public double i;
34 |
35 | ///
36 | /// Holds the second complex component of the quaternion.
37 | ///
38 | public double j;
39 |
40 | ///
41 | /// Holds the third complex component of the quaternion.
42 | ///
43 | public double k;
44 |
45 | ///
46 | ///
47 | ///
48 | public readonly static Quaternion Identity = new Quaternion(1, 0, 0, 0);
49 |
50 | ///
51 | /// The explicit constructor creates a quaternion with the given components.
52 | ///
53 | /// The real component of the rigid body's orientation quaternion.
54 | /// The first complex component of the rigid body's orientation quaternion
55 | /// The second complex component of the rigid body's orientation quaternion
56 | /// The third complex component of the rigid body's orientation quaternion
57 | public Quaternion(double r, double i, double j, double k)
58 | {
59 | this.r = r;
60 | this.i = i;
61 | this.j = j;
62 | this.k = k;
63 | }
64 |
65 | ///
66 | /// Normalises the quaternion to unit length, making it a valid
67 | /// orientation quaternion.
68 | ///
69 | public void Normalise()
70 | {
71 | double d = r * r + i * i + j * j + k * k;
72 |
73 | // Check for zero length quaternion, and use the no-rotation
74 | // quaternion in that case.
75 | if (d < DMath.EPS)
76 | {
77 | i = j = k = 0;
78 | r = 1;
79 | return;
80 | }
81 |
82 | d = 1.0 / Math.Sqrt(d);
83 | r *= d;
84 | i *= d;
85 | j *= d;
86 | k *= d;
87 | }
88 |
89 | ///
90 | /// Multiplies the quaternion by the given quaternion.
91 | ///
92 | public static Quaternion operator *(Quaternion q1, Quaternion q2)
93 | {
94 | Quaternion q = new Quaternion();
95 |
96 | q.r = q1.r * q2.r - q1.i * q2.i -
97 | q1.j * q2.j - q1.k * q2.k;
98 | q.i = q1.r * q2.i + q1.i * q2.r +
99 | q1.j * q2.k - q1.k * q2.j;
100 | q.j = q1.r * q2.j + q1.j * q2.r +
101 | q1.k * q2.i - q1.i * q2.k;
102 | q.k = q1.r * q2.k + q1.k * q2.r +
103 | q1.i * q2.j - q1.j * q2.i;
104 |
105 | return q;
106 | }
107 |
108 | ///
109 | /// Adds the given vector to this, scaled by the given amount.
110 | /// This is used to update the orientation quaternion by a rotation
111 | ///
112 | /// The vector to add.
113 | /// The amount of the vector to add.
114 | public void AddScaledVector(Vector3d vector, double scale)
115 | {
116 | Quaternion q = new Quaternion(0,
117 | vector.x * scale,
118 | vector.y * scale,
119 | vector.z * scale);
120 |
121 | q = q * this;
122 | r += q.r * 0.5;
123 | i += q.i * 0.5;
124 | j += q.j * 0.5;
125 | k += q.k * 0.5;
126 | }
127 |
128 | ///
129 | ///
130 | ///
131 | ///
132 | public void RotateByVector(Vector3d vector)
133 | {
134 | Quaternion q = new Quaternion(0, vector.x, vector.y, vector.z);
135 |
136 | q = this * q;
137 | r = q.r;
138 | i = q.i;
139 | j = q.j;
140 | k = q.k;
141 | }
142 | }
143 |
144 |
145 | }
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/ParticleEngine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles.Forces;
6 | using Cyclone.Particles.Constraints;
7 |
8 | namespace Cyclone.Particles
9 | {
10 | public class ParticleEngine
11 | {
12 | ///
13 | /// Holds the particles.
14 | ///
15 | public List Particles;
16 |
17 | ///
18 | /// Holds the force areas for the in this world.
19 | ///
20 | public List ForceAreas;
21 |
22 | ///
23 | /// Holds the forces for the particles in this world.
24 | ///
25 | public List Forces;
26 |
27 | ///
28 | /// Contact generators.
29 | ///
30 | public List Constraints;
31 |
32 | ///
33 | /// Holds the resolver for contacts.
34 | ///
35 | public ParticleContactResolver Resolver;
36 |
37 | ///
38 | /// Holds the list of contacts.
39 | ///
40 | private ParticleContact[] m_contacts;
41 |
42 | ///
43 | /// Creates a new particle simulator that can handle up to the
44 | /// given number of contacts per frame.You can also optionally
45 | /// give a number of contact-resolution iterations to use. If you
46 | /// don't give a number of iterations, then twice the number of
47 | /// contacts will be used.
48 | ///
49 | public ParticleEngine(int maxContacts)
50 | {
51 | Particles = new List();
52 | ForceAreas = new List();
53 | Forces = new List();
54 | Constraints = new List();
55 | Resolver = new ParticleContactResolver();
56 |
57 | m_contacts = new ParticleContact[maxContacts];
58 | for (int i = 0; i < maxContacts; i++)
59 | m_contacts[i] = new ParticleContact();
60 | }
61 |
62 | ///
63 | /// Initializes the world for a simulation frame. This clears
64 | /// the force accumulators for particles in the world.After
65 | /// calling this, the particles can have their forces for this
66 | /// frame added.
67 | ///
68 | public void StartFrame()
69 | {
70 | foreach (var p in Particles)
71 | p.ClearAccumulator();
72 | }
73 |
74 | ///
75 | /// Processes all the physics for the particle world.
76 | ///
77 | ///
78 | public void RunPhysics(double dt)
79 | {
80 | // First apply the forces
81 | ApplyForces(dt);
82 |
83 | // Then integrate the objects
84 | Integrate(dt);
85 |
86 | // Generate contacts
87 | int usedContacts = GenerateContacts();
88 |
89 | // And process them
90 | if (usedContacts > 0)
91 | Resolver.ResolveContacts(m_contacts, usedContacts, dt);
92 | }
93 |
94 | ///
95 | /// Apply the forces.
96 | ///
97 | ///
98 | private void ApplyForces(double dt)
99 | {
100 | foreach (var f in ForceAreas)
101 | {
102 | foreach(var p in Particles)
103 | f.UpdateForce(p, dt);
104 | }
105 |
106 | foreach (var f in Forces)
107 | f.UpdateForce(dt);
108 | }
109 |
110 | ///
111 | /// Calls each of the registered contact generators to report
112 | /// their contacts.Returns the number of generated contacts.
113 | ///
114 | ///
115 | private int GenerateContacts()
116 | {
117 | ClearContacts();
118 |
119 | int limit = m_contacts.Length;
120 | int nextContact = 0;
121 |
122 | foreach(var g in Constraints)
123 | {
124 | int used = g.AddContact(Particles, m_contacts, nextContact);
125 | limit -= used;
126 | nextContact += used;
127 |
128 | // We've run out of contacts to fill. This means we're missing contacts.
129 | if (limit <= 0) break;
130 | }
131 |
132 | // Return the number of contacts used.
133 | return m_contacts.Length - limit;
134 | }
135 |
136 | ///
137 | /// Integrates all the particles in this world forward in time
138 | /// by the given duration.
139 | ///
140 | ///
141 | private void Integrate(double dt)
142 | {
143 | foreach (var p in Particles)
144 | p.Integrate(dt);
145 | }
146 |
147 | ///
148 | ///
149 | ///
150 | private void ClearContacts()
151 | {
152 | foreach (var contact in m_contacts)
153 | contact.Clear();
154 | }
155 |
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/DMath.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.CompilerServices;
3 |
4 | namespace Cyclone.Core
5 | {
6 | public class DMath
7 | {
8 |
9 | public const double EPS = 1e-18;
10 |
11 | public const double PI = Math.PI;
12 |
13 | public const double SQRT2 = 1.414213562373095;
14 |
15 | public const double Rad2Deg = 180.0 / PI;
16 |
17 | public const double Deg2Rad = PI / 180.0;
18 |
19 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
20 | public static double SafeAcos(double r)
21 | {
22 | return Math.Acos(Math.Min(1.0, Math.Max(-1.0, r)));
23 | }
24 |
25 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
26 | public static double SafeAsin(double r)
27 | {
28 | return Math.Asin(Math.Min(1.0, Math.Max(-1.0, r)));
29 | }
30 |
31 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
32 | public static double SafeSqrt(double v)
33 | {
34 | if (v <= 0.0) return 0.0;
35 | return Math.Sqrt(v);
36 | }
37 |
38 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
39 | public static double SafeLog(double v)
40 | {
41 | if (v <= 0.0) return 0.0;
42 | return Math.Log(v);
43 | }
44 |
45 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
46 | public static double SafeLog10(double v)
47 | {
48 | if (v <= 0.0) return 0.0;
49 | return Math.Log10(v);
50 | }
51 |
52 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
53 | public static double SafeInvSqrt(double n, double d, double eps = EPS)
54 | {
55 | if (d <= 0.0) return 0.0;
56 | d = Math.Sqrt(d);
57 | if (d < eps) return 0.0;
58 | return n / d;
59 | }
60 |
61 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
62 | public static double SafeInv(double v, double eps = EPS)
63 | {
64 | if (Math.Abs(v) < eps) return 0.0;
65 | return 1.0 / v;
66 | }
67 |
68 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
69 | public static double SafeDiv(double n, double d, double eps = EPS)
70 | {
71 | if (Math.Abs(d) < eps) return 0.0;
72 | return n / d;
73 | }
74 |
75 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
76 | public static bool IsZero(double v, double eps = EPS)
77 | {
78 | return Math.Abs(v) < eps;
79 | }
80 |
81 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
82 | public static bool IsFinite(double f)
83 | {
84 | return !(double.IsInfinity(f) || double.IsNaN(f));
85 | }
86 |
87 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
88 | public static double Sqr(double v)
89 | {
90 | return v * v;
91 | }
92 |
93 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
94 | public static double Pow3(double v)
95 | {
96 | return v * v * v;
97 | }
98 |
99 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
100 | public static double Pow4(double v)
101 | {
102 | return v * v * v * v;
103 | }
104 |
105 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
106 | public static double Clamp(double v, double min, double max)
107 | {
108 | if (v < min) v = min;
109 | if (v > max) v = max;
110 | return v;
111 | }
112 |
113 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
114 | public static double Clamp01(double v)
115 | {
116 | if (v < 0.0) v = 0.0;
117 | if (v > 1.0) v = 1.0;
118 | return v;
119 | }
120 |
121 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
122 | public static double SmoothStep(double edge0, double edge1, double x)
123 | {
124 | double t = Clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
125 | return t * t * (3.0 - 2.0 * t);
126 | }
127 |
128 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
129 | public static double Frac(double x)
130 | {
131 | return x - Math.Floor(x);
132 | }
133 |
134 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
135 | public static double Lerp(double v0, double v1, double a)
136 | {
137 | return v0 * (1.0 - a) + v1 * a;
138 | }
139 |
140 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
141 | public static double SignOrZero(double v)
142 | {
143 | if (v == 0) return 0;
144 | return Math.Sign(v);
145 | }
146 |
147 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
148 | public static double Min(double a, double b, double c)
149 | {
150 | return Math.Min(a, Math.Min(b, c));
151 | }
152 |
153 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
154 | public static double Max(double a, double b, double c)
155 | {
156 | return Math.Max(a, Math.Max(b, c));
157 | }
158 |
159 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
160 | public static double Normalize(double a, double min, double max)
161 | {
162 | double len = max - min;
163 | if (len <= 0) return 0;
164 | return (a - min) / len;
165 | }
166 |
167 | }
168 | }
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/RigidBodyEngine.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Rigid.Constraints;
6 | using Cyclone.Rigid.Forces;
7 |
8 | namespace Cyclone.Rigid
9 | {
10 |
11 | ///
12 | /// The world represents an independent simulation of physics. It
13 | /// keeps track of a set of rigid bodies, and provides the means to
14 | /// update them all.
15 | ///
16 | public class RigidBodyEngine
17 | {
18 | ///
19 | /// The list of bodies.
20 | ///
21 | public List Bodies;
22 |
23 | ///
24 | /// Holds the force areas for the in this world.
25 | ///
26 | public List ForceAreas;
27 |
28 | ///
29 | /// Holds the forces for the particles in this world.
30 | ///
31 | public List Forces;
32 |
33 | ///
34 | /// The list of contact generators.
35 | ///
36 | public List Constraints;
37 |
38 | ///
39 | /// The collision geometry.
40 | ///
41 | public CollisionConstraint Collisions;
42 |
43 | ///
44 | /// Holds the resolver for sets of contacts.
45 | ///
46 | public RigidContactResolver Resolver;
47 |
48 | ///
49 | /// Holds an array of contacts, for filling by the contact
50 | /// generators.
51 | ///
52 | private RigidContact[] m_contacts;
53 |
54 | ///
55 | /// Creates a new simulator that can handle up to the given
56 | /// number of contacts per frame. You can also optionally give
57 | /// a number of contact-resolution iterations to use. If you
58 | /// don't give a number of iterations, then four times the
59 | /// number of detected contacts will be used for each frame.
60 | ///
61 | public RigidBodyEngine(int maxContacts)
62 | {
63 | Bodies = new List();
64 | ForceAreas = new List();
65 | Forces = new List();
66 | Constraints = new List();
67 | Resolver = new RigidContactResolver();
68 |
69 | Collisions = new CollisionConstraint();
70 | Constraints.Add(Collisions);
71 |
72 | m_contacts = new RigidContact[maxContacts];
73 | for (int i = 0; i < maxContacts; i++)
74 | m_contacts[i] = new RigidContact();
75 | }
76 |
77 | ///
78 | /// Initialises the world for a simulation frame. This clears
79 | /// the force and torque accumulators for bodies in the
80 | /// world. After calling this, the bodies can have their forces
81 | /// and torques for this frame added.
82 | ///
83 | public void StartFrame()
84 | {
85 | foreach (var body in Bodies)
86 | {
87 | // Remove all forces from the accumulator
88 | body.ClearAccumulators();
89 | body.CalculateDerivedData();
90 | }
91 | }
92 |
93 | ///
94 | /// Processes all the physics for the world.
95 | ///
96 | public void RunPhysics(double dt)
97 | {
98 | // First apply the force.s
99 | ApplyForces(dt);
100 |
101 | Integrate(dt);
102 |
103 | // Generate contacts
104 | int usedContacts = GenerateContacts();
105 |
106 | // And process them
107 | if (usedContacts > 0)
108 | Resolver.ResolveContacts(m_contacts, usedContacts, dt);
109 | }
110 |
111 | ///
112 | /// Apply the forces.
113 | ///
114 | ///
115 | private void ApplyForces(double dt)
116 | {
117 | foreach (var f in ForceAreas)
118 | {
119 | foreach (var b in Bodies)
120 | f.UpdateForce(b, dt);
121 | }
122 |
123 | foreach (var f in Forces)
124 | f.UpdateForce(dt);
125 | }
126 |
127 | ///
128 | /// Calls each of the registered contact generators to report
129 | /// their contacts. Returns the number of generated contacts.
130 | ///
131 | private int GenerateContacts()
132 | {
133 | ClearContacts();
134 |
135 | int limit = m_contacts.Length;
136 | int nextContact = 0;
137 |
138 | foreach (var gen in Constraints)
139 | {
140 | int used = gen.AddContact(Bodies, m_contacts, nextContact);
141 | limit -= used;
142 | nextContact += used;
143 |
144 | // We've run out of contacts to fill. This means we're missing
145 | // contacts.
146 | if (limit <= 0) break;
147 | }
148 |
149 | // Return the number of contacts used.
150 | return m_contacts.Length - limit;
151 | }
152 |
153 | ///
154 | /// Integrates all the bodies in this world forward in time
155 | /// by the given dt.
156 | ///
157 | ///
158 | private void Integrate(double dt)
159 | {
160 | foreach (var b in Bodies)
161 | b.Integrate(dt);
162 | }
163 |
164 | ///
165 | ///
166 | ///
167 | private void ClearContacts()
168 | {
169 | foreach (var contact in m_contacts)
170 | contact.Clear();
171 | }
172 |
173 | }
174 |
175 | }
--------------------------------------------------------------------------------
/Assets/CommonUnity/Cameras/SimpleCameraController.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace Common.Unity.Cameras
4 | {
5 | public class SimpleCameraController : MonoBehaviour
6 | {
7 | class CameraState
8 | {
9 | public float yaw;
10 | public float pitch;
11 | public float roll;
12 | public float x;
13 | public float y;
14 | public float z;
15 |
16 | public void SetFromTransform(Transform t)
17 | {
18 | pitch = t.eulerAngles.x;
19 | yaw = t.eulerAngles.y;
20 | roll = t.eulerAngles.z;
21 | x = t.position.x;
22 | y = t.position.y;
23 | z = t.position.z;
24 | }
25 |
26 | public void Translate(Vector3 translation)
27 | {
28 | Vector3 rotatedTranslation = Quaternion.Euler(pitch, yaw, roll) * translation;
29 |
30 | x += rotatedTranslation.x;
31 | y += rotatedTranslation.y;
32 | z += rotatedTranslation.z;
33 | }
34 |
35 | public void LerpTowards(CameraState target, float positionLerpPct, float rotationLerpPct)
36 | {
37 | yaw = Mathf.Lerp(yaw, target.yaw, rotationLerpPct);
38 | pitch = Mathf.Lerp(pitch, target.pitch, rotationLerpPct);
39 | roll = Mathf.Lerp(roll, target.roll, rotationLerpPct);
40 |
41 | x = Mathf.Lerp(x, target.x, positionLerpPct);
42 | y = Mathf.Lerp(y, target.y, positionLerpPct);
43 | z = Mathf.Lerp(z, target.z, positionLerpPct);
44 | }
45 |
46 | public void UpdateTransform(Transform t)
47 | {
48 | t.eulerAngles = new Vector3(pitch, yaw, roll);
49 | t.position = new Vector3(x, y, z);
50 | }
51 | }
52 |
53 | CameraState m_TargetCameraState = new CameraState();
54 | CameraState m_InterpolatingCameraState = new CameraState();
55 |
56 | [Header("Movement Settings")]
57 | [Tooltip("Exponential boost factor on translation, controllable by mouse wheel.")]
58 | public float boost = 3.5f;
59 |
60 | [Tooltip("Time it takes to interpolate camera position 99% of the way to the target."), Range(0.001f, 1f)]
61 | public float positionLerpTime = 0.2f;
62 |
63 | [Header("Rotation Settings")]
64 | [Tooltip("X = Change in mouse position.\nY = Multiplicative factor for camera rotation.")]
65 | public AnimationCurve mouseSensitivityCurve = new AnimationCurve(new Keyframe(0f, 0.5f, 0f, 5f), new Keyframe(1f, 2.5f, 0f, 0f));
66 |
67 | [Tooltip("Time it takes to interpolate camera rotation 99% of the way to the target."), Range(0.001f, 1f)]
68 | public float rotationLerpTime = 0.01f;
69 |
70 | [Tooltip("Whether or not to invert our Y axis for mouse input to rotation.")]
71 | public bool invertY = false;
72 |
73 | void OnEnable()
74 | {
75 | m_TargetCameraState.SetFromTransform(transform);
76 | m_InterpolatingCameraState.SetFromTransform(transform);
77 | }
78 |
79 | Vector3 GetInputTranslationDirection()
80 | {
81 | Vector3 direction = new Vector3();
82 | if (Input.GetKey(KeyCode.W))
83 | {
84 | direction += Vector3.forward;
85 | }
86 | if (Input.GetKey(KeyCode.S))
87 | {
88 | direction += Vector3.back;
89 | }
90 | if (Input.GetKey(KeyCode.A))
91 | {
92 | direction += Vector3.left;
93 | }
94 | if (Input.GetKey(KeyCode.D))
95 | {
96 | direction += Vector3.right;
97 | }
98 | if (Input.GetKey(KeyCode.Q))
99 | {
100 | direction += Vector3.down;
101 | }
102 | if (Input.GetKey(KeyCode.E))
103 | {
104 | direction += Vector3.up;
105 | }
106 | return direction;
107 | }
108 |
109 | void Update()
110 | {
111 |
112 | // Rotation
113 | if (Input.GetMouseButton(1))
114 | {
115 | var mouseMovement = new Vector2(Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y") * (invertY ? 1 : -1));
116 |
117 | var mouseSensitivityFactor = mouseSensitivityCurve.Evaluate(mouseMovement.magnitude);
118 |
119 | m_TargetCameraState.yaw += mouseMovement.x * mouseSensitivityFactor;
120 | m_TargetCameraState.pitch += mouseMovement.y * mouseSensitivityFactor;
121 | }
122 |
123 | // Translation
124 | var translation = GetInputTranslationDirection() * Time.deltaTime;
125 |
126 | // Speed up movement when shift key held
127 | if (Input.GetKey(KeyCode.LeftShift))
128 | {
129 | translation *= 10.0f;
130 | }
131 |
132 | // Modify movement by a boost factor (defined in Inspector and modified in play mode through the mouse scroll wheel)
133 | boost += Input.mouseScrollDelta.y * 0.2f;
134 | translation *= Mathf.Pow(2.0f, boost);
135 |
136 | m_TargetCameraState.Translate(translation);
137 |
138 | // Framerate-independent interpolation
139 | // Calculate the lerp amount, such that we get 99% of the way to our target in the specified time
140 | var positionLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / positionLerpTime) * Time.deltaTime);
141 | var rotationLerpPct = 1f - Mathf.Exp((Mathf.Log(1f - 0.99f) / rotationLerpTime) * Time.deltaTime);
142 | m_InterpolatingCameraState.LerpTowards(m_TargetCameraState, positionLerpPct, rotationLerpPct);
143 |
144 | m_InterpolatingCameraState.UpdateTransform(transform);
145 | }
146 | }
147 |
148 | }
--------------------------------------------------------------------------------
/ProjectSettings/InputManager.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!13 &1
4 | InputManager:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 2
7 | m_Axes:
8 | - serializedVersion: 3
9 | m_Name: Horizontal
10 | descriptiveName:
11 | descriptiveNegativeName:
12 | negativeButton: left
13 | positiveButton: right
14 | altNegativeButton: a
15 | altPositiveButton: d
16 | gravity: 3
17 | dead: 0.001
18 | sensitivity: 3
19 | snap: 1
20 | invert: 0
21 | type: 0
22 | axis: 0
23 | joyNum: 0
24 | - serializedVersion: 3
25 | m_Name: Vertical
26 | descriptiveName:
27 | descriptiveNegativeName:
28 | negativeButton: down
29 | positiveButton: up
30 | altNegativeButton: s
31 | altPositiveButton: w
32 | gravity: 3
33 | dead: 0.001
34 | sensitivity: 3
35 | snap: 1
36 | invert: 0
37 | type: 0
38 | axis: 0
39 | joyNum: 0
40 | - serializedVersion: 3
41 | m_Name: Fire1
42 | descriptiveName:
43 | descriptiveNegativeName:
44 | negativeButton:
45 | positiveButton: left ctrl
46 | altNegativeButton:
47 | altPositiveButton: mouse 0
48 | gravity: 1000
49 | dead: 0.001
50 | sensitivity: 1000
51 | snap: 0
52 | invert: 0
53 | type: 0
54 | axis: 0
55 | joyNum: 0
56 | - serializedVersion: 3
57 | m_Name: Fire2
58 | descriptiveName:
59 | descriptiveNegativeName:
60 | negativeButton:
61 | positiveButton: left alt
62 | altNegativeButton:
63 | altPositiveButton: mouse 1
64 | gravity: 1000
65 | dead: 0.001
66 | sensitivity: 1000
67 | snap: 0
68 | invert: 0
69 | type: 0
70 | axis: 0
71 | joyNum: 0
72 | - serializedVersion: 3
73 | m_Name: Fire3
74 | descriptiveName:
75 | descriptiveNegativeName:
76 | negativeButton:
77 | positiveButton: left shift
78 | altNegativeButton:
79 | altPositiveButton: mouse 2
80 | gravity: 1000
81 | dead: 0.001
82 | sensitivity: 1000
83 | snap: 0
84 | invert: 0
85 | type: 0
86 | axis: 0
87 | joyNum: 0
88 | - serializedVersion: 3
89 | m_Name: Jump
90 | descriptiveName:
91 | descriptiveNegativeName:
92 | negativeButton:
93 | positiveButton: space
94 | altNegativeButton:
95 | altPositiveButton:
96 | gravity: 1000
97 | dead: 0.001
98 | sensitivity: 1000
99 | snap: 0
100 | invert: 0
101 | type: 0
102 | axis: 0
103 | joyNum: 0
104 | - serializedVersion: 3
105 | m_Name: Mouse X
106 | descriptiveName:
107 | descriptiveNegativeName:
108 | negativeButton:
109 | positiveButton:
110 | altNegativeButton:
111 | altPositiveButton:
112 | gravity: 0
113 | dead: 0
114 | sensitivity: 0.1
115 | snap: 0
116 | invert: 0
117 | type: 1
118 | axis: 0
119 | joyNum: 0
120 | - serializedVersion: 3
121 | m_Name: Mouse Y
122 | descriptiveName:
123 | descriptiveNegativeName:
124 | negativeButton:
125 | positiveButton:
126 | altNegativeButton:
127 | altPositiveButton:
128 | gravity: 0
129 | dead: 0
130 | sensitivity: 0.1
131 | snap: 0
132 | invert: 0
133 | type: 1
134 | axis: 1
135 | joyNum: 0
136 | - serializedVersion: 3
137 | m_Name: Mouse ScrollWheel
138 | descriptiveName:
139 | descriptiveNegativeName:
140 | negativeButton:
141 | positiveButton:
142 | altNegativeButton:
143 | altPositiveButton:
144 | gravity: 0
145 | dead: 0
146 | sensitivity: 0.1
147 | snap: 0
148 | invert: 0
149 | type: 1
150 | axis: 2
151 | joyNum: 0
152 | - serializedVersion: 3
153 | m_Name: Horizontal
154 | descriptiveName:
155 | descriptiveNegativeName:
156 | negativeButton:
157 | positiveButton:
158 | altNegativeButton:
159 | altPositiveButton:
160 | gravity: 0
161 | dead: 0.19
162 | sensitivity: 1
163 | snap: 0
164 | invert: 0
165 | type: 2
166 | axis: 0
167 | joyNum: 0
168 | - serializedVersion: 3
169 | m_Name: Vertical
170 | descriptiveName:
171 | descriptiveNegativeName:
172 | negativeButton:
173 | positiveButton:
174 | altNegativeButton:
175 | altPositiveButton:
176 | gravity: 0
177 | dead: 0.19
178 | sensitivity: 1
179 | snap: 0
180 | invert: 1
181 | type: 2
182 | axis: 1
183 | joyNum: 0
184 | - serializedVersion: 3
185 | m_Name: Fire1
186 | descriptiveName:
187 | descriptiveNegativeName:
188 | negativeButton:
189 | positiveButton: joystick button 0
190 | altNegativeButton:
191 | altPositiveButton:
192 | gravity: 1000
193 | dead: 0.001
194 | sensitivity: 1000
195 | snap: 0
196 | invert: 0
197 | type: 0
198 | axis: 0
199 | joyNum: 0
200 | - serializedVersion: 3
201 | m_Name: Fire2
202 | descriptiveName:
203 | descriptiveNegativeName:
204 | negativeButton:
205 | positiveButton: joystick button 1
206 | altNegativeButton:
207 | altPositiveButton:
208 | gravity: 1000
209 | dead: 0.001
210 | sensitivity: 1000
211 | snap: 0
212 | invert: 0
213 | type: 0
214 | axis: 0
215 | joyNum: 0
216 | - serializedVersion: 3
217 | m_Name: Fire3
218 | descriptiveName:
219 | descriptiveNegativeName:
220 | negativeButton:
221 | positiveButton: joystick button 2
222 | altNegativeButton:
223 | altPositiveButton:
224 | gravity: 1000
225 | dead: 0.001
226 | sensitivity: 1000
227 | snap: 0
228 | invert: 0
229 | type: 0
230 | axis: 0
231 | joyNum: 0
232 | - serializedVersion: 3
233 | m_Name: Jump
234 | descriptiveName:
235 | descriptiveNegativeName:
236 | negativeButton:
237 | positiveButton: joystick button 3
238 | altNegativeButton:
239 | altPositiveButton:
240 | gravity: 1000
241 | dead: 0.001
242 | sensitivity: 1000
243 | snap: 0
244 | invert: 0
245 | type: 0
246 | axis: 0
247 | joyNum: 0
248 | - serializedVersion: 3
249 | m_Name: Submit
250 | descriptiveName:
251 | descriptiveNegativeName:
252 | negativeButton:
253 | positiveButton: return
254 | altNegativeButton:
255 | altPositiveButton: joystick button 0
256 | gravity: 1000
257 | dead: 0.001
258 | sensitivity: 1000
259 | snap: 0
260 | invert: 0
261 | type: 0
262 | axis: 0
263 | joyNum: 0
264 | - serializedVersion: 3
265 | m_Name: Submit
266 | descriptiveName:
267 | descriptiveNegativeName:
268 | negativeButton:
269 | positiveButton: enter
270 | altNegativeButton:
271 | altPositiveButton: space
272 | gravity: 1000
273 | dead: 0.001
274 | sensitivity: 1000
275 | snap: 0
276 | invert: 0
277 | type: 0
278 | axis: 0
279 | joyNum: 0
280 | - serializedVersion: 3
281 | m_Name: Cancel
282 | descriptiveName:
283 | descriptiveNegativeName:
284 | negativeButton:
285 | positiveButton: escape
286 | altNegativeButton:
287 | altPositiveButton: joystick button 1
288 | gravity: 1000
289 | dead: 0.001
290 | sensitivity: 1000
291 | snap: 0
292 | invert: 0
293 | type: 0
294 | axis: 0
295 | joyNum: 0
296 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.obj
68 | *.iobj
69 | *.pch
70 | *.pdb
71 | *.ipdb
72 | *.pgc
73 | *.pgd
74 | *.rsp
75 | *.sbr
76 | *.tlb
77 | *.tli
78 | *.tlh
79 | *.tmp
80 | *.tmp_proj
81 | *_wpftmp.csproj
82 | *.log
83 | *.vspscc
84 | *.vssscc
85 | .builds
86 | *.pidb
87 | *.svclog
88 | *.scc
89 |
90 | # Chutzpah Test files
91 | _Chutzpah*
92 |
93 | # Visual C++ cache files
94 | ipch/
95 | *.aps
96 | *.ncb
97 | *.opendb
98 | *.opensdf
99 | *.sdf
100 | *.cachefile
101 | *.VC.db
102 | *.VC.VC.opendb
103 |
104 | # Visual Studio profiler
105 | *.psess
106 | *.vsp
107 | *.vspx
108 | *.sap
109 |
110 | # Visual Studio Trace Files
111 | *.e2e
112 |
113 | # TFS 2012 Local Workspace
114 | $tf/
115 |
116 | # Guidance Automation Toolkit
117 | *.gpState
118 |
119 | # ReSharper is a .NET coding add-in
120 | _ReSharper*/
121 | *.[Rr]e[Ss]harper
122 | *.DotSettings.user
123 |
124 | # JustCode is a .NET coding add-in
125 | .JustCode
126 |
127 | # TeamCity is a build add-in
128 | _TeamCity*
129 |
130 | # DotCover is a Code Coverage Tool
131 | *.dotCover
132 |
133 | # AxoCover is a Code Coverage Tool
134 | .axoCover/*
135 | !.axoCover/settings.json
136 |
137 | # Visual Studio code coverage results
138 | *.coverage
139 | *.coveragexml
140 |
141 | # NCrunch
142 | _NCrunch_*
143 | .*crunch*.local.xml
144 | nCrunchTemp_*
145 |
146 | # MightyMoose
147 | *.mm.*
148 | AutoTest.Net/
149 |
150 | # Web workbench (sass)
151 | .sass-cache/
152 |
153 | # Installshield output folder
154 | [Ee]xpress/
155 |
156 | # DocProject is a documentation generator add-in
157 | DocProject/buildhelp/
158 | DocProject/Help/*.HxT
159 | DocProject/Help/*.HxC
160 | DocProject/Help/*.hhc
161 | DocProject/Help/*.hhk
162 | DocProject/Help/*.hhp
163 | DocProject/Help/Html2
164 | DocProject/Help/html
165 |
166 | # Click-Once directory
167 | publish/
168 |
169 | # Publish Web Output
170 | *.[Pp]ublish.xml
171 | *.azurePubxml
172 | # Note: Comment the next line if you want to checkin your web deploy settings,
173 | # but database connection strings (with potential passwords) will be unencrypted
174 | *.pubxml
175 | *.publishproj
176 |
177 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
178 | # checkin your Azure Web App publish settings, but sensitive information contained
179 | # in these scripts will be unencrypted
180 | PublishScripts/
181 |
182 | # NuGet Packages
183 | *.nupkg
184 | # The packages folder can be ignored because of Package Restore
185 | **/[Pp]ackages/*
186 | # except build/, which is used as an MSBuild target.
187 | !**/[Pp]ackages/build/
188 | # Uncomment if necessary however generally it will be regenerated when needed
189 | #!**/[Pp]ackages/repositories.config
190 | # NuGet v3's project.json files produces more ignorable files
191 | *.nuget.props
192 | *.nuget.targets
193 |
194 | # Microsoft Azure Build Output
195 | csx/
196 | *.build.csdef
197 |
198 | # Microsoft Azure Emulator
199 | ecf/
200 | rcf/
201 |
202 | # Windows Store app package directories and files
203 | AppPackages/
204 | BundleArtifacts/
205 | Package.StoreAssociation.xml
206 | _pkginfo.txt
207 | *.appx
208 |
209 | # Visual Studio cache files
210 | # files ending in .cache can be ignored
211 | *.[Cc]ache
212 | # but keep track of directories ending in .cache
213 | !?*.[Cc]ache/
214 |
215 | # Others
216 | ClientBin/
217 | ~$*
218 | *~
219 | *.dbmdl
220 | *.dbproj.schemaview
221 | *.jfm
222 | *.pfx
223 | *.publishsettings
224 | orleans.codegen.cs
225 |
226 | # Including strong name files can present a security risk
227 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
228 | #*.snk
229 |
230 | # Since there are multiple workflows, uncomment next line to ignore bower_components
231 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
232 | #bower_components/
233 |
234 | # RIA/Silverlight projects
235 | Generated_Code/
236 |
237 | # Backup & report files from converting an old project file
238 | # to a newer Visual Studio version. Backup files are not needed,
239 | # because we have git ;-)
240 | _UpgradeReport_Files/
241 | Backup*/
242 | UpgradeLog*.XML
243 | UpgradeLog*.htm
244 | ServiceFabricBackup/
245 | *.rptproj.bak
246 |
247 | # SQL Server files
248 | *.mdf
249 | *.ldf
250 | *.ndf
251 |
252 | # Business Intelligence projects
253 | *.rdl.data
254 | *.bim.layout
255 | *.bim_*.settings
256 | *.rptproj.rsuser
257 | *- Backup*.rdl
258 |
259 | # Microsoft Fakes
260 | FakesAssemblies/
261 |
262 | # GhostDoc plugin setting file
263 | *.GhostDoc.xml
264 |
265 | # Node.js Tools for Visual Studio
266 | .ntvs_analysis.dat
267 | node_modules/
268 |
269 | # Visual Studio 6 build log
270 | *.plg
271 |
272 | # Visual Studio 6 workspace options file
273 | *.opt
274 |
275 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
276 | *.vbw
277 |
278 | # Visual Studio LightSwitch build output
279 | **/*.HTMLClient/GeneratedArtifacts
280 | **/*.DesktopClient/GeneratedArtifacts
281 | **/*.DesktopClient/ModelManifest.xml
282 | **/*.Server/GeneratedArtifacts
283 | **/*.Server/ModelManifest.xml
284 | _Pvt_Extensions
285 |
286 | # Paket dependency manager
287 | .paket/paket.exe
288 | paket-files/
289 |
290 | # FAKE - F# Make
291 | .fake/
292 |
293 | # JetBrains Rider
294 | .idea/
295 | *.sln.iml
296 |
297 | # CodeRush personal settings
298 | .cr/personal
299 |
300 | # Python Tools for Visual Studio (PTVS)
301 | __pycache__/
302 | *.pyc
303 |
304 | # Cake - Uncomment if you are using it
305 | # tools/**
306 | # !tools/packages.config
307 |
308 | # Tabs Studio
309 | *.tss
310 |
311 | # Telerik's JustMock configuration file
312 | *.jmconfig
313 |
314 | # BizTalk build output
315 | *.btp.cs
316 | *.btm.cs
317 | *.odx.cs
318 | *.xsd.cs
319 |
320 | # OpenCover UI analysis results
321 | OpenCover/
322 |
323 | # Azure Stream Analytics local run output
324 | ASALocalRun/
325 |
326 | # MSBuild Binary and Structured Log
327 | *.binlog
328 |
329 | # NVidia Nsight GPU debugger configuration file
330 | *.nvuser
331 |
332 | # MFractors (Xamarin productivity tool) working folder
333 | .mfractor/
334 |
335 | # Local History for Visual Studio
336 | .localhistory/
337 |
338 | # BeatPulse healthcheck temp database
339 | healthchecksdb
340 | /Library
341 | /Temp
342 | /UserSettings
343 |
--------------------------------------------------------------------------------
/ProjectSettings/QualitySettings.asset:
--------------------------------------------------------------------------------
1 | %YAML 1.1
2 | %TAG !u! tag:unity3d.com,2011:
3 | --- !u!47 &1
4 | QualitySettings:
5 | m_ObjectHideFlags: 0
6 | serializedVersion: 5
7 | m_CurrentQuality: 5
8 | m_QualitySettings:
9 | - serializedVersion: 2
10 | name: Very Low
11 | pixelLightCount: 0
12 | shadows: 0
13 | shadowResolution: 0
14 | shadowProjection: 1
15 | shadowCascades: 1
16 | shadowDistance: 15
17 | shadowNearPlaneOffset: 3
18 | shadowCascade2Split: 0.33333334
19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
20 | shadowmaskMode: 0
21 | blendWeights: 1
22 | textureQuality: 1
23 | anisotropicTextures: 0
24 | antiAliasing: 0
25 | softParticles: 0
26 | softVegetation: 0
27 | realtimeReflectionProbes: 0
28 | billboardsFaceCameraPosition: 0
29 | vSyncCount: 0
30 | lodBias: 0.3
31 | maximumLODLevel: 0
32 | streamingMipmapsActive: 0
33 | streamingMipmapsAddAllCameras: 1
34 | streamingMipmapsMemoryBudget: 512
35 | streamingMipmapsRenderersPerFrame: 512
36 | streamingMipmapsMaxLevelReduction: 2
37 | streamingMipmapsMaxFileIORequests: 1024
38 | particleRaycastBudget: 4
39 | asyncUploadTimeSlice: 2
40 | asyncUploadBufferSize: 16
41 | asyncUploadPersistentBuffer: 1
42 | resolutionScalingFixedDPIFactor: 1
43 | excludedTargetPlatforms: []
44 | - serializedVersion: 2
45 | name: Low
46 | pixelLightCount: 0
47 | shadows: 0
48 | shadowResolution: 0
49 | shadowProjection: 1
50 | shadowCascades: 1
51 | shadowDistance: 20
52 | shadowNearPlaneOffset: 3
53 | shadowCascade2Split: 0.33333334
54 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
55 | shadowmaskMode: 0
56 | blendWeights: 2
57 | textureQuality: 0
58 | anisotropicTextures: 0
59 | antiAliasing: 0
60 | softParticles: 0
61 | softVegetation: 0
62 | realtimeReflectionProbes: 0
63 | billboardsFaceCameraPosition: 0
64 | vSyncCount: 0
65 | lodBias: 0.4
66 | maximumLODLevel: 0
67 | streamingMipmapsActive: 0
68 | streamingMipmapsAddAllCameras: 1
69 | streamingMipmapsMemoryBudget: 512
70 | streamingMipmapsRenderersPerFrame: 512
71 | streamingMipmapsMaxLevelReduction: 2
72 | streamingMipmapsMaxFileIORequests: 1024
73 | particleRaycastBudget: 16
74 | asyncUploadTimeSlice: 2
75 | asyncUploadBufferSize: 16
76 | asyncUploadPersistentBuffer: 1
77 | resolutionScalingFixedDPIFactor: 1
78 | excludedTargetPlatforms: []
79 | - serializedVersion: 2
80 | name: Medium
81 | pixelLightCount: 1
82 | shadows: 1
83 | shadowResolution: 0
84 | shadowProjection: 1
85 | shadowCascades: 1
86 | shadowDistance: 20
87 | shadowNearPlaneOffset: 3
88 | shadowCascade2Split: 0.33333334
89 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
90 | shadowmaskMode: 0
91 | blendWeights: 2
92 | textureQuality: 0
93 | anisotropicTextures: 1
94 | antiAliasing: 0
95 | softParticles: 0
96 | softVegetation: 0
97 | realtimeReflectionProbes: 0
98 | billboardsFaceCameraPosition: 0
99 | vSyncCount: 1
100 | lodBias: 0.7
101 | maximumLODLevel: 0
102 | streamingMipmapsActive: 0
103 | streamingMipmapsAddAllCameras: 1
104 | streamingMipmapsMemoryBudget: 512
105 | streamingMipmapsRenderersPerFrame: 512
106 | streamingMipmapsMaxLevelReduction: 2
107 | streamingMipmapsMaxFileIORequests: 1024
108 | particleRaycastBudget: 64
109 | asyncUploadTimeSlice: 2
110 | asyncUploadBufferSize: 16
111 | asyncUploadPersistentBuffer: 1
112 | resolutionScalingFixedDPIFactor: 1
113 | excludedTargetPlatforms: []
114 | - serializedVersion: 2
115 | name: High
116 | pixelLightCount: 2
117 | shadows: 2
118 | shadowResolution: 1
119 | shadowProjection: 1
120 | shadowCascades: 2
121 | shadowDistance: 40
122 | shadowNearPlaneOffset: 3
123 | shadowCascade2Split: 0.33333334
124 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
125 | shadowmaskMode: 1
126 | blendWeights: 2
127 | textureQuality: 0
128 | anisotropicTextures: 1
129 | antiAliasing: 0
130 | softParticles: 0
131 | softVegetation: 1
132 | realtimeReflectionProbes: 1
133 | billboardsFaceCameraPosition: 1
134 | vSyncCount: 1
135 | lodBias: 1
136 | maximumLODLevel: 0
137 | streamingMipmapsActive: 0
138 | streamingMipmapsAddAllCameras: 1
139 | streamingMipmapsMemoryBudget: 512
140 | streamingMipmapsRenderersPerFrame: 512
141 | streamingMipmapsMaxLevelReduction: 2
142 | streamingMipmapsMaxFileIORequests: 1024
143 | particleRaycastBudget: 256
144 | asyncUploadTimeSlice: 2
145 | asyncUploadBufferSize: 16
146 | asyncUploadPersistentBuffer: 1
147 | resolutionScalingFixedDPIFactor: 1
148 | excludedTargetPlatforms: []
149 | - serializedVersion: 2
150 | name: Very High
151 | pixelLightCount: 3
152 | shadows: 2
153 | shadowResolution: 2
154 | shadowProjection: 1
155 | shadowCascades: 2
156 | shadowDistance: 70
157 | shadowNearPlaneOffset: 3
158 | shadowCascade2Split: 0.33333334
159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
160 | shadowmaskMode: 1
161 | blendWeights: 4
162 | textureQuality: 0
163 | anisotropicTextures: 2
164 | antiAliasing: 2
165 | softParticles: 1
166 | softVegetation: 1
167 | realtimeReflectionProbes: 1
168 | billboardsFaceCameraPosition: 1
169 | vSyncCount: 1
170 | lodBias: 1.5
171 | maximumLODLevel: 0
172 | streamingMipmapsActive: 0
173 | streamingMipmapsAddAllCameras: 1
174 | streamingMipmapsMemoryBudget: 512
175 | streamingMipmapsRenderersPerFrame: 512
176 | streamingMipmapsMaxLevelReduction: 2
177 | streamingMipmapsMaxFileIORequests: 1024
178 | particleRaycastBudget: 1024
179 | asyncUploadTimeSlice: 2
180 | asyncUploadBufferSize: 16
181 | asyncUploadPersistentBuffer: 1
182 | resolutionScalingFixedDPIFactor: 1
183 | excludedTargetPlatforms: []
184 | - serializedVersion: 2
185 | name: Ultra
186 | pixelLightCount: 4
187 | shadows: 2
188 | shadowResolution: 2
189 | shadowProjection: 1
190 | shadowCascades: 4
191 | shadowDistance: 150
192 | shadowNearPlaneOffset: 3
193 | shadowCascade2Split: 0.33333334
194 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667}
195 | shadowmaskMode: 1
196 | blendWeights: 4
197 | textureQuality: 0
198 | anisotropicTextures: 2
199 | antiAliasing: 2
200 | softParticles: 1
201 | softVegetation: 1
202 | realtimeReflectionProbes: 1
203 | billboardsFaceCameraPosition: 1
204 | vSyncCount: 1
205 | lodBias: 2
206 | maximumLODLevel: 0
207 | streamingMipmapsActive: 0
208 | streamingMipmapsAddAllCameras: 1
209 | streamingMipmapsMemoryBudget: 512
210 | streamingMipmapsRenderersPerFrame: 512
211 | streamingMipmapsMaxLevelReduction: 2
212 | streamingMipmapsMaxFileIORequests: 1024
213 | particleRaycastBudget: 4096
214 | asyncUploadTimeSlice: 2
215 | asyncUploadBufferSize: 16
216 | asyncUploadPersistentBuffer: 1
217 | resolutionScalingFixedDPIFactor: 1
218 | excludedTargetPlatforms: []
219 | m_PerPlatformDefaultQuality:
220 | Android: 2
221 | Lumin: 5
222 | Nintendo 3DS: 5
223 | Nintendo Switch: 5
224 | PS4: 5
225 | PSP2: 2
226 | Standalone: 5
227 | WebGL: 3
228 | Windows Store Apps: 5
229 | XboxOne: 5
230 | iPhone: 2
231 | tvOS: 2
232 |
--------------------------------------------------------------------------------
/Assets/Cyclone/Particles/Constraints/ParticleContact.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 | using Cyclone.Particles;
6 |
7 | namespace Cyclone.Particles.Constraints
8 | {
9 | ///
10 | /// A Contact represents two objects in contact (in this case
11 | /// ParticleContact representing two Particles). Resolving a
12 | /// contact removes their interpenetration, and applies sufficient
13 | /// impulse to keep them apart.Colliding bodies may also rebound.
14 | ///
15 | /// The contact has no callable functions, it just holds the
16 | /// contact details. To resolve a set of contacts, use the particle
17 | /// contact resolver class.
18 | ///
19 | public class ParticleContact
20 | {
21 | ///
22 | /// Holds the particles that are involved in the contact. The
23 | /// second of these can be NULL, for contacts with the scenery.
24 | ///
25 | public Particle[] Particles;
26 |
27 | ///
28 | /// Holds the normal restitution coefficient at the contact.
29 | ///
30 | public double Restitution;
31 |
32 | ///
33 | /// Holds the direction of the contact in world coordinates.
34 | ///
35 | public Vector3d ContactNormal;
36 |
37 | ///
38 | /// Holds the depth of penetration at the contact.
39 | ///
40 | public double Penetration;
41 |
42 | ///
43 | /// Holds the amount each particle is moved by during
44 | /// interpenetration resolution.
45 | ///
46 | public Vector3d[] ParticlesMovement;
47 |
48 | ///
49 | ///
50 | ///
51 | public ParticleContact()
52 | {
53 | Particles = new Particle[2];
54 | ParticlesMovement = new Vector3d[2];
55 | }
56 |
57 | ///
58 | ///
59 | ///
60 | public void Clear()
61 | {
62 | Particles[0] = null;
63 | Particles[1] = null;
64 | }
65 |
66 | ///
67 | /// Resolves this contact, for both velocity and interpenetration.
68 | ///
69 | ///
70 | public void Resolve(double dt)
71 | {
72 | ResolveVelocity(dt);
73 | ResolveInterpenetration(dt);
74 | }
75 |
76 | ///
77 | /// Calculates the separating velocity at this contact.
78 | ///
79 | ///
80 | public double CalculateSeparatingVelocity()
81 | {
82 | Vector3d relativeVelocity = Particles[0].Velocity;
83 | if (Particles[1] != null)
84 | relativeVelocity -= Particles[1].Velocity;
85 |
86 | return Vector3d.Dot(relativeVelocity, ContactNormal);
87 | }
88 |
89 | ///
90 | /// Handles the impulse calculations for this collision.
91 | ///
92 | ///
93 | private void ResolveVelocity(double dt)
94 | {
95 | // Find the velocity in the direction of the contact
96 | double separatingVelocity = CalculateSeparatingVelocity();
97 |
98 | // Check if it needs to be resolved
99 | if (separatingVelocity > 0)
100 | {
101 | // The contact is either separating, or stationary - there's
102 | // no impulse required.
103 | return;
104 | }
105 |
106 | // Calculate the new separating velocity
107 | double newSepVelocity = -separatingVelocity * Restitution;
108 |
109 | // Check the velocity build-up due to acceleration only
110 | Vector3d accCausedVelocity = Particles[0].Acceleration;
111 | if (Particles[1] != null) accCausedVelocity -= Particles[1].Acceleration;
112 | double accCausedSepVelocity = Vector3d.Dot(accCausedVelocity, ContactNormal) * dt;
113 |
114 | // If we've got a closing velocity due to acceleration build-up,
115 | // remove it from the new separating velocity
116 | if (accCausedSepVelocity < 0)
117 | {
118 | newSepVelocity += Restitution * accCausedSepVelocity;
119 |
120 | // Make sure we haven't removed more than was
121 | // there to remove.
122 | if (newSepVelocity < 0) newSepVelocity = 0;
123 | }
124 |
125 | double deltaVelocity = newSepVelocity - separatingVelocity;
126 |
127 | // We apply the change in velocity to each object in proportion to
128 | // their inverse mass (i.e. those with lower inverse mass [higher
129 | // actual mass] get less change in velocity)..
130 | double totalInverseMass = Particles[0].InverseMass;
131 | if (Particles[1] != null) totalInverseMass += Particles[1].InverseMass;
132 |
133 | // If all m_particless have infinite mass, then impulses have no effect
134 | if (totalInverseMass <= 0) return;
135 |
136 | // Calculate the impulse to apply
137 | double impulse = deltaVelocity / totalInverseMass;
138 |
139 | // Find the amount of impulse per unit of inverse mass
140 | Vector3d impulsePerIMass = ContactNormal * impulse;
141 |
142 | // Apply impulses: they are applied in the direction of the contact,
143 | // and are proportional to the inverse mass.
144 | Particles[0].Velocity += impulsePerIMass * Particles[0].InverseMass;
145 |
146 | if (Particles[1] != null)
147 | {
148 | // Particle 1 goes in the opposite direction
149 | Particles[1].Velocity += impulsePerIMass * -Particles[1].InverseMass;
150 | }
151 | }
152 |
153 | ///
154 | /// Handles the interpenetration resolution for this contact.
155 | ///
156 | ///
157 | private void ResolveInterpenetration(double dt)
158 | {
159 | // If we don't have any penetration, skip this step.
160 | if (Penetration <= 0) return;
161 |
162 | // The movement of each object is based on their inverse mass, so
163 | // total that.
164 | double totalInverseMass = Particles[0].InverseMass;
165 | if (Particles[1] != null) totalInverseMass += Particles[1].InverseMass;
166 |
167 | // If all m_particless have infinite mass, then we do nothing
168 | if (totalInverseMass <= 0) return;
169 |
170 | // Find the amount of penetration resolution per unit of inverse mass
171 | Vector3d movePerIMass = ContactNormal * (Penetration / totalInverseMass);
172 |
173 | // Calculate the the movement amounts
174 | ParticlesMovement[0] = movePerIMass * Particles[0].InverseMass;
175 | if (Particles[1] != null)
176 | ParticlesMovement[1] = movePerIMass * -Particles[1].InverseMass;
177 | else
178 | ParticlesMovement[1] = Vector3d.Zero;
179 |
180 | // Apply the penetration resolution
181 | Particles[0].Position += ParticlesMovement[0];
182 | if (Particles[1] != null)
183 | Particles[1].Position += ParticlesMovement[1];
184 | }
185 |
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/Assets/CommonUnity/Drawing/SegmentRenderer.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using System;
3 | using System.Collections.Generic;
4 |
5 | using Cyclone.Core;
6 |
7 | namespace Common.Unity.Drawing
8 | {
9 |
10 | public enum LINE_MODE { LINES = 2, TRIANGLES = 3, TETRAHEDRON = 4 };
11 |
12 | public class SegmentRenderer : BaseRenderer
13 | {
14 |
15 | public SegmentRenderer()
16 | {
17 | LineMode = LINE_MODE.LINES;
18 | }
19 |
20 | public SegmentRenderer(LINE_MODE lineMode, DRAW_ORIENTATION orientation)
21 | {
22 | LineMode = LINE_MODE.LINES;
23 | Orientation = DRAW_ORIENTATION.XY;
24 | }
25 |
26 | public LINE_MODE LineMode { get; set; }
27 |
28 | #region DOUBLE
29 |
30 | public void Load(IList vertices, IList indices = null)
31 | {
32 | SetIndices(vertices.Count, indices);
33 |
34 | foreach (var v in vertices)
35 | m_vertices.Add(v.ToVector4());
36 | }
37 |
38 | public void Load(Vector3d a, Vector3d b)
39 | {
40 | SetIndices(2, null);
41 |
42 | m_vertices.Add(a.ToVector4());
43 | m_vertices.Add(b.ToVector4());
44 | }
45 |
46 | #endregion
47 |
48 | #region UNITY
49 |
50 | public void Load(IList vertices, IList indices = null)
51 | {
52 | SetIndices(vertices.Count, indices);
53 |
54 | foreach (var v in vertices)
55 | m_vertices.Add(v);
56 | }
57 |
58 | public void Load(IList vertices, IList indices = null)
59 | {
60 | SetIndices(vertices.Count, indices);
61 |
62 | foreach (var v in vertices)
63 | m_vertices.Add(v);
64 | }
65 |
66 | public void Load(Vector3 a, Vector3 b)
67 | {
68 | SetIndices(2, null);
69 |
70 | m_vertices.Add(a);
71 | m_vertices.Add(b);
72 | }
73 |
74 | public void Load(IList vertices, IList indices = null)
75 | {
76 | SetIndices(vertices.Count, indices);
77 |
78 | foreach (var v in vertices)
79 | m_vertices.Add(v);
80 | }
81 |
82 | public void Load(Vector2 a, Vector2 b)
83 | {
84 | SetIndices(2, null);
85 |
86 | if (Orientation == DRAW_ORIENTATION.XY)
87 | {
88 | m_vertices.Add(a);
89 | m_vertices.Add(b);
90 | }
91 | else if (Orientation == DRAW_ORIENTATION.XZ)
92 | {
93 | m_vertices.Add(new Vector4(a.x, 0, a.y, 1));
94 | m_vertices.Add(new Vector4(b.x, 0, b.y, 1));
95 | }
96 | }
97 |
98 | #endregion
99 |
100 | #region DRAW
101 |
102 | public override void Draw(Camera camera, Matrix4x4 localToWorld)
103 | {
104 | switch (LineMode)
105 | {
106 | case LINE_MODE.LINES:
107 | DrawVerticesAsLines(camera, localToWorld);
108 | break;
109 |
110 | case LINE_MODE.TRIANGLES:
111 | DrawVerticesAsTriangles(camera, localToWorld);
112 | break;
113 |
114 | case LINE_MODE.TETRAHEDRON:
115 | DrawVerticesAsTetrahedron(camera, localToWorld);
116 | break;
117 | }
118 | }
119 |
120 | private void DrawVerticesAsLines(Camera camera, Matrix4x4 localToWorld)
121 | {
122 | GL.PushMatrix();
123 |
124 | GL.LoadIdentity();
125 | GL.modelview = camera.worldToCameraMatrix * localToWorld;
126 | GL.LoadProjectionMatrix(camera.projectionMatrix);
127 |
128 | Material.SetPass(0);
129 | GL.Begin(GL.LINES);
130 | GL.Color(Color);
131 |
132 | int vertexCount = m_vertices.Count;
133 |
134 | for (int i = 0; i < m_indices.Count / 2; i++)
135 | {
136 | int i0 = m_indices[i * 2 + 0];
137 | int i1 = m_indices[i * 2 + 1];
138 |
139 | if (i0 < 0 || i0 >= vertexCount) continue;
140 | if (i1 < 0 || i1 >= vertexCount) continue;
141 |
142 | GL.Vertex(m_vertices[i0]);
143 | GL.Vertex(m_vertices[i1]);
144 | }
145 |
146 | GL.End();
147 |
148 | GL.PopMatrix();
149 | }
150 |
151 | private void DrawVerticesAsTriangles(Camera camera, Matrix4x4 localToWorld)
152 | {
153 | GL.PushMatrix();
154 |
155 | GL.LoadIdentity();
156 | GL.MultMatrix(camera.worldToCameraMatrix * localToWorld);
157 | GL.LoadProjectionMatrix(camera.projectionMatrix);
158 |
159 | Material.SetPass(0);
160 | GL.Begin(GL.LINES);
161 | GL.Color(Color);
162 |
163 | int vertexCount = m_vertices.Count;
164 |
165 | for (int i = 0; i < m_indices.Count / 3; i++)
166 | {
167 | int i0 = m_indices[i * 3 + 0];
168 | int i1 = m_indices[i * 3 + 1];
169 | int i2 = m_indices[i * 3 + 2];
170 |
171 | if (i0 < 0 || i0 >= vertexCount) continue;
172 | if (i1 < 0 || i1 >= vertexCount) continue;
173 | if (i2 < 0 || i2 >= vertexCount) continue;
174 |
175 | GL.Vertex(m_vertices[i0]);
176 | GL.Vertex(m_vertices[i1]);
177 |
178 | GL.Vertex(m_vertices[i0]);
179 | GL.Vertex(m_vertices[i2]);
180 |
181 | GL.Vertex(m_vertices[i2]);
182 | GL.Vertex(m_vertices[i1]);
183 | }
184 |
185 | GL.End();
186 |
187 | GL.PopMatrix();
188 | }
189 |
190 | private void DrawVerticesAsTetrahedron(Camera camera, Matrix4x4 localToWorld)
191 | {
192 | GL.PushMatrix();
193 |
194 | GL.LoadIdentity();
195 | GL.MultMatrix(camera.worldToCameraMatrix * localToWorld);
196 | GL.LoadProjectionMatrix(camera.projectionMatrix);
197 |
198 | Material.SetPass(0);
199 | GL.Begin(GL.LINES);
200 | GL.Color(Color);
201 |
202 | int vertexCount = m_vertices.Count;
203 |
204 | for (int i = 0; i < m_indices.Count / 4; i++)
205 | {
206 | int i0 = m_indices[i * 4 + 0];
207 | int i1 = m_indices[i * 4 + 1];
208 | int i2 = m_indices[i * 4 + 2];
209 | int i3 = m_indices[i * 4 + 3];
210 |
211 | if (i0 < 0 || i0 >= vertexCount) continue;
212 | if (i1 < 0 || i1 >= vertexCount) continue;
213 | if (i2 < 0 || i2 >= vertexCount) continue;
214 | if (i3 < 0 || i3 >= vertexCount) continue;
215 |
216 | GL.Vertex(m_vertices[i0]);
217 | GL.Vertex(m_vertices[i1]);
218 |
219 | GL.Vertex(m_vertices[i0]);
220 | GL.Vertex(m_vertices[i2]);
221 |
222 | GL.Vertex(m_vertices[i0]);
223 | GL.Vertex(m_vertices[i3]);
224 |
225 | GL.Vertex(m_vertices[i1]);
226 | GL.Vertex(m_vertices[i2]);
227 |
228 | GL.Vertex(m_vertices[i3]);
229 | GL.Vertex(m_vertices[i2]);
230 |
231 | GL.Vertex(m_vertices[i1]);
232 | GL.Vertex(m_vertices[i3]);
233 | }
234 |
235 | GL.End();
236 |
237 | GL.PopMatrix();
238 | }
239 |
240 | #endregion
241 |
242 | }
243 |
244 | }
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/Matrix4.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Cyclone.Core
5 | {
6 |
7 | ///
8 | /// Holds a transform matrix, consisting of a rotation matrix and
9 | /// a position.The matrix has 12 elements, it is assumed that the
10 | /// remaining four are(0,0,0,1); producing a homogenous matrix.
11 | ///
12 | public struct Matrix4
13 | {
14 |
15 | public double data0, data1, data2, data3;
16 | public double data4, data5, data6, data7;
17 | public double data8, data9, data10, data11;
18 |
19 |
20 | ///
21 | /// Creates an identity matrix.
22 | ///
23 | static readonly public Matrix4 Identity = new Matrix4(1, 0, 0, 0,
24 | 0, 1, 0, 0,
25 | 0, 0, 1, 0);
26 |
27 |
28 | public Matrix4(double m0, double m1, double m2, double m3,
29 | double m4, double m5, double m6, double m7,
30 | double m8, double m9, double m10, double m11)
31 | {
32 | data0 = m0; data1 = m1; data2 = m2; data3 = m3;
33 | data4 = m4; data5 = m5; data6 = m6; data7 = m7;
34 | data8 = m8; data9 = m9; data10 = m10; data11 = m11;
35 | }
36 |
37 | ///
38 | /// Access the varible at index i
39 | ///
40 | unsafe public double this[int i]
41 | {
42 | get
43 | {
44 | if ((uint)i >= 12)
45 | throw new IndexOutOfRangeException("Matrix4 index out of range.");
46 |
47 | fixed (Matrix4* array = &this) { return ((double*)array)[i]; }
48 | }
49 | set
50 | {
51 | if ((uint)i >= 12)
52 | throw new IndexOutOfRangeException("Matrix4 index out of range.");
53 |
54 | fixed (double* array = &data0) { array[i] = value; }
55 | }
56 | }
57 |
58 | ///
59 | /// Returns a matrix which is this matrix multiplied by the given
60 | /// other matrix.
61 | ///
62 | public static Matrix4 operator *(Matrix4 m1, Matrix4 m2)
63 | {
64 | Matrix4 result = new Matrix4();
65 | result.data0 = (m2.data0 * m1.data0) + (m2.data4 * m1.data1) + (m2.data8 * m1.data2);
66 | result.data4 = (m2.data0 * m1.data4) + (m2.data4 * m1.data5) + (m2.data8 * m1.data6);
67 | result.data8 = (m2.data0 * m1.data8) + (m2.data4 * m1.data9) + (m2.data8 * m1.data10);
68 |
69 | result.data1 = (m2.data1 * m1.data0) + (m2.data5 * m1.data1) + (m2.data9 * m1.data2);
70 | result.data5 = (m2.data1 * m1.data4) + (m2.data5 * m1.data5) + (m2.data9 * m1.data6);
71 | result.data9 = (m2.data1 * m1.data8) + (m2.data5 * m1.data9) + (m2.data9 * m1.data10);
72 |
73 | result.data2 = (m2.data2 * m1.data0) + (m2.data6 * m1.data1) + (m2.data10 * m1.data2);
74 | result.data6 = (m2.data2 * m1.data4) + (m2.data6 * m1.data5) + (m2.data10 * m1.data6);
75 | result.data10 = (m2.data2 * m1.data8) + (m2.data6 * m1.data9) + (m2.data10 * m1.data10);
76 |
77 | result.data3 = (m2.data3 * m1.data0) + (m2.data7 * m1.data1) + (m2.data11 * m1.data2) + m1.data3;
78 | result.data7 = (m2.data3 * m1.data4) + (m2.data7 * m1.data5) + (m2.data11 * m1.data6) + m1.data7;
79 | result.data11 = (m2.data3 * m1.data8) + (m2.data7 * m1.data9) + (m2.data11 * m1.data10) + m1.data11;
80 |
81 | return result;
82 | }
83 |
84 | ///
85 | /// Transform the given vector by this matrix.
86 | ///
87 | public static Vector3d operator *(Matrix4 m, Vector3d vector)
88 | {
89 | return new Vector3d(
90 | vector.x * m.data0 +
91 | vector.y * m.data1 +
92 | vector.z * m.data2 + m.data3,
93 |
94 | vector.x * m.data4 +
95 | vector.y * m.data5 +
96 | vector.z * m.data6 + m.data7,
97 |
98 | vector.x * m.data8 +
99 | vector.y * m.data9 +
100 | vector.z * m.data10 + m.data11
101 | );
102 | }
103 |
104 | ///
105 | /// A matrix as a string.
106 | ///
107 | public override string ToString()
108 | {
109 | return data0 + "," + data1 + "," + data2 + "," + data3 + "\n" +
110 | data4 + "," + data5 + "," + data6 + "," + data7 + "\n" +
111 | data8 + "," + data9 + "," + data10 + "," + data11;
112 | }
113 |
114 | ///
115 | /// Sets the matrix to be a diagonal matrix with the given coefficients.
116 | ///
117 | public void SetDiagonal(double a, double b, double c)
118 | {
119 | data0 = a;
120 | data5 = b;
121 | data10 = c;
122 | }
123 |
124 | ///
125 | /// Transform the given vector by this matrix.
126 | ///
127 | public Vector3d Transform(Vector3d vector)
128 | {
129 | return this * vector;
130 | }
131 |
132 | ///
133 | /// Returns the determinant of the matrix.
134 | ///
135 | public double GetDeterminant()
136 | {
137 | return -data8 * data5 * data2 +
138 | data4 * data9 * data2 +
139 | data8 * data1 * data6 -
140 | data0 * data9 * data6 -
141 | data4 * data1 * data10 +
142 | data0 * data5 * data10;
143 | }
144 |
145 | ///
146 | /// Sets the matrix to be the inverse of the given matrix.
147 | ///
148 | public void SetInverse(Matrix4 m)
149 | {
150 | // Make sure the determinant is non-zero.
151 | double det = m.GetDeterminant();
152 | if (det == 0) return;
153 | det = 1.0 / det;
154 |
155 | data0 = (-m.data9 * m.data6 + m.data5 * m.data10) * det;
156 | data4 = (m.data8 * m.data6 - m.data4 * m.data10) * det;
157 | data8 = (-m.data8 * m.data5 + m.data4 * m.data9) * det;
158 |
159 | data1 = (m.data9 * m.data2 - m.data1 * m.data10) * det;
160 | data5 = (-m.data8 * m.data2 + m.data0 * m.data10) * det;
161 | data9 = (m.data8 * m.data1 - m.data0 * m.data9) * det;
162 |
163 | data2 = (-m.data5 * m.data2 + m.data1 * m.data6) * det;
164 | data6 = (+m.data4 * m.data2 - m.data0 * m.data6) * det;
165 | data10 = (-m.data4 * m.data1 + m.data0 * m.data5) * det;
166 |
167 | data3 = (m.data9 * m.data6 * m.data3
168 | - m.data5 * m.data10 * m.data3
169 | - m.data9 * m.data2 * m.data7
170 | + m.data1 * m.data10 * m.data7
171 | + m.data5 * m.data2 * m.data11
172 | - m.data1 * m.data6 * m.data11) * det;
173 | data7 = (-m.data8 * m.data6 * m.data3
174 | + m.data4 * m.data10 * m.data3
175 | + m.data8 * m.data2 * m.data7
176 | - m.data0 * m.data10 * m.data7
177 | - m.data4 * m.data2 * m.data11
178 | + m.data0 * m.data6 * m.data11) * det;
179 | data11 = (m.data8 * m.data5 * m.data3
180 | - m.data4 * m.data9 * m.data3
181 | - m.data8 * m.data1 * m.data7
182 | + m.data0 * m.data9 * m.data7
183 | + m.data4 * m.data1 * m.data11
184 | - m.data0 * m.data5 * m.data11) * det;
185 | }
186 |
187 | ///
188 | /// Returns a new matrix containing the inverse of this matrix.
189 | ///
190 | public Matrix4 Inverse()
191 | {
192 | Matrix4 result = Matrix4.Identity;
193 | result.SetInverse(this);
194 | return result;
195 | }
196 |
197 | ///
198 | /// Inverts the matrix.
199 | ///
200 | public void Invert()
201 | {
202 | SetInverse(this);
203 | }
204 |
205 | ///
206 | /// Transform the given direction vector by this matrix.
207 | ///
208 | /// @note When a direction is converted between frames of
209 | /// reference, there is no translation required.
210 | ///
211 | public Vector3d TransformDirection(Vector3d vector)
212 | {
213 | return new Vector3d(
214 | vector.x * data0 +
215 | vector.y * data1 +
216 | vector.z * data2,
217 |
218 | vector.x * data4 +
219 | vector.y * data5 +
220 | vector.z * data6,
221 |
222 | vector.x * data8 +
223 | vector.y * data9 +
224 | vector.z * data10
225 | );
226 | }
227 |
228 | ///
229 | /// Transform the given direction vector by the
230 | /// transformational inverse of this matrix.
231 | ///
232 | /// @note This function relies on the fact that the inverse of
233 | /// a pure rotation matrix is its transpose. It separates the
234 | /// translational and rotation components, transposes the
235 | /// rotation, and multiplies out. If the matrix is not a
236 | /// scale and shear free transform matrix, then this function
237 | /// will not give correct results.
238 | ///
239 | /// @note When a direction is converted between frames of
240 | /// reference, there is no translation required.
241 | ///
242 | public Vector3d TransformInverseDirection(Vector3d vector)
243 | {
244 | return new Vector3d(
245 | vector.x * data0 +
246 | vector.y * data4 +
247 | vector.z * data8,
248 |
249 | vector.x * data1 +
250 | vector.y * data5 +
251 | vector.z * data9,
252 |
253 | vector.x * data2 +
254 | vector.y * data6 +
255 | vector.z * data10
256 | );
257 | }
258 |
259 | ///
260 | /// Transform the given vector by the transformational inverse
261 | /// of this matrix.
262 | ///
263 | /// @note This function relies on the fact that the inverse of
264 | /// a pure rotation matrix is its transpose. It separates the
265 | /// translational and rotation components, transposes the
266 | /// rotation, and multiplies out. If the matrix is not a
267 | /// scale and shear free transform matrix, then this function
268 | /// will not give correct results.
269 | ///
270 | public Vector3d TransformInverse(Vector3d vector)
271 | {
272 | Vector3d tmp = vector;
273 | tmp.x -= data3;
274 | tmp.y -= data7;
275 | tmp.z -= data11;
276 | return new Vector3d(
277 | tmp.x * data0 +
278 | tmp.y * data4 +
279 | tmp.z * data8,
280 |
281 | tmp.x * data1 +
282 | tmp.y * data5 +
283 | tmp.z * data9,
284 |
285 | tmp.x * data2 +
286 | tmp.y * data6 +
287 | tmp.z * data10
288 | );
289 | }
290 |
291 | ///
292 | /// Gets a vector representing one axis (i.e. one column) in the matrix.
293 | ///
294 | /// The row to return. Row 3 corresponds
295 | /// to the position of the transform matrix.
296 | ///
297 | public Vector3d GetAxisVector(int i)
298 | {
299 | return new Vector3d(this[i], this[i + 4], this[i + 8]);
300 | }
301 |
302 | /**
303 | * Sets this matrix to be the rotation matrix corresponding to
304 | * the given quaternion.
305 | */
306 | public void SetOrientationAndPos(Quaternion q, Vector3d pos)
307 | {
308 | data0 = 1 - (2 * q.j * q.j + 2 * q.k * q.k);
309 | data1 = 2 * q.i * q.j + 2 * q.k * q.r;
310 | data2 = 2 * q.i * q.k - 2 * q.j * q.r;
311 | data3 = pos.x;
312 |
313 | data4 = 2 * q.i * q.j - 2 * q.k * q.r;
314 | data5 = 1 - (2 * q.i * q.i + 2 * q.k * q.k);
315 | data6 = 2 * q.j * q.k + 2 * q.i * q.r;
316 | data7 = pos.y;
317 |
318 | data8 = 2 * q.i * q.k + 2 * q.j * q.r;
319 | data9 = 2 * q.j * q.k - 2 * q.i * q.r;
320 | data10 = 1 - (2 * q.i * q.i + 2 * q.j * q.j);
321 | data11 = pos.z;
322 | }
323 |
324 | }
325 |
326 | }
--------------------------------------------------------------------------------
/Assets/Cyclone/Core/Matrix3.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace Cyclone.Core
5 | {
6 |
7 | ///
8 | /// Holds an inertia tensor, consisting of a 3x3 row-major matrix.
9 | /// This matrix is not padding to produce an aligned structure, since
10 | /// it is most commonly used with a mass(single double) and two
11 | /// damping coefficients to make the 12-element characteristics array
12 | /// of a rigid body.
13 | ///
14 | public struct Matrix3
15 | {
16 | public double data0, data1, data2;
17 | public double data3, data4, data5;
18 | public double data6, data7, data8;
19 |
20 | ///
21 | /// Creates an identity matrix.
22 | ///
23 | static readonly public Matrix3 Identity = new Matrix3(1, 0, 0,
24 | 0, 1, 0,
25 | 0, 0, 1);
26 |
27 |
28 | public Matrix3(double m0, double m1, double m2,
29 | double m3, double m4, double m5,
30 | double m6, double m7, double m8)
31 | {
32 | data0 = m0; data1 = m1; data2 = m2;
33 | data3 = m3; data4 = m4; data5 = m5;
34 | data6 = m6; data7 = m7; data8 = m8;
35 | }
36 |
37 | ///
38 | /// Creates a new matrix with the given three vectors making
39 | /// up its columns.
40 | ///
41 | public Matrix3(Vector3d compOne, Vector3d compTwo, Vector3d compThree)
42 | {
43 | data0 = compOne.x; data1 = compTwo.x; data2 = compThree.x;
44 | data3 = compOne.y; data4 = compTwo.y; data5 = compThree.y;
45 | data6 = compOne.z; data7 = compTwo.z; data8 = compThree.z;
46 | }
47 |
48 | ///
49 | /// Access the varible at index i
50 | ///
51 | unsafe public double this[int i]
52 | {
53 | get
54 | {
55 | if ((uint)i >= 9)
56 | throw new IndexOutOfRangeException("Matrix3 index out of range.");
57 |
58 | fixed (Matrix3* array = &this) { return ((double*)array)[i]; }
59 | }
60 | set
61 | {
62 | if ((uint)i >= 9)
63 | throw new IndexOutOfRangeException("Matrix3 index out of range.");
64 |
65 | fixed (double* array = &data0) { array[i] = value; }
66 | }
67 | }
68 |
69 | ///
70 | /// Transform the given vector by this matrix.
71 | ///
72 | public static Vector3d operator *(Matrix3 m, Vector3d vector)
73 | {
74 | return new Vector3d(
75 | vector.x * m.data0 + vector.y * m.data1 + vector.z * m.data2,
76 | vector.x * m.data3 + vector.y * m.data4 + vector.z * m.data5,
77 | vector.x * m.data6 + vector.y * m.data7 + vector.z * m.data8
78 | );
79 | }
80 |
81 | ///
82 | /// Returns a matrix which is this matrix multiplied by the given
83 | /// other matrix.
84 | ///
85 | public static Matrix3 operator *(Matrix3 m1, Matrix3 m2)
86 | {
87 | return new Matrix3(
88 | m1.data0 * m2.data0 + m1.data1 * m2.data3 + m1.data2 * m2.data6,
89 | m1.data0 * m2.data1 + m1.data1 * m2.data4 + m1.data2 * m2.data7,
90 | m1.data0 * m2.data2 + m1.data1 * m2.data5 + m1.data2 * m2.data8,
91 |
92 | m1.data3 * m2.data0 + m1.data4 * m2.data3 + m1.data5 * m2.data6,
93 | m1.data3 * m2.data1 + m1.data4 * m2.data4 + m1.data5 * m2.data7,
94 | m1.data3 * m2.data2 + m1.data4 * m2.data5 + m1.data5 * m2.data8,
95 |
96 | m1.data6 * m2.data0 + m1.data7 * m2.data3 + m1.data8 * m2.data6,
97 | m1.data6 * m2.data1 + m1.data7 * m2.data4 + m1.data8 * m2.data7,
98 | m1.data6 * m2.data2 + m1.data7 * m2.data5 + m1.data8 * m2.data8
99 | );
100 | }
101 |
102 | ///
103 | /// Multiplies this matrix in place by the given scalar.
104 | ///
105 | public static Matrix3 operator *(Matrix3 m1, double scalar)
106 | {
107 | return new Matrix3(
108 | m1.data0 * scalar, m1.data1 * scalar, m1.data2 * scalar,
109 | m1.data3 * scalar, m1.data4 * scalar, m1.data5 * scalar,
110 | m1.data6 * scalar, m1.data7 * scalar, m1.data8 * scalar);
111 | }
112 |
113 | ///
114 | /// Do a component-wise addition of this matrix and the given
115 | /// matrix.
116 | ///
117 | public static Matrix3 operator +(Matrix3 m1, Matrix3 m2)
118 | {
119 | return new Matrix3(
120 | m1.data0 + m2.data0, m1.data1 + m2.data1, m1.data2 + m2.data2,
121 | m1.data3 + m2.data3, m1.data4 + m2.data4, m1.data5 + m2.data5,
122 | m1.data6 + m2.data6, m1.data7 + m2.data7, m1.data8 + m2.data8);
123 | }
124 |
125 | ///
126 | /// Do a component-wise subtraction of this matrix and the given
127 | /// matrix.
128 | ///
129 | public static Matrix3 operator -(Matrix3 m1, Matrix3 m2)
130 | {
131 | return new Matrix3(
132 | m1.data0 - m2.data0, m1.data1 - m2.data1, m1.data2 - m2.data2,
133 | m1.data3 - m2.data3, m1.data4 - m2.data4, m1.data5 - m2.data5,
134 | m1.data6 - m2.data6, m1.data7 - m2.data7, m1.data8 - m2.data8);
135 | }
136 |
137 | ///
138 | /// A matrix as a string.
139 | ///
140 | public override string ToString()
141 | {
142 | return data0 + "," + data1 + "," + data2 + "\n" +
143 | data3 + "," + data4 + "," + data5 + "\n" +
144 | data6 + "," + data7 + "," + data8;
145 | }
146 |
147 | ///
148 | /// Sets the value of the matrix from inertia tensor values.
149 | ///
150 | public void SetInertiaTensorCoeffs(double ix, double iy, double iz, double ixy = 0, double ixz = 0, double iyz = 0)
151 | {
152 | data0 = ix;
153 | data1 = data3 = -ixy;
154 | data2 = data6 = -ixz;
155 | data4 = iy;
156 | data5 = data7 = -iyz;
157 | data8 = iz;
158 | }
159 |
160 | ///
161 | /// Sets the value of the matrix as an inertia tensor of
162 | /// a rectangular block aligned with the body's coordinate
163 | /// system with the given axis half-sizes and mass.
164 | ///
165 | public void SetBlockInertiaTensor(Vector3d halfSizes, double mass)
166 | {
167 | Vector3d squares = halfSizes * halfSizes;
168 | SetInertiaTensorCoeffs(0.3 * mass * (squares.y + squares.z), 0.3 * mass * (squares.x + squares.z), 0.3 * mass * (squares.x + squares.y));
169 | }
170 |
171 | ///
172 | /// Sets the matrix to be a skew symmetric matrix based on
173 | /// the given vector.The skew symmetric matrix is the equivalent
174 | /// of the vector product.So if a, b are vectors.a x b = A_s b
175 | /// where A_s is the skew symmetric form of a.
176 | ///
177 | public void SetSkewSymmetric(Vector3d vector)
178 | {
179 | data0 = data4 = data8 = 0;
180 | data1 = -vector.z;
181 | data2 = vector.y;
182 | data3 = vector.z;
183 | data5 = -vector.x;
184 | data6 = -vector.y;
185 | data7 = vector.x;
186 | }
187 |
188 | ///
189 | /// Sets the matrix values from the given three vector components.
190 | /// These are arranged as the three columns of the vector.
191 | ///
192 | public void SetComponents(Vector3d compOne, Vector3d compTwo, Vector3d compThree)
193 | {
194 | data0 = compOne.x; data1 = compTwo.x; data2 = compThree.x;
195 | data3 = compOne.y; data4 = compTwo.y; data5 = compThree.y;
196 | data6 = compOne.z; data7 = compTwo.z; data8 = compThree.z;
197 | }
198 |
199 | ///
200 | /// Transform the given vector by this matrix.
201 | ///
202 | public Vector3d Transform(Vector3d vector)
203 | {
204 | return this * vector;
205 | }
206 |
207 | ///
208 | /// Transform the given vector by the transpose of this matrix.
209 | ///
210 | public Vector3d TransformTranspose(Vector3d vector)
211 | {
212 | return new Vector3d(
213 | vector.x * data0 + vector.y * data3 + vector.z * data6,
214 | vector.x * data1 + vector.y * data4 + vector.z * data7,
215 | vector.x * data2 + vector.y * data5 + vector.z * data8
216 | );
217 | }
218 |
219 | ///
220 | /// Gets a vector representing one row in the matrix.
221 | ///
222 | /// The row to return.
223 | public Vector3d GetRowVector(int i)
224 | {
225 | return new Vector3d(this[i * 3], this[i * 3 + 1], this[i * 3 + 2]);
226 | }
227 |
228 | ///
229 | /// Gets a vector representing one axis (i.e. one column) in the matrix.
230 | ///
231 | /// The row to return.
232 | public Vector3d GetAxisVector(int i)
233 | {
234 | return new Vector3d(this[i], this[i + 3], this[i + 6]);
235 | }
236 |
237 | ///
238 | /// Sets the matrix to be the inverse of the given matrix.
239 | ///
240 | public void SetInverse(Matrix3 m)
241 | {
242 | double t4 = m.data0 * m.data4;
243 | double t6 = m.data0 * m.data5;
244 | double t8 = m.data1 * m.data3;
245 | double t10 = m.data2 * m.data3;
246 | double t12 = m.data1 * m.data6;
247 | double t14 = m.data2 * m.data6;
248 |
249 | // Calculate the determinant
250 | double t16 = (t4 * m.data8 - t6 * m.data7 - t8 * m.data8 +
251 | t10 * m.data7 + t12 * m.data5 - t14 * m.data4);
252 |
253 | // Make sure the determinant is non-zero.
254 | if (t16 == 0.0) return;
255 | double t17 = 1 / t16;
256 |
257 | data0 = (m.data4 * m.data8 - m.data5 * m.data7) * t17;
258 | data1 = -(m.data1 * m.data8 - m.data2 * m.data7) * t17;
259 | data2 = (m.data1 * m.data5 - m.data2 * m.data4) * t17;
260 | data3 = -(m.data3 * m.data8 - m.data5 * m.data6) * t17;
261 | data4 = (m.data0 * m.data8 - t14) * t17;
262 | data5 = -(t6 - t10) * t17;
263 | data6 = (m.data3 * m.data7 - m.data4 * m.data6) * t17;
264 | data7 = -(m.data0 * m.data7 - t12) * t17;
265 | data8 = (t4 - t8) * t17;
266 | }
267 |
268 | ///
269 | /// Returns a new matrix containing the inverse of this matrix.
270 | ///
271 | public Matrix3 Inverse()
272 | {
273 | Matrix3 result = Identity;
274 | result.SetInverse(this);
275 | return result;
276 | }
277 |
278 | ///
279 | /// Inverts the matrix.
280 | ///
281 | public void Invert()
282 | {
283 | SetInverse(this);
284 | }
285 |
286 | ///
287 | /// Sets the matrix to be the transpose of the given matrix.
288 | ///
289 | public void SetTranspose(Matrix3 m)
290 | {
291 | data0 = m.data0;
292 | data1 = m.data3;
293 | data2 = m.data6;
294 | data3 = m.data1;
295 | data4 = m.data4;
296 | data5 = m.data7;
297 | data6 = m.data2;
298 | data7 = m.data5;
299 | data8 = m.data8;
300 | }
301 |
302 | ///
303 | /// Returns a new matrix containing the transpose of this matrix.
304 | ///
305 | public Matrix3 Transpose()
306 | {
307 | Matrix3 result = Identity;
308 | result.SetTranspose(this);
309 | return result;
310 | }
311 |
312 | ///
313 | /// Sets this matrix to be the rotation matrix corresponding to
314 | /// the given quaternion.
315 | ///
316 | public void SetOrientation(Quaternion q)
317 | {
318 | data0 = 1 - (2 * q.j * q.j + 2 * q.k * q.k);
319 | data1 = 2 * q.i * q.j + 2 * q.k * q.r;
320 | data2 = 2 * q.i * q.k - 2 * q.j * q.r;
321 | data3 = 2 * q.i * q.j - 2 * q.k * q.r;
322 | data4 = 1 - (2 * q.i * q.i + 2 * q.k * q.k);
323 | data5 = 2 * q.j * q.k + 2 * q.i * q.r;
324 | data6 = 2 * q.i * q.k + 2 * q.j * q.r;
325 | data7 = 2 * q.j * q.k - 2 * q.i * q.r;
326 | data8 = 1 - (2 * q.i * q.i + 2 * q.j * q.j);
327 | }
328 |
329 | ///
330 | /// Interpolates a couple of matrices.
331 | ///
332 | public static Matrix3 LinearInterpolate(Matrix3 a, Matrix3 b, double prop)
333 | {
334 | Matrix3 result = new Matrix3();
335 | for (int i = 0; i < 9; i++)
336 | result[i] = a[i] * (1 - prop) + b[i] * prop;
337 |
338 | return result;
339 | }
340 | }
341 |
342 | }
--------------------------------------------------------------------------------
/Assets/Cyclone/Rigid/Constraints/RigidContactResolver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Cyclone.Core;
5 |
6 | namespace Cyclone.Rigid.Constraints
7 | {
8 |
9 | ///
10 | /// The contact resolution routine. One resolver instance
11 | /// can be shared for the whole simulation, as long as you need
12 | /// roughly the same parameters each time (which is normal).
13 | ///
14 | /// @section algorithm Resolution Algorithm
15 | ///
16 | /// The resolver uses an iterative satisfaction algorithm; it loops
17 | /// through each contact and tries to resolve it. Each contact is
18 | /// resolved locally, which may in turn put other contacts in a worse
19 | /// position. The algorithm then revisits other contacts and repeats
20 | /// the process up to a specified iteration limit. It can be proved
21 | /// that given enough iterations, the simulation will get to the
22 | /// correct result. As with all approaches, numerical stability can
23 | /// cause problems that make a correct resolution impossible.
24 | ///
25 | /// @subsection strengths Strengths
26 | ///
27 | /// This algorithm is very fast, much faster than other physics
28 | /// approaches. Even using many more iterations than there are
29 | /// contacts, it will be faster than global approaches.
30 | ///
31 | /// Many global algorithms are unstable under high friction, this
32 | /// approach is very robust indeed for high friction and low
33 | /// restitution values.
34 | ///
35 | /// The algorithm produces visually believable behaviour. Tradeoffs
36 | /// have been made to err on the side of visual realism rather than
37 | /// computational expense or numerical accuracy.
38 | ///
39 | /// @subsection weaknesses Weaknesses
40 | ///
41 | /// The algorithm does not cope well with situations with many
42 | /// inter-related contacts: stacked boxes, for example. In this
43 | /// case the simulation may appear to jiggle slightly, which often
44 | /// dislodges a box from the stack, allowing it to collapse.
45 | ///
46 | /// Another issue with the resolution mechanism is that resolving
47 | /// one contact may make another contact move sideways against
48 | /// friction, because each contact is handled independently, this
49 | /// friction is not taken into account. If one object is pushing
50 | /// against another, the pushed object may move across its support
51 | /// without friction, even though friction is set between those bodies.
52 | ///
53 | /// In general this resolver is not suitable for stacks of bodies,
54 | /// but is perfect for handling impact, explosive, and flat resting
55 | /// situations.
56 | ///
57 | public class RigidContactResolver
58 | {
59 |
60 | ///
61 | /// Holds the number of iterations to perform when resolving
62 | /// velocity.
63 | ///
64 | public int VelocityIterations;
65 |
66 | ///
67 | /// Holds the number of iterations to perform when resolving
68 | /// position.
69 | ///
70 | public int PositionIterations;
71 |
72 | ///
73 | /// To avoid instability velocities smaller
74 | /// than this value are considered to be zero. Too small and the
75 | /// simulation may be unstable, too large and the bodies may
76 | /// interpenetrate visually. A good starting point is the default
77 | /// of 0.01.
78 | ///
79 | public double VelocityEpsilon;
80 |
81 | ///
82 | /// To avoid instability penetrations
83 | /// smaller than this value are considered to be not interpenetrating.
84 | /// Too small and the simulation may be unstable, too large and the
85 | /// bodies may interpenetrate visually. A good starting point is
86 | /// the default of 0.01.
87 | ///
88 | public double PositionEpsilon;
89 |
90 | ///
91 | /// Stores the number of velocity iterations used in the
92 | /// last call to resolve contacts.
93 | ///
94 | public int VelocityIterationsUsed;
95 |
96 | ///
97 | /// Stores the number of position iterations used in the
98 | /// last call to resolve contacts.
99 | ///
100 | public int PositionIterationsUsed;
101 |
102 | ///
103 | /// Creates a new contact resolver.
104 | ///
105 | public RigidContactResolver(int iterations = 0)
106 | {
107 | VelocityIterations = iterations;
108 | PositionIterations = iterations;
109 | VelocityEpsilon = 0.001;
110 | PositionEpsilon = 0.001;
111 | }
112 |
113 | ///
114 | /// Resolves a set of contacts for both penetration and velocity.
115 | ///
116 | /// Contacts that cannot interact with
117 | /// each other should be passed to separate calls to resolveContacts,
118 | /// as the resolution algorithm takes much longer for lots of
119 | /// contacts than it does for the same number of contacts in small
120 | /// sets.
121 | ///
122 | /// @param contactArray Pointer to an array of contact objects.
123 | ///
124 | /// @param numContacts The number of contacts in the array to resolve.
125 | ///
126 | /// @param numIterations The number of iterations through the
127 | /// resolution algorithm. This should be at least the number of
128 | /// contacts (otherwise some constraints will not be resolved -
129 | /// although sometimes this is not noticable). If the iterations are
130 | /// not needed they will not be used, so adding more iterations may
131 | /// not make any difference. In some cases you would need millions
132 | /// of iterations. Think about the number of iterations as a bound:
133 | /// if you specify a large number, sometimes the algorithm WILL use
134 | /// it, and you may drop lots of frames.
135 | ///
136 | /// @param dt The duration of the previous integration step.
137 | /// This is used to compensate for forces applied.
138 | ///
139 | public void ResolveContacts(IList contacts, int numContacts, double dt)
140 | {
141 | // Make sure we have something to do.
142 | if (numContacts == 0) return;
143 |
144 | if (VelocityIterations <= 0)
145 | VelocityIterations = numContacts * 4;
146 |
147 | if(PositionIterations <= 0)
148 | PositionIterations = numContacts * 4;
149 |
150 | // Prepare the contacts for processing
151 | PrepareContacts(contacts, numContacts, dt);
152 |
153 | // Resolve the interpenetration problems with the contacts.
154 | AdjustPositions(contacts, numContacts, dt);
155 |
156 | // Resolve the velocity problems with the contacts.
157 | AdjustVelocities(contacts, numContacts, dt);
158 | }
159 |
160 | ///
161 | /// Sets up contacts ready for processing. This makes sure their
162 | /// internal data is configured correctly and the correct set of bodies
163 | /// is made alive.
164 | ///
165 | public void PrepareContacts(IList contacts, int numContacts, double dt)
166 | {
167 | // Generate contact velocity and axis information.
168 | for (int i = 0; i < numContacts; i++)
169 | {
170 | // Calculate the internal contact data (inertia, basis, etc).
171 | contacts[i].CalculateInternals(dt);
172 | }
173 | }
174 |
175 | ///
176 | /// Resolves the velocity issues with the given array of constraints,
177 | /// using the given number of iterations.
178 | ///
179 | public void AdjustVelocities(IList contacts, int numContacts, double dt)
180 | {
181 | var c = contacts;
182 | Vector3d[] velocityChange = new Vector3d[2];
183 | Vector3d[] rotationChange = new Vector3d[2];
184 | Vector3d deltaVel;
185 |
186 | // iteratively handle impacts in order of severity.
187 | VelocityIterationsUsed = 0;
188 | while (VelocityIterationsUsed < VelocityIterations)
189 | {
190 | // Find contact with maximum magnitude of probable velocity change.
191 | double max = VelocityEpsilon;
192 | int index = numContacts;
193 | for (int i = 0; i < numContacts; i++)
194 | {
195 | if (c[i].DesiredDeltaVelocity > max)
196 | {
197 | max = c[i].DesiredDeltaVelocity;
198 | index = i;
199 | }
200 | }
201 |
202 | if (index == numContacts) break;
203 |
204 | // Match the awake state at the contact
205 | c[index].MatchAwakeState();
206 |
207 | // Do the resolution on the contact that came out top.
208 | c[index].ApplyVelocityChange(velocityChange, rotationChange);
209 |
210 | // With the change in velocity of the two bodies, the update of
211 | // contact velocities means that some of the relative closing
212 | // velocities need recomputing.
213 | for (int i = 0; i < numContacts; i++)
214 | {
215 | // Check each body in the contact
216 | for (int b = 0; b < 2; b++)
217 | {
218 | if (c[i].Body[b] == null) continue;
219 |
220 | // Check for a match with each body in the newly
221 | // resolved contact
222 | for (int d = 0; d < 2; d++)
223 | {
224 | if (c[i].Body[b] == c[index].Body[d])
225 | {
226 | deltaVel = velocityChange[d] + Vector3d.Cross(rotationChange[d], c[i].RelativeContactPosition[b]);
227 |
228 | // The sign of the change is negative if we're dealing
229 | // with the second body in a contact.
230 | c[i].ContactVelocity += c[i].ContactToWorld.TransformTranspose(deltaVel) * (b != 0 ? -1 : 1);
231 | c[i].CalculateDesiredDeltaVelocity(dt);
232 | }
233 | }
234 | }
235 | }
236 |
237 | VelocityIterationsUsed++;
238 | }
239 | }
240 |
241 | ///
242 | /// Resolves the positional issues with the given array of constraints,
243 | /// using the given number of iterations.
244 | ///
245 | public void AdjustPositions(IList contacts, int numContacts, double dt)
246 | {
247 | var c = contacts;
248 | int i, index;
249 | Vector3d[] linearChange = new Vector3d[2];
250 |
251 | Vector3d[] angularChange = new Vector3d[2];
252 | double max;
253 | Vector3d deltaPosition;
254 |
255 | // iteratively resolve interpenetrations in order of severity.
256 | PositionIterationsUsed = 0;
257 | while (PositionIterationsUsed < PositionIterations)
258 | {
259 | // Find biggest penetration
260 | max = PositionEpsilon;
261 | index = numContacts;
262 | for (i = 0; i < numContacts; i++)
263 | {
264 | if (c[i].Penetration > max)
265 | {
266 | max = c[i].Penetration;
267 | index = i;
268 | }
269 | }
270 |
271 | if (index == numContacts) break;
272 |
273 | // Match the awake state at the contact
274 | c[index].MatchAwakeState();
275 |
276 | // Resolve the penetration.
277 | c[index].ApplyPositionChange(linearChange, angularChange, max);
278 |
279 | // Again this action may have changed the penetration of other
280 | // bodies, so we update contacts.
281 | for (i = 0; i < numContacts; i++)
282 | {
283 | // Check each body in the contact
284 | for (int b = 0; b < 2; b++)
285 | {
286 |
287 | if (c[i].Body[b] == null) continue;
288 |
289 | // Check for a match with each body in the newly
290 | // resolved contact
291 | for (int d = 0; d < 2; d++)
292 | {
293 | if (c[i].Body[b] == c[index].Body[d])
294 | {
295 | deltaPosition = linearChange[d] + Vector3d.Cross(angularChange[d], c[i].RelativeContactPosition[b]);
296 |
297 | // The sign of the change is positive if we're
298 | // dealing with the second body in a contact
299 | // and negative otherwise (because we're
300 | // subtracting the resolution)..
301 | c[i].Penetration += Vector3d.Dot(deltaPosition, c[i].ContactNormal) * (b != 0 ? 1 : -1);
302 | }
303 | }
304 | }
305 | }
306 |
307 | PositionIterationsUsed++;
308 | }
309 | }
310 |
311 | }
312 |
313 | }
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
--------------------------------------------------------------------------------