├── .editorconfig ├── .gitattributes ├── .gitignore ├── Jitter.sln ├── LICENSE.md ├── README.md ├── appveyor.yml ├── build.bat ├── component ├── Details.md ├── GettingStarted.md ├── License.md └── component.yaml ├── media └── Jitter Logo │ ├── jitterstackbig.png │ ├── jitterstacksmall.png │ ├── jitterstringbig.png │ ├── jitterstringsmall.png │ ├── stack_1024x1024.png │ ├── stack_128x128.png │ ├── stack_256x256.png │ ├── stack_4096x4096.png │ └── stack_512x512.png ├── samples └── JitterDemo │ ├── JitterDemo.sln │ └── JitterDemo │ ├── Camera.cs │ ├── Content │ ├── Car.png │ ├── ConvexDecomposition.obj │ ├── JitterDemoContent.mgcb │ ├── StaticMesh.x │ ├── car.fbx │ ├── checker.bmp │ ├── cloth.png │ ├── convexhull.x │ ├── font1.spritefont │ ├── font2.spritefont │ ├── kooten.ttf │ ├── logo1.png │ ├── logo2.png │ ├── torus.x │ └── wheel.fbx │ ├── Conversion.cs │ ├── DebugDrawer.cs │ ├── Display.cs │ ├── Forces │ ├── Buoyancy.cs │ ├── ForceGenerator.cs │ └── PseudoCloth.cs │ ├── Game.ico │ ├── GameThumbnail.png │ ├── JitterDemo.cs │ ├── JitterDemo.csproj │ ├── PhysicsObjects │ ├── ClothObject.cs │ ├── ConvexHullObject.cs │ ├── TerrainObject.cs │ └── Vehicle │ │ ├── CarObject.cs │ │ ├── DefaultCar.cs │ │ └── Wheel.cs │ ├── Primitives3D │ ├── BoxPrimitive.cs │ ├── CapsulePrimitive.cs │ ├── ConePrimitive.cs │ ├── ConvexHullPrimitive.cs │ ├── CylinderPrimitive.cs │ ├── DrawManager.cs │ ├── GeometricPrimitive.cs │ ├── SpherePrimitive.cs │ ├── TerrainPrimitive.cs │ └── VertexPositionNormal.cs │ ├── Program.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── QuadDrawer.cs │ ├── Scenes │ ├── BroadphaseStress.cs │ ├── Cardhouse.cs │ ├── Cloth.cs │ ├── ConvexDecomposition.cs │ ├── CylinderWall.cs │ ├── Domino.cs │ ├── EmptyScene.cs │ ├── Jenga.cs │ ├── NewtonCradle.cs │ ├── PrismaticJointTest.cs │ ├── Pyramid.cs │ ├── Ragdoll.cs │ ├── Restitution.cs │ ├── Rope.cs │ ├── Scene.cs │ ├── SoftBodyJenga.cs │ ├── Terrain.cs │ ├── Tower.cs │ ├── TriangleMesh.cs │ └── Wall.cs │ └── app.config ├── source ├── Jitter.sln └── Jitter │ ├── ArrayResourcePool.cs │ ├── Collision │ ├── CollisionIsland.cs │ ├── CollisionSystem.cs │ ├── CollisionSystemBrute.cs │ ├── CollisionSystemPersistentSAP.cs │ ├── CollisionSystemSAP.cs │ ├── DynamicTree.cs │ ├── DynamicTreeNode.cs │ ├── GJKCollide.cs │ ├── IBroadphaseEntity.cs │ ├── IslandManager.cs │ ├── Octree.cs │ ├── Shapes │ │ ├── BoxShape.cs │ │ ├── CapsuleShape.cs │ │ ├── CompoundShape.cs │ │ ├── ConeShape.cs │ │ ├── ConvexHullShape.cs │ │ ├── CylinderShape.cs │ │ ├── MinkowskiSumShape.cs │ │ ├── Multishape.cs │ │ ├── Shape.cs │ │ ├── SphereShape.cs │ │ ├── TerrainShape.cs │ │ └── TriangleMeshShape.cs │ ├── TriangleVertexIndices.cs │ └── XenoCollide.cs │ ├── DataStructures │ └── ReadOnlyHashset.cs │ ├── Dynamics │ ├── Arbiter.cs │ ├── ArbiterKey.cs │ ├── ArbiterKeyComparer.cs │ ├── ArbiterMap.cs │ ├── Constraint.cs │ ├── Constraints │ │ ├── FixedAngle.cs │ │ ├── PointOnLine.cs │ │ ├── PointOnPoint.cs │ │ ├── PointPointDistance.cs │ │ └── SingleBody │ │ │ ├── FixedAngle.cs │ │ │ ├── PointOnLine.cs │ │ │ └── PointOnPoint.cs │ ├── Contact.cs │ ├── ContactSettings.cs │ ├── IConstraint.cs │ ├── Joints │ │ ├── HingeJoint.cs │ │ ├── Joint.cs │ │ ├── LimitedHingeJoint.cs │ │ └── PrismaticJoint.cs │ ├── Material.cs │ ├── RigidBody.cs │ └── SoftBody.cs │ ├── IDebugDraw.cs │ ├── Jitter.csproj │ ├── LinearMath │ ├── JBBox.cs │ ├── JConvexHull.cs │ ├── JMath.cs │ ├── JMatrix.cs │ ├── JQuaternion.cs │ └── JVector.cs │ ├── ResourcePool.cs │ ├── ThreadManager.cs │ └── World.cs └── tools └── hacdtest ├── ConvexDecomposition.obj ├── ReadMe.txt ├── TestHACD.exe ├── bunny.obj └── hornbug.obj /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | build/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | *.sap 89 | 90 | # TFS 2012 Local Workspace 91 | $tf/ 92 | 93 | # Guidance Automation Toolkit 94 | *.gpState 95 | 96 | # ReSharper is a .NET coding add-in 97 | _ReSharper*/ 98 | *.[Rr]e[Ss]harper 99 | *.DotSettings.user 100 | 101 | # JustCode is a .NET coding add-in 102 | .JustCode 103 | 104 | # TeamCity is a build add-in 105 | _TeamCity* 106 | 107 | # DotCover is a Code Coverage Tool 108 | *.dotCover 109 | 110 | # NCrunch 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | nCrunchTemp_* 114 | 115 | # MightyMoose 116 | *.mm.* 117 | AutoTest.Net/ 118 | 119 | # Web workbench (sass) 120 | .sass-cache/ 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.[Pp]ublish.xml 140 | *.azurePubxml 141 | # TODO: Comment the next line if you want to checkin your web deploy settings 142 | # but database connection strings (with potential passwords) will be unencrypted 143 | *.pubxml 144 | *.publishproj 145 | 146 | # NuGet Packages 147 | *.nupkg 148 | # The packages folder can be ignored because of Package Restore 149 | **/packages/* 150 | # except build/, which is used as an MSBuild target. 151 | !**/packages/build/ 152 | # Uncomment if necessary however generally it will be regenerated when needed 153 | #!**/packages/repositories.config 154 | 155 | # Windows Azure Build Output 156 | csx/ 157 | *.build.csdef 158 | 159 | # Windows Azure Emulator 160 | ecf/ 161 | rcf/ 162 | 163 | # Windows Store app package directory 164 | AppPackages/ 165 | 166 | # Visual Studio cache files 167 | # files ending in .cache can be ignored 168 | *.[Cc]ache 169 | # but keep track of directories ending in .cache 170 | !*.[Cc]ache/ 171 | 172 | # Others 173 | ClientBin/ 174 | [Ss]tyle[Cc]op.* 175 | ~$* 176 | *~ 177 | *.dbmdl 178 | *.dbproj.schemaview 179 | *.pfx 180 | *.publishsettings 181 | node_modules/ 182 | orleans.codegen.cs 183 | 184 | # RIA/Silverlight projects 185 | Generated_Code/ 186 | 187 | # Backup & report files from converting an old project file 188 | # to a newer Visual Studio version. Backup files are not needed, 189 | # because we have git ;-) 190 | _UpgradeReport_Files/ 191 | Backup*/ 192 | UpgradeLog*.XML 193 | UpgradeLog*.htm 194 | 195 | # SQL Server files 196 | *.mdf 197 | *.ldf 198 | 199 | # Business Intelligence projects 200 | *.rdl.data 201 | *.bim.layout 202 | *.bim_*.settings 203 | 204 | # Microsoft Fakes 205 | FakesAssemblies/ 206 | 207 | # GhostDoc plugin setting file 208 | *.GhostDoc.xml 209 | 210 | # Node.js Tools for Visual Studio 211 | .ntvs_analysis.dat 212 | 213 | # Visual Studio 6 build log 214 | *.plg 215 | 216 | # Visual Studio 6 workspace options file 217 | *.opt 218 | 219 | # Visual Studio LightSwitch build output 220 | **/*.HTMLClient/GeneratedArtifacts 221 | **/*.DesktopClient/GeneratedArtifacts 222 | **/*.DesktopClient/ModelManifest.xml 223 | **/*.Server/GeneratedArtifacts 224 | **/*.Server/ModelManifest.xml 225 | _Pvt_Extensions 226 | 227 | # Paket dependency manager 228 | .paket/paket.exe 229 | 230 | # FAKE - F# Make 231 | .fake/ 232 | 233 | output/ 234 | -------------------------------------------------------------------------------- /Jitter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29001.49 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jitter", "source\Jitter\Jitter.csproj", "{AA03EF1A-94F7-4D30-AB14-2092863FF923}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|ARM = Debug|ARM 12 | Debug|x86 = Debug|x86 13 | Release|Any CPU = Release|Any CPU 14 | Release|ARM = Release|ARM 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|ARM.ActiveCfg = Debug|Any CPU 21 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|ARM.Build.0 = Debug|Any CPU 22 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|x86.ActiveCfg = Debug|Any CPU 23 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|x86.Build.0 = Debug|Any CPU 24 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|ARM.ActiveCfg = Release|Any CPU 27 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|ARM.Build.0 = Release|Any CPU 28 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|x86.ActiveCfg = Release|Any CPU 29 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|x86.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {9C7BED84-7617-412B-A88A-9E106EBAD5FA} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Thorben Linneweber, Matthew Leibowitz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Jitter Physics 2 | 3 | [![JitterPhysics Build][appveyor-badge]][appveyor-link] [![JitterPhysics on NuGet][nuget-badge]][nuget-link] 4 | 5 | Jitter Physics is a fast and lightweight 3D physics engine written in C#. 6 | 7 | | Jitter Physics Cloth | Speculative Contacts Jitter Physics | 8 | | :-----------------------------------: | :--------------------------------------------------: | 9 | | [![Jitter Physics Cloth][img1]][vid1] | [![Speculative Contacts Jitter Physics][img2]][vid2] | 10 | 11 | 12 | **Platforms & Frameworks** 13 | - Every platform which supports .NET, Mono or Xamarin 14 | - Works with the Mono framework on Linux/Mac without any recompilation 15 | - Also supports the Xbox360 and Windows Phone _(up to v0.1.7)_ 16 | - No dependencies. Every 3D engine/framework is supported: OpenTK, SlimDX, 17 | SharpDX, XNA, IrrlichtEngine, Urho3D 18 | 19 | **Overall Design** 20 | - Written in pure C# with a clean and object orientated API 21 | - Optimized for low to no garbage collections and maximum speed 22 | - Supported Shapes: TriangleMesh, Terrain, Compound, MinkowskiSum, Box, Sphere, 23 | Cylinder, Cone, Capsule, ConvexHull 24 | - Take advantage of multi-core CPUs by using the internal multithreading of 25 | the engine 26 | 27 | ## Jitter Physics (2D) 28 | 29 | The ["Jitter-2D" branch][jitter2d] is still in development an is not complete. 30 | At this time, it is probably better to make use of [Farseer Physics][farseer]. 31 | 32 | ## Quick Start 33 | 34 | ### Initialize the Physics System 35 | Create a world class and initialize it with a `CollisionSystem`: 36 | 37 | CollisionSystem collision = new CollisionSystemSAP(); 38 | World world = new World(collision); 39 | 40 | ### Add Objects to the World 41 | Create a shape of your choice and pass it to a body: 42 | 43 | Shape shape = new BoxShape(1.0f, 2.0f, 3.0f); 44 | RigidBody body = new RigidBody(shape); 45 | 46 | It's valid to use the same shape for different bodies. 47 | Set the position and orientation of the body by using it's properties. 48 | The next step is to add the `Body` to the world: 49 | 50 | world.AddBody(body); 51 | 52 | ### Run the Simulation 53 | Now you can call the `Step` method to integrate the world one timestep further. 54 | This should be done in you main game loop: 55 | 56 | while (gameRunning) 57 | { 58 | world.Step(1.0f / 100.0f, true); 59 | 60 | // do other stuff, like drawing 61 | } 62 | 63 | The first parameter is the timestep. This value should be as small as possible 64 | to get a stable simulation. The second parameter is for whether using internal 65 | multithreading or not. That's it the body is now simulated and affected by 66 | default gravity specified in `World.Gravity`. After each timestep the `Position` 67 | of the body should be different. 68 | 69 | ## Credits 70 | 71 | This library was originally written by Thorben Linneweber. Original source code can be found at https://code.google.com/archive/p/jitterphysics. 72 | 73 | 74 | [img1]: http://img.youtube.com/vi/cM23EJOFp3E/0.jpg 75 | [vid1]: http://www.youtube.com/watch?v= 76 | [img2]: http://img.youtube.com/vi/bKP2GZLlPWA/0.jpg 77 | [vid2]: http://www.youtube.com/watch?v=bKP2GZLlPWA 78 | [jitter2d]: https://github.com/mattleibow/jitterphysics/tree/Jitter-2D 79 | [farseer]: https://farseerphysics.codeplex.com/ 80 | 81 | [appveyor-badge]: https://img.shields.io/appveyor/ci/mattleibow/JitterPhysics/master.svg?style=flat-square 82 | [appveyor-link]: https://ci.appveyor.com/project/mattleibow/jitterphysics 83 | [nuget-badge]: https://img.shields.io/nuget/v/JitterPhysics.svg?style=flat-square 84 | [nuget-link]: https://www.nuget.org/packages/JitterPhysics/ 85 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # build variables 2 | os: Visual Studio 2015 3 | configuration: Release 4 | platform: Any CPU 5 | environment: 6 | LibraryVersion: 0.2.0 7 | xamarin: 8 | email: 9 | secure: +SUXZSPLHwp39+Yh09d2xxVGsEgHtlSD4NT1Og5h3sg= 10 | password: 11 | secure: Tvdf5rZl6IOCwZbvyj9B2w== 12 | android: true 13 | ios: true 14 | 15 | # versioning 16 | version: $(LibraryVersion).{build} 17 | assembly_info: 18 | patch: true 19 | file: '**\AssemblyInfo.*' 20 | assembly_version: $(LibraryVersion).0 21 | assembly_file_version: '{version}' 22 | assembly_informational_version: '{version}-{branch}' 23 | 24 | # packages 25 | install: 26 | - cinst 7zip -x86 27 | - cinst 7zip.commandline -x86 28 | - cinst xamarin-component -version 1.1.0.7 29 | - ps: | 30 | $tempDir="$pwd\temp" 31 | $installerUrl="http://www.monogame.net/releases/v3.4/MonoGameSetup.exe" 32 | $installerFile="$tempDir\MonoGameSetup.zip" 33 | $installerExtracted="$tempDir\MonoGameSetup" 34 | $programFiles = "${env:ProgramFiles(x86)}\" 35 | 36 | Write-Host "Downloading MonoGame to $installerFile..." 37 | If ((Test-Path $tempDir) -eq 0) { 38 | New-Item -ItemType Directory $tempDir 39 | } 40 | Invoke-WebRequest $installerUrl -OutFile $installerFile 41 | 42 | Write-Host "Extracting MonoGame to $installerExtracted..." 43 | 7z x -y $installerFile -o"$installerExtracted" 44 | Write-Host "Copying the MonoGame content pipeline to $programFiles..." 45 | Copy-Item "$installerExtracted\`$PROGRAMFILES\MSBuild\MonoGame" "$programFiles\MSBuild" -Recurse 46 | 47 | # build 48 | branches: 49 | only: 50 | - master 51 | before_build: 52 | - if not exist output mkdir output 53 | - if not exist output\net4 mkdir output\net4 54 | - if not exist output\Portable mkdir output\Portable 55 | - nuget restore source\Jitter.sln 56 | build: 57 | project: source\Jitter.sln 58 | verbosity: normal 59 | after_build: 60 | - ps: | 61 | $ErrorActionPreference = "Stop" 62 | 63 | $nugetVersion = "$env:APPVEYOR_BUILD_VERSION" 64 | 65 | Write-Host "Copying the output files..." 66 | copy source\Jitter\bin\net4\Release\Jitter.dll output\net4\ 67 | copy source\Jitter\bin\net4\Release\Jitter.pdb output\net4\ 68 | copy source\Jitter\bin\net4\Release\Jitter.xml output\net4\ 69 | copy source\Jitter\bin\Portable\Release\Jitter.dll output\Portable\ 70 | copy source\Jitter\bin\Portable\Release\Jitter.pdb output\Portable\ 71 | copy source\Jitter\bin\Portable\Release\Jitter.xml output\Portable\ 72 | 73 | Write-Host "Setting .nuspec version tag to $nugetVersion..." 74 | $content = (Get-Content nuget\Jitter.nuspec) 75 | $content = $content -replace '\$version\$', $nugetVersion 76 | $content | Out-File nuget\Jitter.nuspec 77 | nuget pack nuget\Jitter.nuspec -OutputDirectory output 78 | 79 | Write-Host "Setting component.yaml version tag to $nugetVersion..." 80 | $content = (Get-Content component\component.yaml) 81 | $content = $content -replace '\$version\$', $nugetVersion 82 | $content | Out-File component\component.yaml 83 | xamarin-component package ./component/ 84 | mv component\*.xam output 85 | 86 | test_script: 87 | - ps: | 88 | $ErrorActionPreference = "Stop" 89 | 90 | Write-Host "Building the samples..." 91 | 92 | nuget restore samples\JitterDemo\JitterDemo.sln 93 | msbuild samples\JitterDemo\JitterDemo.sln /p:Configuration=$env:configuration /p:Platform="Any CPU" 94 | If ($LastExitCode -ne 0) { 95 | exit $LastExitCode 96 | } 97 | 98 | nuget restore samples\JitterOpenGLDemo\JitterOpenGLDemo.sln 99 | msbuild samples\JitterOpenGLDemo\JitterOpenGLDemo.sln /p:Configuration=$env:configuration /p:Platform="Any CPU" 100 | If ($LastExitCode -ne 0) { 101 | exit $LastExitCode 102 | } 103 | 104 | nuget restore samples\JitterPhoneDemo\SimpleJitterPhoneDemo.sln 105 | msbuild samples\JitterPhoneDemo\SimpleJitterPhoneDemo.sln /p:Configuration=$env:configuration /p:Platform="x86" 106 | If ($LastExitCode -ne 0) { 107 | exit $LastExitCode 108 | } 109 | 110 | nuget restore samples\JitterPortableSample\JitterSample.sln 111 | msbuild samples\JitterPortableSample\JitterSample.sln /p:Configuration=$env:configuration /p:Platform="Any CPU" 112 | If ($LastExitCode -ne 0) { 113 | exit $LastExitCode 114 | } 115 | 116 | # artifacts 117 | artifacts: 118 | - path: output\ 119 | name: Jitter-$(APPVEYOR_BUILD_VERSION) 120 | type: zip 121 | - path: output\JitterPhysics*.nupkg 122 | - path: output\JitterPhysics*.xam 123 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem clean up any files / folders 4 | if not exist output mkdir output 5 | del /S /Q output 6 | for /D %%p in ("output\*") do rmdir "%%p" /s /q 7 | 8 | 9 | rem build 3D library 10 | msbuild source\Jitter.sln /p:Configuration=Release /t:Rebuild 11 | 12 | rem ready for packaging 13 | if not exist output\net4 mkdir output\net4 14 | if not exist output\Portable mkdir output\Portable 15 | copy source\Jitter\bin\net4\Release\Jitter.dll output\net4\ 16 | copy source\Jitter\bin\net4\Release\Jitter.pdb output\net4\ 17 | copy source\Jitter\bin\net4\Release\Jitter.xml output\net4\ 18 | copy source\Jitter\bin\Portable\Release\Jitter.dll output\Portable\ 19 | copy source\Jitter\bin\Portable\Release\Jitter.pdb output\Portable\ 20 | copy source\Jitter\bin\Portable\Release\Jitter.xml output\Portable\ 21 | 22 | rem package 23 | nuget pack nuget\Jitter.nuspec -OutputDirectory output 24 | 25 | rem package 26 | xamarin-component package ./component/ 27 | mv component\*.xam output 28 | -------------------------------------------------------------------------------- /component/Details.md: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | **Jitter Physics** is a fast and lightweight physics engine for all managed 7 | languages. 8 | 9 | **Platforms & Frameworks** 10 | - Every platform which supports .NET/Mono 11 | - Works with the Mono framework on Linux/Mac without any recompilation 12 | - No dependencies. Every 3D engine/framework is supported: OpenTK, SlimDX, 13 | SharpDX, XNA, MonoGame, IrrlichtEngine 14 | 15 | **Overall Design** 16 | - Written in pure C# with a clean and object orientated API 17 | - Optimized for low to no garbage collections and maximum speed 18 | - Supported Shapes: TriangleMesh, Terrain, Compound, MinkowskiSum, Box, Sphere, 19 | Cylinder, Cone, Capsule, ConvexHull 20 | - Take advantage of multi-core CPUs by using the internal multi-threading of 21 | the engine 22 | 23 | ## The Samples 24 | _The samples use the [MonoGame][mg] framework and the MonoGame content 25 | pipeline. To build the samples, and the content, the MonoGame content 26 | pipeline needs to be installed using the [MonoGame installer][mg-setup]._ 27 | 28 | ## Quick Start 29 | 30 | ### Initialize the Physics System 31 | Create a `World` instance and initialize it with a `CollisionSystem`: 32 | 33 | CollisionSystem collision = new CollisionSystemSAP(); 34 | World world = new World(collision); 35 | 36 | ### Add Objects to the World 37 | Create a shape of your choice, and pass it to a body: 38 | 39 | Shape shape = new BoxShape(1.0f, 2.0f, 3.0f); 40 | RigidBody body = new RigidBody(shape); 41 | 42 | It is valid to use the same shape for different bodies. The 43 | position and orientation of the body can be set using it's properties. 44 | 45 | The next step is to add the `Body` to the world: 46 | 47 | world.AddBody(body); 48 | 49 | ### Run the Simulation 50 | Now you can call the `Step` method to integrate the world one timestep further. 51 | This should be done in you main game loop: 52 | 53 | while (gameRunning) 54 | { 55 | world.Step(1.0f / 100.0f, true); 56 | 57 | // do other stuff, like drawing 58 | } 59 | 60 | The first parameter is the timestep. This value should be as small as possible 61 | to get a stable simulation. The second parameter is for whether using internal 62 | multi-threading or not. That's it the body is now simulated and affected by 63 | default gravity specified in `World.Gravity`. After each timestep the `Position` 64 | of the body should be different. 65 | 66 | [mg]: http://www.monogame.net/ 67 | [mg-setup]: http://www.monogame.net/2015/04/29/monogame-3-4/ 68 | -------------------------------------------------------------------------------- /component/License.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Thorben Linneweber, Matthew Leibowitz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /component/component.yaml: -------------------------------------------------------------------------------- 1 | %YAML 1.2 2 | --- 3 | name: Jitter Physics 4 | id: JitterPhysics 5 | publisher: Xamarin Inc 6 | publisher-url: https://xamarin.com 7 | summary: Jitter Physics is a fast and lightweight physics engine for all managed languages. 8 | version: $version$ 9 | src-url: https://github.com/mattleibow/jitterphysics 10 | 11 | details: Details.md 12 | license: License.md 13 | getting-started: GettingStarted.md 14 | 15 | is_shell: true 16 | no_build: true 17 | skip_docs: true 18 | packages: 19 | android: JitterPhysics, Version=$version$ 20 | ios: JitterPhysics, Version=$version$ 21 | ios-unified: JitterPhysics, Version=$version$ 22 | winphone-8.0: JitterPhysics, Version=$version$ 23 | winphone-8.1: JitterPhysics, Version=$version$ 24 | mac-unified: JitterPhysics, Version=$version$ 25 | libraries: 26 | android: ../output/Portable/Jitter.dll 27 | ios: ../output/Portable/Jitter.dll 28 | ios-unified: ../output/Portable/Jitter.dll 29 | winphone-8.0: ../output/Portable/Jitter.dll 30 | winphone-8.1: ../output/Portable/Jitter.dll 31 | winrt: ../output/Portable/Jitter.dll 32 | mac-unified: ../output/Portable/Jitter.dll 33 | local-nuget-repo: ../output 34 | 35 | icons: 36 | - ../media/Jitter Logo/stack_128x128.png 37 | - ../media/Jitter Logo/stack_512x512.png 38 | 39 | samples: 40 | - name: Android Sample 41 | path: ../samples/JitterPortableSample/JitterAndroidSample.sln 42 | removeProjects: 43 | - Jitter.Portable 44 | installNuGets: 45 | - project: JitterAndroidSample 46 | packages: JitterPhysics 47 | - project: JitterSample 48 | packages: JitterPhysics 49 | - name: iOS Sample 50 | path: ../samples/JitterPortableSample/JitteriOSSample.sln 51 | removeProjects: 52 | - Jitter.Portable 53 | installNuGets: 54 | - project: JitteriOSSample 55 | packages: JitterPhysics 56 | - project: JitterSample 57 | packages: JitterPhysics 58 | - name: Windows Phone Sample 59 | path: ../samples/JitterPortableSample/JitterWPASample.sln 60 | removeProjects: 61 | - Jitter.Portable 62 | installNuGets: 63 | - project: JitterWPASample 64 | packages: JitterPhysics 65 | - project: JitterSample 66 | packages: JitterPhysics 67 | -------------------------------------------------------------------------------- /media/Jitter Logo/jitterstackbig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/jitterstackbig.png -------------------------------------------------------------------------------- /media/Jitter Logo/jitterstacksmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/jitterstacksmall.png -------------------------------------------------------------------------------- /media/Jitter Logo/jitterstringbig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/jitterstringbig.png -------------------------------------------------------------------------------- /media/Jitter Logo/jitterstringsmall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/jitterstringsmall.png -------------------------------------------------------------------------------- /media/Jitter Logo/stack_1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/stack_1024x1024.png -------------------------------------------------------------------------------- /media/Jitter Logo/stack_128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/stack_128x128.png -------------------------------------------------------------------------------- /media/Jitter Logo/stack_256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/stack_256x256.png -------------------------------------------------------------------------------- /media/Jitter Logo/stack_4096x4096.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/stack_4096x4096.png -------------------------------------------------------------------------------- /media/Jitter Logo/stack_512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/media/Jitter Logo/stack_512x512.png -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jitter.Portable", "..\..\source\Jitter\Jitter.Portable.csproj", "{AA03EF1A-94F7-4D30-AB14-2092863FF92A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JitterDemo", "JitterDemo\JitterDemo.csproj", "{6D78166B-77BC-4BAF-97CC-A946D013145B}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {6D78166B-77BC-4BAF-97CC-A946D013145B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {6D78166B-77BC-4BAF-97CC-A946D013145B}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {6D78166B-77BC-4BAF-97CC-A946D013145B}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {6D78166B-77BC-4BAF-97CC-A946D013145B}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/Car.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/Car.png -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/car.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/car.fbx -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/checker.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/checker.bmp -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/cloth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/cloth.png -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/font1.spritefont: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 14 | kooten 15 | 16 | 20 | 14 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | 45 | 46 | 53 | 54 | 55 | 56 | ~ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/font2.spritefont: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 14 | kooten 15 | 16 | 20 | 10 21 | 22 | 26 | 0 27 | 28 | 32 | true 33 | 34 | 38 | 39 | 40 | 44 | 45 | 46 | 53 | 54 | 55 | 56 | ~ 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/kooten.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/kooten.ttf -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/logo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/logo1.png -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/logo2.png -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Content/wheel.fbx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Content/wheel.fbx -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Conversion.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using Microsoft.Xna.Framework; 3 | 4 | namespace JitterDemo 5 | { 6 | public sealed class Conversion 7 | { 8 | public static JVector ToJitterVector(Vector3 vector) 9 | { 10 | return new JVector(vector.X, vector.Y, vector.Z); 11 | } 12 | 13 | public static Matrix ToXNAMatrix(JMatrix matrix) 14 | { 15 | return new Matrix( 16 | matrix.M11, 17 | matrix.M12, 18 | matrix.M13, 19 | 0.0f, 20 | matrix.M21, 21 | matrix.M22, 22 | matrix.M23, 23 | 0.0f, 24 | matrix.M31, 25 | matrix.M32, 26 | matrix.M33, 27 | 0.0f, 28 | 0.0f, 29 | 0.0f, 30 | 0.0f, 31 | 1.0f); 32 | } 33 | 34 | public static JMatrix ToJitterMatrix(Matrix matrix) 35 | { 36 | return new JMatrix 37 | { 38 | M11 = matrix.M11, 39 | M12 = matrix.M12, 40 | M13 = matrix.M13, 41 | M21 = matrix.M21, 42 | M22 = matrix.M22, 43 | M23 = matrix.M23, 44 | M31 = matrix.M31, 45 | M32 = matrix.M32, 46 | M33 = matrix.M33 47 | }; 48 | } 49 | 50 | public static Vector3 ToXNAVector(JVector vector) 51 | { 52 | return new Vector3(vector.X, vector.Y, vector.Z); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Display.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Content; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace JitterDemo 8 | { 9 | public class Display : DrawableGameComponent 10 | { 11 | private readonly ContentManager content; 12 | private SpriteBatch spriteBatch; 13 | private SpriteFont font1, font2; 14 | private Texture2D texture; 15 | 16 | private int frameRate = 0; 17 | private int frameCounter = 0; 18 | private TimeSpan elapsedTime = TimeSpan.Zero; 19 | 20 | private int bbWidth, bbHeight; 21 | 22 | public Display(Game game) 23 | : base(game) 24 | { 25 | content = new ContentManager(game.Services); 26 | DisplayText = new List(); 27 | for (int i = 0; i < 25; i++) 28 | { 29 | DisplayText.Add(string.Empty); 30 | } 31 | } 32 | 33 | private void GraphicsDevice_DeviceReset(object sender, EventArgs e) 34 | { 35 | bbWidth = GraphicsDevice.PresentationParameters.BackBufferWidth; 36 | bbHeight = GraphicsDevice.PresentationParameters.BackBufferHeight; 37 | } 38 | 39 | protected override void LoadContent() 40 | { 41 | GraphicsDevice.DeviceReset += new EventHandler(GraphicsDevice_DeviceReset); 42 | GraphicsDevice_DeviceReset(null, null); 43 | 44 | spriteBatch = new SpriteBatch(GraphicsDevice); 45 | font1 = content.Load("Content/font1"); 46 | font2 = content.Load("Content/font2"); 47 | 48 | texture = content.Load("Content/logo2"); 49 | } 50 | 51 | protected override void UnloadContent() 52 | { 53 | content.Unload(); 54 | } 55 | 56 | public override void Update(GameTime gameTime) 57 | { 58 | elapsedTime += gameTime.ElapsedGameTime; 59 | 60 | if (elapsedTime > TimeSpan.FromSeconds(1)) 61 | { 62 | elapsedTime -= TimeSpan.FromSeconds(1); 63 | frameRate = frameCounter; 64 | frameCounter = 0; 65 | } 66 | } 67 | 68 | public List DisplayText { set; get; } 69 | 70 | public override void Draw(GameTime gameTime) 71 | { 72 | frameCounter++; 73 | 74 | string fps = frameRate.ToString(); 75 | 76 | spriteBatch.Begin(); 77 | 78 | spriteBatch.Draw(texture, new Rectangle(bbWidth - 105, 5, 100, 91), Color.White); 79 | spriteBatch.DrawString(font1, fps, new Vector2(11, 6), Color.Black); 80 | spriteBatch.DrawString(font1, fps, new Vector2(12, 7), Color.Yellow); 81 | 82 | for (int i = 0; i < DisplayText.Count; i++) 83 | { 84 | if (!string.IsNullOrEmpty(DisplayText[i])) 85 | { 86 | // spriteBatch.DrawString(font2, DisplayText[i], new Vector2(11, 40 + (i * 20)), Color.White); 87 | } 88 | } 89 | 90 | spriteBatch.End(); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Forces/ForceGenerator.cs: -------------------------------------------------------------------------------- 1 | namespace Jitter.Forces 2 | { 3 | /// 4 | /// Base class for physic effect. 5 | /// 6 | public class ForceGenerator 7 | { 8 | /// 9 | /// 10 | /// 11 | protected World world; 12 | 13 | private readonly World.WorldStep preStep, postStep; 14 | 15 | /// 16 | /// 17 | /// 18 | /// 19 | public ForceGenerator(World world) 20 | { 21 | this.world = world; 22 | 23 | preStep = new World.WorldStep(PreStep); 24 | postStep = new World.WorldStep(PostStep); 25 | 26 | world.Events.PostStep += postStep; 27 | world.Events.PreStep += preStep; 28 | } 29 | 30 | /// 31 | /// 32 | /// 33 | /// 34 | public virtual void PreStep(float timeStep) 35 | { 36 | } 37 | 38 | /// 39 | /// 40 | /// 41 | /// 42 | public virtual void PostStep(float timeStep) 43 | { 44 | } 45 | 46 | /// 47 | /// 48 | /// 49 | public void RemoveEffect() 50 | { 51 | world.Events.PostStep -= postStep; 52 | world.Events.PreStep -= preStep; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Forces/PseudoCloth.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Jitter.Dynamics; 6 | using Jitter.Collision.Shapes; 7 | using Jitter.LinearMath; 8 | using Jitter.Dynamics.Constraints; 9 | 10 | namespace Jitter.Forces 11 | { 12 | public class PseudoCloth 13 | { 14 | 15 | 16 | public List constraints = new List(); 17 | 18 | public class PseudoClothBody : RigidBody 19 | { 20 | public PseudoClothBody(float sphereRadius) : base(new SphereShape(sphereRadius)) { } 21 | } 22 | 23 | int sizeX, sizeY; 24 | float scale; 25 | 26 | World world; 27 | 28 | PseudoClothBody[] bodies; 29 | 30 | public PseudoCloth(World world, int sizeX, int sizeY, float scale) 31 | { 32 | bodies = new PseudoClothBody[sizeX * sizeY]; 33 | 34 | for (int i = 0; i < sizeX; i++) 35 | { 36 | for (int e = 0; e < sizeX; e++) 37 | { 38 | bodies[i + e * sizeY] = new PseudoClothBody(0.1f); 39 | bodies[i + e * sizeY].Position = new JVector(i * scale, 0, e * scale) + JVector.Up * 10.0f; 40 | bodies[i + e * sizeY].StaticFriction =0.5f; 41 | bodies[i + e * sizeY].DynamicFriction = 0.5f; 42 | bodies[i + e * sizeY].Mass = 0.1f; 43 | world.AddBody(bodies[i + e * sizeY]); 44 | } 45 | } 46 | 47 | world.CollisionSystem.PassedBroadphase += new Collision.PassedBroadphaseHandler(CollisionSystem_PassedBroadphase); 48 | world.PostStep += new WorldStep(world_PostStep); 49 | 50 | this.world = world; 51 | 52 | for (int i = 0; i < sizeX; i++) 53 | { 54 | for (int e = 0; e < sizeY; e++) 55 | { 56 | if (i + 1 < sizeX) 57 | { 58 | AddDistance(e * sizeY + i, (i + 1) + e * sizeY); 59 | // (i,e) and (i+1,e) 60 | } 61 | 62 | if (e + 1 < sizeY) 63 | { 64 | AddDistance(e * sizeY + i, ((e + 1) * sizeY) + i); 65 | // (e,i) and (e+1,i) 66 | 67 | } 68 | 69 | if( (i + 1 < sizeX) && (e + 1 < sizeY)) 70 | { 71 | AddDistance(e * sizeY + i, ((e + 1) * sizeY) +( i+1)); 72 | } 73 | 74 | 75 | if ((i > 0) && (e + 1 < sizeY)) 76 | { 77 | AddDistance(e * sizeY + i, ((e + 1) * sizeY) + (i - 1)); 78 | } 79 | 80 | 81 | } 82 | } 83 | 84 | this.sizeX = sizeX; 85 | this.sizeY = sizeY; 86 | this.scale = scale; 87 | 88 | } 89 | 90 | void world_PostStep(float timeStep) 91 | { 92 | CheckConstraints(); 93 | } 94 | 95 | public RigidBody GetCorner(int e,int i) 96 | { 97 | return bodies[e * sizeY + i]; 98 | } 99 | 100 | 101 | 102 | private void AddDistance(int p1, int p2) 103 | { 104 | DistanceConstraint dc = new DistanceConstraint(bodies[p1], bodies[p2], bodies[p1].position, bodies[p2].position); 105 | dc.Softness = 2f; 106 | dc.BiasFactor = 0.1f; 107 | world.AddConstraint(dc); 108 | this.constraints.Add(dc); 109 | } 110 | 111 | public void CheckConstraints() 112 | { 113 | foreach (Constraint c in constraints) 114 | { 115 | if ((c as DistanceConstraint).AppliedImpulse.Length() > 1.8f) 116 | { 117 | world.constraints.Remove(c); 118 | } 119 | } 120 | } 121 | 122 | 123 | 124 | 125 | 126 | 127 | private bool CollisionSystem_PassedBroadphase(RigidBody body1, RigidBody body2) 128 | { 129 | // prevent PseudoClothBody,PseudoClothBody collisions 130 | return !(body1 is PseudoClothBody && body2 is PseudoClothBody); 131 | } 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Game.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/Game.ico -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/GameThumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/samples/JitterDemo/JitterDemo/GameThumbnail.png -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/PhysicsObjects/TerrainObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Microsoft.Xna.Framework; 6 | using Microsoft.Xna.Framework.Graphics; 7 | using Jitter.Collision.Shapes; 8 | using Jitter.Dynamics; 9 | using Jitter.LinearMath; 10 | using JitterDemo.Primitives3D; 11 | 12 | namespace JitterDemo 13 | { 14 | public class TerrainObject : DrawableGameComponent 15 | { 16 | TerrainPrimitive primitive; 17 | BasicEffect effect; 18 | RigidBody terrainBody; 19 | 20 | Matrix worldMatrix = Matrix.Identity; 21 | 22 | public Matrix World { get { return worldMatrix; } 23 | set 24 | { 25 | worldMatrix = value; 26 | terrainBody.Orientation = Conversion.ToJitterMatrix(worldMatrix); 27 | terrainBody.Position = Conversion.ToJitterVector(worldMatrix.Translation); 28 | 29 | } 30 | } 31 | 32 | public TerrainObject(Game game,BasicEffect effect) 33 | : base(game) 34 | { 35 | this.effect = effect; 36 | } 37 | 38 | public override void Initialize() 39 | { 40 | base.Initialize(); 41 | primitive = new TerrainPrimitive(GraphicsDevice, 42 | (int a, int b) => 43 | { return (float)(Math.Sin(a * 0.1f) * Math.Cos(b * 0.1f))*3; }); 44 | 45 | JitterDemo demo = this.Game as JitterDemo; 46 | 47 | TerrainShape terrainShape = new TerrainShape(primitive.heights, 1.0f, 1.0f); 48 | 49 | terrainBody = new RigidBody(terrainShape); 50 | terrainBody.IsStatic = true; 51 | terrainBody.Tag = true; 52 | 53 | demo.World.AddBody(terrainBody); 54 | 55 | World = Matrix.CreateTranslation(-50, 0, -50); 56 | } 57 | 58 | public override void Draw(GameTime gameTime) 59 | { 60 | effect.DiffuseColor = Color.Red.ToVector3(); 61 | primitive.AddWorldMatrix(worldMatrix); 62 | primitive.Draw(effect); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/PhysicsObjects/Vehicle/CarObject.cs: -------------------------------------------------------------------------------- 1 | #region Using Statements 2 | using Microsoft.Xna.Framework; 3 | using Jitter.Collision.Shapes; 4 | using Jitter; 5 | using Jitter.LinearMath; 6 | using Microsoft.Xna.Framework.Input; 7 | using Microsoft.Xna.Framework.Graphics; 8 | #endregion 9 | 10 | namespace JitterDemo.Vehicle 11 | { 12 | public class CarObject : DrawableGameComponent 13 | { 14 | private Model chassisModel = null; 15 | private Model tireModel = null; 16 | 17 | public DefaultCar carBody = null; 18 | 19 | public CarObject(Game game) 20 | : base(game) 21 | { 22 | BuildCar(); 23 | } 24 | 25 | private void BuildCar() 26 | { 27 | var demo = Game as JitterDemo; 28 | var world = demo.World; 29 | 30 | var lower = new CompoundShape.TransformedShape( 31 | new BoxShape(2.5f, 1f, 6.0f), JMatrix.Identity, JVector.Zero); 32 | 33 | var upper = new CompoundShape.TransformedShape( 34 | new BoxShape(2.0f, 0.5f, 3.0f), JMatrix.Identity, (JVector.Up * 0.75f) + (JVector.Backward * 1.0f)); 35 | 36 | CompoundShape.TransformedShape[] subShapes = { lower, upper }; 37 | 38 | Shape chassis = new CompoundShape(subShapes); 39 | 40 | //chassis = new BoxShape(2.5f, 1f, 6.0f); 41 | 42 | carBody = new DefaultCar(world, chassis) 43 | { 44 | // use the inertia of the lower box. 45 | 46 | // adjust some driving values 47 | SteerAngle = 30, 48 | DriveTorque = 155, 49 | AccelerationRate = 10, 50 | SteerRate = 2f 51 | }; 52 | carBody.AdjustWheelValues(); 53 | 54 | carBody.Tag = BodyTag.DontDrawMe; 55 | carBody.AllowDeactivation = false; 56 | 57 | // place the car two units above the ground. 58 | carBody.Position = new JVector(0, 5, 0); 59 | 60 | world.AddBody(carBody); 61 | } 62 | 63 | public override void Update(GameTime gameTime) 64 | { 65 | var keyState = Keyboard.GetState(); 66 | 67 | float steer, accelerate; 68 | if (keyState.IsKeyDown(Keys.Up)) accelerate = 1.0f; 69 | else if (keyState.IsKeyDown(Keys.Down)) accelerate = -1.0f; 70 | else accelerate = 0.0f; 71 | 72 | if (keyState.IsKeyDown(Keys.Left)) steer = 1; 73 | else if (keyState.IsKeyDown(Keys.Right)) steer = -1; 74 | else steer = 0.0f; 75 | 76 | carBody.SetInput(accelerate, steer); 77 | 78 | base.Update(gameTime); 79 | } 80 | 81 | #region Draw Wheels 82 | private void DrawWheels() 83 | { 84 | var demo = Game as JitterDemo; 85 | 86 | for(int i = 0;i("car"); 143 | tireModel = Game.Content.Load("wheel"); 144 | 145 | base.LoadContent(); 146 | } 147 | 148 | public override void Draw(GameTime gameTime) 149 | { 150 | DrawWheels(); 151 | DrawChassis(); 152 | base.Draw(gameTime); 153 | } 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/BoxPrimitive.cs: -------------------------------------------------------------------------------- 1 | #region File Description 2 | //----------------------------------------------------------------------------- 3 | // BoxPrimitive.cs 4 | // 5 | // Microsoft XNA Community Game Platform 6 | // Copyright (C) Microsoft Corporation. All rights reserved. 7 | //----------------------------------------------------------------------------- 8 | #endregion 9 | 10 | #region Using Statements 11 | using Microsoft.Xna.Framework; 12 | using Microsoft.Xna.Framework.Graphics; 13 | #endregion 14 | 15 | namespace JitterDemo.Primitives3D 16 | { 17 | /// 18 | /// Geometric primitive class for drawing cubes. 19 | /// 20 | public class BoxPrimitive : GeometricPrimitive 21 | { 22 | /// 23 | /// Constructs a new cube primitive, using default settings. 24 | /// 25 | public BoxPrimitive(GraphicsDevice graphicsDevice) 26 | : this(graphicsDevice, 1) 27 | { 28 | } 29 | 30 | /// 31 | /// Constructs a new cube primitive, with the specified size. 32 | /// 33 | public BoxPrimitive(GraphicsDevice graphicsDevice, float size) 34 | { 35 | // A cube has six faces, each one pointing in a different direction. 36 | Vector3[] normals = 37 | { 38 | new Vector3(0, 0, 1), 39 | new Vector3(0, 0, -1), 40 | new Vector3(1, 0, 0), 41 | new Vector3(-1, 0, 0), 42 | new Vector3(0, 1, 0), 43 | new Vector3(0, -1, 0), 44 | }; 45 | 46 | // Create each face in turn. 47 | foreach (var normal in normals) 48 | { 49 | // Get two vectors perpendicular to the face normal and to each other. 50 | var side1 = new Vector3(normal.Y, normal.Z, normal.X); 51 | var side2 = Vector3.Cross(normal, side1); 52 | 53 | // Six indices (two triangles) per face. 54 | AddIndex(CurrentVertex + 0); 55 | AddIndex(CurrentVertex + 1); 56 | AddIndex(CurrentVertex + 2); 57 | 58 | AddIndex(CurrentVertex + 0); 59 | AddIndex(CurrentVertex + 2); 60 | AddIndex(CurrentVertex + 3); 61 | 62 | // Four vertices per face. 63 | AddVertex((normal - side1 - side2) * size / 2, normal); 64 | AddVertex((normal - side1 + side2) * size / 2, normal); 65 | AddVertex((normal + side1 + side2) * size / 2, normal); 66 | AddVertex((normal + side1 - side2) * size / 2, normal); 67 | } 68 | 69 | InitializePrimitive(graphicsDevice); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/CapsulePrimitive.cs: -------------------------------------------------------------------------------- 1 | #region File Description 2 | //----------------------------------------------------------------------------- 3 | // CapsulePrimitive.cs 4 | // 5 | // Microsoft XNA Community Game Platform 6 | // Copyright (C) Microsoft Corporation. All rights reserved. 7 | //----------------------------------------------------------------------------- 8 | #endregion 9 | 10 | #region Using Statements 11 | using System; 12 | using Microsoft.Xna.Framework; 13 | using Microsoft.Xna.Framework.Graphics; 14 | #endregion 15 | 16 | namespace JitterDemo.Primitives3D 17 | { 18 | /// 19 | /// Geometric primitive class for drawing spheres. 20 | /// 21 | public class CapsulePrimitive : GeometricPrimitive 22 | { 23 | /// 24 | /// Constructs a new sphere primitive, using default settings. 25 | /// 26 | public CapsulePrimitive(GraphicsDevice graphicsDevice) 27 | : this(graphicsDevice, 1.0f,0.8f, 12) 28 | { 29 | } 30 | 31 | /// 32 | /// Constructs a new sphere primitive, 33 | /// with the specified size and tessellation level. 34 | /// 35 | public CapsulePrimitive(GraphicsDevice graphicsDevice, 36 | float diameter,float length, int tessellation) 37 | { 38 | if (tessellation % 2 != 0) 39 | throw new ArgumentOutOfRangeException("tessellation should be even"); 40 | 41 | int verticalSegments = tessellation; 42 | int horizontalSegments = tessellation * 2; 43 | 44 | float radius = diameter / 2; 45 | 46 | // Start with a single vertex at the bottom of the sphere. 47 | AddVertex((Vector3.Down * radius) + (Vector3.Down * 0.5f * length), Vector3.Down); 48 | 49 | // Create rings of vertices at progressively higher latitudes. 50 | for (int i = 0; i < verticalSegments - 1; i++) 51 | { 52 | float latitude = ((i + 1) * MathHelper.Pi 53 | / verticalSegments) - MathHelper.PiOver2; 54 | float dy = (float)Math.Sin(latitude); 55 | float dxz = (float)Math.Cos(latitude); 56 | 57 | bool bla = false; 58 | 59 | if (i > (verticalSegments-2) / 2) 60 | { 61 | bla = true; 62 | } 63 | 64 | // Create a single ring of vertices at this latitude. 65 | for (int j = 0; j < horizontalSegments; j++) 66 | { 67 | float longitude = j * MathHelper.TwoPi / horizontalSegments; 68 | 69 | float dx = (float)Math.Cos(longitude) * dxz; 70 | float dz = (float)Math.Sin(longitude) * dxz; 71 | 72 | var normal = new Vector3(dx, dy, dz); 73 | var position = normal * radius; 74 | 75 | if (bla) position += Vector3.Up * 0.5f * length; 76 | else position += Vector3.Down * 0.5f * length; 77 | 78 | AddVertex(position, normal); 79 | } 80 | } 81 | 82 | // Finish with a single vertex at the top of the sphere. 83 | AddVertex((Vector3.Up * radius) + (Vector3.Up * 0.5f * length), Vector3.Up); 84 | 85 | // Create a fan connecting the bottom vertex to the bottom latitude ring. 86 | for (int i = 0; i < horizontalSegments; i++) 87 | { 88 | AddIndex(0); 89 | AddIndex(1 + ((i + 1) % horizontalSegments)); 90 | AddIndex(1 + i); 91 | } 92 | 93 | // Fill the sphere body with triangles joining each pair of latitude rings. 94 | for (int i = 0; i < verticalSegments - 2; i++) 95 | { 96 | for (int j = 0; j < horizontalSegments; j++) 97 | { 98 | int nextI = i + 1; 99 | int nextJ = (j + 1) % horizontalSegments; 100 | 101 | AddIndex(1 + (i * horizontalSegments) + j); 102 | AddIndex(1 + (i * horizontalSegments) + nextJ); 103 | AddIndex(1 + (nextI * horizontalSegments) + j); 104 | 105 | AddIndex(1 + (i * horizontalSegments) + nextJ); 106 | AddIndex(1 + (nextI * horizontalSegments) + nextJ); 107 | AddIndex(1 + (nextI * horizontalSegments) + j); 108 | } 109 | } 110 | 111 | // Create a fan connecting the top vertex to the top latitude ring. 112 | for (int i = 0; i < horizontalSegments; i++) 113 | { 114 | AddIndex(CurrentVertex - 1); 115 | AddIndex(CurrentVertex - 2 - ((i + 1) % horizontalSegments)); 116 | AddIndex(CurrentVertex - 2 - i); 117 | } 118 | 119 | InitializePrimitive(graphicsDevice); 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/ConePrimitive.cs: -------------------------------------------------------------------------------- 1 | #region File Description 2 | //----------------------------------------------------------------------------- 3 | // ConePrimitive.cs 4 | // 5 | // Microsoft XNA Community Game Platform 6 | // Copyright (C) Microsoft Corporation. All rights reserved. 7 | //----------------------------------------------------------------------------- 8 | #endregion 9 | 10 | #region Using Statements 11 | using Microsoft.Xna.Framework; 12 | using Microsoft.Xna.Framework.Graphics; 13 | using System; 14 | #endregion 15 | 16 | namespace JitterDemo.Primitives3D 17 | { 18 | /// 19 | /// Geometric primitive class for drawing cubes. 20 | /// 21 | public class ConePrimitive : GeometricPrimitive 22 | { 23 | /// 24 | /// Constructs a new cube primitive, using default settings. 25 | /// 26 | public ConePrimitive(GraphicsDevice graphicsDevice) 27 | : this(graphicsDevice, 1.0f, 1.0f, 32) 28 | { 29 | } 30 | 31 | /// 32 | /// Constructs a new cube primitive, with the specified size. 33 | /// 34 | public ConePrimitive(GraphicsDevice graphicsDevice, float height, float radius, int tessellation) 35 | { 36 | // Create a ring of triangles around the outside of the cylinder. 37 | AddVertex(Vector3.Up * (2.0f / 3.0f) * height, Vector3.Up); 38 | 39 | for (int i = 0; i < tessellation; i++) 40 | { 41 | var normal = GetCircleVector(i, tessellation); 42 | AddVertex((normal * radius) + (1.0f / 3.0f * height * Vector3.Down), normal); 43 | 44 | AddIndex(0); 45 | AddIndex(i); 46 | AddIndex(i + 1); 47 | } 48 | 49 | AddIndex(0); 50 | AddIndex(tessellation); 51 | AddIndex(1); 52 | 53 | CreateCap(tessellation, 1.0f / 3.0f * height , radius, Vector3.Down); 54 | 55 | InitializePrimitive(graphicsDevice); 56 | } 57 | 58 | /// 59 | /// Helper method creates a triangle fan to close the ends of the cylinder. 60 | /// 61 | private void CreateCap(int tessellation, float height, float radius, Vector3 normal) 62 | { 63 | // Create cap indices. 64 | for (int i = 0; i < tessellation - 2; i++) 65 | { 66 | if (normal.Y > 0) 67 | { 68 | AddIndex(CurrentVertex); 69 | AddIndex(CurrentVertex + ((i + 1) % tessellation)); 70 | AddIndex(CurrentVertex + ((i + 2) % tessellation)); 71 | } 72 | else 73 | { 74 | AddIndex(CurrentVertex); 75 | AddIndex(CurrentVertex + ((i + 2) % tessellation)); 76 | AddIndex(CurrentVertex + ((i + 1) % tessellation)); 77 | } 78 | } 79 | 80 | // Create cap vertices. 81 | for (int i = 0; i < tessellation; i++) 82 | { 83 | var position = (GetCircleVector(i, tessellation) * radius) 84 | + (normal * height); 85 | 86 | AddVertex(position, normal); 87 | } 88 | } 89 | 90 | /// 91 | /// Helper method computes a point on a circle. 92 | /// 93 | private static Vector3 GetCircleVector(int i, int tessellation) 94 | { 95 | float angle = i * MathHelper.TwoPi / tessellation; 96 | 97 | float dx = (float)Math.Cos(angle); 98 | float dz = (float)Math.Sin(angle); 99 | 100 | return new Vector3(dx, 0, dz); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/ConvexHullPrimitive.cs: -------------------------------------------------------------------------------- 1 | //using System; 2 | //using System.Collections.Generic; 3 | //using System.Linq; 4 | //using System.Text; 5 | //using Microsoft.Xna.Framework.Graphics; 6 | //using Microsoft.Xna.Framework; 7 | //using Jitter.LinearMath; 8 | //using JitterDemo; 9 | 10 | //namespace JitterDemo.Primitives3D 11 | //{ 12 | // public class ConvexHullPrimitive : GeometricPrimitive 13 | // { 14 | 15 | // //public JConvexHull ConvexHull = new JConvexHull(); 16 | 17 | // public ConvexHullPrimitive(GraphicsDevice device, List pointCloud) 18 | // { 19 | // JConvexHull.Build(pointCloud,JConvexHull.Approximation.Level5); 20 | 21 | // int counter = 0; 22 | 23 | // foreach (JConvexHull.Face face in ConvexHull.HullFaces) 24 | // { 25 | // this.AddVertex(Conversion.ToXNAVector(pointCloud[face.VertexC]), Conversion.ToXNAVector(face.Normal)); 26 | // this.AddVertex(Conversion.ToXNAVector(pointCloud[face.VertexB]), Conversion.ToXNAVector(face.Normal)); 27 | // this.AddVertex(Conversion.ToXNAVector(pointCloud[face.VertexA]), Conversion.ToXNAVector(face.Normal)); 28 | 29 | // this.AddIndex(counter + 0); 30 | // this.AddIndex(counter + 1); 31 | // this.AddIndex(counter + 2); 32 | 33 | // counter+=3; 34 | // } 35 | 36 | 37 | // this.InitializePrimitive(device); 38 | // } 39 | 40 | // } 41 | //} 42 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/CylinderPrimitive.cs: -------------------------------------------------------------------------------- 1 | #region File Description 2 | //----------------------------------------------------------------------------- 3 | // CylinderPrimitive.cs 4 | // 5 | // Microsoft XNA Community Game Platform 6 | // Copyright (C) Microsoft Corporation. All rights reserved. 7 | //----------------------------------------------------------------------------- 8 | #endregion 9 | 10 | #region Using Statements 11 | using System; 12 | using Microsoft.Xna.Framework; 13 | using Microsoft.Xna.Framework.Graphics; 14 | #endregion 15 | 16 | namespace JitterDemo.Primitives3D 17 | { 18 | /// 19 | /// Geometric primitive class for drawing cylinders. 20 | /// 21 | public class CylinderPrimitive : GeometricPrimitive 22 | { 23 | /// 24 | /// Constructs a new cylinder primitive, using default settings. 25 | /// 26 | public CylinderPrimitive(GraphicsDevice graphicsDevice) 27 | : this(graphicsDevice, 1, 1, 32) 28 | { 29 | } 30 | 31 | /// 32 | /// Constructs a new cylinder primitive, 33 | /// with the specified size and tessellation level. 34 | /// 35 | public CylinderPrimitive(GraphicsDevice graphicsDevice, 36 | float height, float radius, int tessellation) 37 | { 38 | if (tessellation < 3) 39 | throw new ArgumentOutOfRangeException(nameof(tessellation)); 40 | 41 | height /= 2; 42 | 43 | // Create a ring of triangles around the outside of the cylinder. 44 | for (int i = 0; i < tessellation; i++) 45 | { 46 | var normal = GetCircleVector(i, tessellation); 47 | 48 | AddVertex((normal * radius) + (Vector3.Up * height), normal); 49 | AddVertex((normal * radius) + (Vector3.Down * height), normal); 50 | 51 | AddIndex(i * 2); 52 | AddIndex((i * 2) + 1); 53 | AddIndex(((i * 2) + 2) % (tessellation * 2)); 54 | 55 | AddIndex((i * 2) + 1); 56 | AddIndex(((i * 2) + 3) % (tessellation * 2)); 57 | AddIndex(((i * 2) + 2) % (tessellation * 2)); 58 | } 59 | 60 | // Create flat triangle fan caps to seal the top and bottom. 61 | CreateCap(tessellation, height, radius, Vector3.Up); 62 | CreateCap(tessellation, height, radius, Vector3.Down); 63 | 64 | InitializePrimitive(graphicsDevice); 65 | } 66 | 67 | /// 68 | /// Helper method creates a triangle fan to close the ends of the cylinder. 69 | /// 70 | private void CreateCap(int tessellation, float height, float radius, Vector3 normal) 71 | { 72 | // Create cap indices. 73 | for (int i = 0; i < tessellation - 2; i++) 74 | { 75 | if (normal.Y > 0) 76 | { 77 | AddIndex(CurrentVertex); 78 | AddIndex(CurrentVertex + ((i + 1) % tessellation)); 79 | AddIndex(CurrentVertex + ((i + 2) % tessellation)); 80 | } 81 | else 82 | { 83 | AddIndex(CurrentVertex); 84 | AddIndex(CurrentVertex + ((i + 2) % tessellation)); 85 | AddIndex(CurrentVertex + ((i + 1) % tessellation)); 86 | } 87 | } 88 | 89 | // Create cap vertices. 90 | for (int i = 0; i < tessellation; i++) 91 | { 92 | var position = (GetCircleVector(i, tessellation) * radius) 93 | + (normal * height); 94 | 95 | AddVertex(position, normal); 96 | } 97 | } 98 | 99 | /// 100 | /// Helper method computes a point on a circle. 101 | /// 102 | private static Vector3 GetCircleVector(int i, int tessellation) 103 | { 104 | float angle = i * MathHelper.TwoPi / tessellation; 105 | 106 | float dx = (float)Math.Cos(angle); 107 | float dz = (float)Math.Sin(angle); 108 | 109 | return new Vector3(dx, 0, dz); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/DrawManager.cs: -------------------------------------------------------------------------------- 1 | namespace JitterDemo.Primitives3D 2 | { 3 | //public class DrawManager : DrawableGameComponent 4 | //{ 5 | 6 | // public void RegisterDraw(GeometricPrimitive primitive, Matrix world) 7 | // { 8 | // } 9 | 10 | //} 11 | } 12 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/GeometricPrimitive.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Xna.Framework; 4 | using Microsoft.Xna.Framework.Graphics; 5 | 6 | namespace JitterDemo.Primitives3D 7 | { 8 | public abstract class GeometricPrimitive : IDisposable 9 | { 10 | private readonly List vertices = new List(); 11 | private readonly List indices = new List(); 12 | 13 | private VertexBuffer vertexBuffer; 14 | private IndexBuffer indexBuffer; 15 | 16 | protected void AddVertex(Vector3 position, Vector3 normal) 17 | { 18 | vertices.Add(new VertexPositionNormal(position, normal)); 19 | } 20 | 21 | protected void AddIndex(int index) 22 | { 23 | if (index > ushort.MaxValue) 24 | throw new ArgumentOutOfRangeException(nameof(index)); 25 | 26 | indices.Add((ushort)index); 27 | } 28 | 29 | protected int CurrentVertex 30 | { 31 | get { return vertices.Count; } 32 | } 33 | 34 | protected void InitializePrimitive(GraphicsDevice graphicsDevice) 35 | { 36 | vertexBuffer = new VertexBuffer(graphicsDevice, 37 | typeof(VertexPositionNormal), 38 | vertices.Count, BufferUsage.None); 39 | 40 | vertexBuffer.SetData(vertices.ToArray()); 41 | 42 | indexBuffer = new IndexBuffer(graphicsDevice, typeof(ushort), 43 | indices.Count, BufferUsage.None); 44 | 45 | indexBuffer.SetData(indices.ToArray()); 46 | } 47 | 48 | ~GeometricPrimitive() 49 | { 50 | Dispose(false); 51 | } 52 | 53 | public void Dispose() 54 | { 55 | Dispose(true); 56 | GC.SuppressFinalize(this); 57 | } 58 | 59 | protected virtual void Dispose(bool disposing) 60 | { 61 | if (disposing) 62 | { 63 | vertexBuffer?.Dispose(); 64 | 65 | indexBuffer?.Dispose(); 66 | } 67 | } 68 | 69 | private Matrix[] worlds = new Matrix[1]; 70 | private int index = 0; 71 | 72 | public void AddWorldMatrix(Matrix matrix) 73 | { 74 | if (index == worlds.Length) 75 | { 76 | var temp = new Matrix[worlds.Length + 50]; 77 | worlds.CopyTo(temp, 0); 78 | worlds = temp; 79 | } 80 | 81 | worlds[index] = matrix; 82 | index++; 83 | } 84 | 85 | public void Draw(BasicEffect effect) 86 | { 87 | if (index == 0) return; 88 | 89 | var graphicsDevice = effect.GraphicsDevice; 90 | 91 | graphicsDevice.SetVertexBuffer(vertexBuffer); 92 | graphicsDevice.Indices = indexBuffer; 93 | 94 | int primitiveCount = indices.Count / 3; 95 | 96 | for (int i = 0; i < index; i++) 97 | { 98 | effect.World = worlds[i]; effect.CurrentTechnique.Passes[0].Apply(); 99 | graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, primitiveCount); 100 | } 101 | 102 | index = 0; 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/SpherePrimitive.cs: -------------------------------------------------------------------------------- 1 | #region File Description 2 | //----------------------------------------------------------------------------- 3 | // SpherePrimitive.cs 4 | // 5 | // Microsoft XNA Community Game Platform 6 | // Copyright (C) Microsoft Corporation. All rights reserved. 7 | //----------------------------------------------------------------------------- 8 | #endregion 9 | 10 | #region Using Statements 11 | using System; 12 | using Microsoft.Xna.Framework; 13 | using Microsoft.Xna.Framework.Graphics; 14 | #endregion 15 | 16 | namespace JitterDemo.Primitives3D 17 | { 18 | /// 19 | /// Geometric primitive class for drawing spheres. 20 | /// 21 | public class SpherePrimitive : GeometricPrimitive 22 | { 23 | /// 24 | /// Constructs a new sphere primitive, using default settings. 25 | /// 26 | public SpherePrimitive(GraphicsDevice graphicsDevice) 27 | : this(graphicsDevice, 1, 16) 28 | { 29 | } 30 | 31 | /// 32 | /// Constructs a new sphere primitive, 33 | /// with the specified size and tessellation level. 34 | /// 35 | public SpherePrimitive(GraphicsDevice graphicsDevice, 36 | float radius, int tessellation) 37 | { 38 | if (tessellation < 3) 39 | throw new ArgumentOutOfRangeException(nameof(tessellation)); 40 | 41 | int verticalSegments = tessellation; 42 | int horizontalSegments = tessellation * 2; 43 | 44 | // Start with a single vertex at the bottom of the sphere. 45 | AddVertex(Vector3.Down * radius, Vector3.Down); 46 | 47 | // Create rings of vertices at progressively higher latitudes. 48 | for (int i = 0; i < verticalSegments - 1; i++) 49 | { 50 | float latitude = ((i + 1) * MathHelper.Pi 51 | / verticalSegments) - MathHelper.PiOver2; 52 | 53 | float dy = (float)Math.Sin(latitude); 54 | float dxz = (float)Math.Cos(latitude); 55 | 56 | // Create a single ring of vertices at this latitude. 57 | for (int j = 0; j < horizontalSegments; j++) 58 | { 59 | float longitude = j * MathHelper.TwoPi / horizontalSegments; 60 | 61 | float dx = (float)Math.Cos(longitude) * dxz; 62 | float dz = (float)Math.Sin(longitude) * dxz; 63 | 64 | var normal = new Vector3(dx, dy, dz); 65 | 66 | AddVertex(normal * radius, normal); 67 | } 68 | } 69 | 70 | // Finish with a single vertex at the top of the sphere. 71 | AddVertex(Vector3.Up * radius, Vector3.Up); 72 | 73 | // Create a fan connecting the bottom vertex to the bottom latitude ring. 74 | for (int i = 0; i < horizontalSegments; i++) 75 | { 76 | AddIndex(0); 77 | AddIndex(1 + ((i + 1) % horizontalSegments)); 78 | AddIndex(1 + i); 79 | } 80 | 81 | // Fill the sphere body with triangles joining each pair of latitude rings. 82 | for (int i = 0; i < verticalSegments - 2; i++) 83 | { 84 | for (int j = 0; j < horizontalSegments; j++) 85 | { 86 | int nextI = i + 1; 87 | int nextJ = (j + 1) % horizontalSegments; 88 | 89 | AddIndex(1 + (i * horizontalSegments) + j); 90 | AddIndex(1 + (i * horizontalSegments) + nextJ); 91 | AddIndex(1 + (nextI * horizontalSegments) + j); 92 | 93 | AddIndex(1 + (i * horizontalSegments) + nextJ); 94 | AddIndex(1 + (nextI * horizontalSegments) + nextJ); 95 | AddIndex(1 + (nextI * horizontalSegments) + j); 96 | } 97 | } 98 | 99 | // Create a fan connecting the top vertex to the top latitude ring. 100 | for (int i = 0; i < horizontalSegments; i++) 101 | { 102 | AddIndex(CurrentVertex - 1); 103 | AddIndex(CurrentVertex - 2 - ((i + 1) % horizontalSegments)); 104 | AddIndex(CurrentVertex - 2 - i); 105 | } 106 | 107 | InitializePrimitive(graphicsDevice); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/TerrainPrimitive.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework.Graphics; 2 | using Microsoft.Xna.Framework; 3 | 4 | namespace JitterDemo.Primitives3D 5 | { 6 | public class TerrainPrimitive : GeometricPrimitive 7 | { 8 | public delegate float TerrainFunction(int coordX,int coordZ); 9 | 10 | public float[,] heights; 11 | 12 | public TerrainPrimitive(GraphicsDevice device,TerrainFunction function) 13 | { 14 | heights = new float[100,100]; 15 | 16 | for (int i = 0; i < 100; i++) 17 | { 18 | for (int e = 0; e < 100; e++) 19 | { 20 | heights[i,e]=function(i,e); 21 | } 22 | } 23 | 24 | var neighbour = new Vector3[4]; 25 | 26 | for (int i = 0; i < 100; i++) 27 | { 28 | for (int e = 0; e < 100; e++) 29 | { 30 | var pos = new Vector3(i, heights[i,e], e); 31 | 32 | if (i > 0) neighbour[0] = new Vector3(i - 1, heights[i - 1,e], e); 33 | else neighbour[0] = pos; 34 | 35 | if (e > 0) neighbour[1] = new Vector3(i, heights[i,e - 1], e - 1); 36 | else neighbour[1] = pos; 37 | 38 | if (i < 99) neighbour[2] = new Vector3(i +1, heights[i + 1,e], e); 39 | else neighbour[2] = pos; 40 | 41 | if (e < 99) neighbour[3] = new Vector3(i, heights[i,e+1], e+1); 42 | else neighbour[3] = pos; 43 | 44 | var normal = Vector3.Zero; 45 | 46 | normal += Vector3.Cross(neighbour[1] - pos, neighbour[0] - pos); 47 | normal += Vector3.Cross(neighbour[2] - pos, neighbour[1] - pos); 48 | normal += Vector3.Cross(neighbour[3] - pos, neighbour[2] - pos); 49 | normal += Vector3.Cross(neighbour[0] - pos, neighbour[3] - pos); 50 | normal.Normalize(); 51 | 52 | AddVertex(new Vector3(i, heights[i,e], e), normal); 53 | } 54 | } 55 | 56 | for (int i = 1; i < 100; i++) 57 | { 58 | for (int e = 1; e < 100; e++) 59 | { 60 | AddIndex(((i - 1) * 100) + e); 61 | AddIndex((i * 100) + (e - 1)); 62 | AddIndex((i * 100) + e); 63 | 64 | AddIndex((i * 100) + (e - 1)); 65 | AddIndex(((i - 1) * 100) + e); 66 | AddIndex(((i - 1) * 100) + (e - 1)); 67 | } 68 | } 69 | 70 | 71 | InitializePrimitive(device); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Primitives3D/VertexPositionNormal.cs: -------------------------------------------------------------------------------- 1 | #region File Description 2 | //----------------------------------------------------------------------------- 3 | // VertexPositionNormal.cs 4 | // 5 | // Microsoft XNA Community Game Platform 6 | // Copyright (C) Microsoft Corporation. All rights reserved. 7 | //----------------------------------------------------------------------------- 8 | #endregion 9 | 10 | #region Using Statements 11 | using Microsoft.Xna.Framework; 12 | using Microsoft.Xna.Framework.Graphics; 13 | #endregion 14 | 15 | namespace JitterDemo.Primitives3D 16 | { 17 | /// 18 | /// Custom vertex type for vertices that have just a 19 | /// position and a normal, without any texture coordinates. 20 | /// 21 | public struct VertexPositionNormal : IVertexType 22 | { 23 | public Vector3 Position; 24 | public Vector3 Normal; 25 | 26 | /// 27 | /// Constructor. 28 | /// 29 | public VertexPositionNormal(Vector3 position, Vector3 normal) 30 | { 31 | Position = position; 32 | Normal = normal; 33 | } 34 | 35 | /// 36 | /// A VertexDeclaration object, which contains information about the vertex 37 | /// elements contained within this struct. 38 | /// 39 | public static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration 40 | ( 41 | new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), 42 | new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0) 43 | ); 44 | 45 | VertexDeclaration IVertexType.VertexDeclaration 46 | { 47 | get { return VertexPositionNormal.VertexDeclaration; } 48 | } 49 | } 50 | 51 | public struct VertexPositionNormalColor : IVertexType 52 | { 53 | public Vector3 Position; 54 | public Vector3 Normal; 55 | public Vector3 Color; 56 | 57 | /// 58 | /// Constructor. 59 | /// 60 | public VertexPositionNormalColor(Vector3 position, Vector3 normal,Vector3 color) 61 | { 62 | Position = position; 63 | Normal = normal; 64 | Color = color; 65 | } 66 | 67 | /// 68 | /// A VertexDeclaration object, which contains information about the vertex 69 | /// elements contained within this struct. 70 | /// 71 | public static readonly VertexDeclaration VertexDeclaration = new VertexDeclaration 72 | ( 73 | new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0), 74 | new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0), 75 | new VertexElement(24, VertexElementFormat.Vector3, VertexElementUsage.Color, 0) 76 | ); 77 | 78 | VertexDeclaration IVertexType.VertexDeclaration 79 | { 80 | get { return VertexPositionNormalColor.VertexDeclaration; } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Program.cs: -------------------------------------------------------------------------------- 1 | namespace JitterDemo 2 | { 3 | internal static class Program 4 | { 5 | private static void Main() 6 | { 7 | using (var game = new JitterDemo()) 8 | { 9 | game.Run(); 10 | } 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("JitterDemo")] 8 | [assembly: AssemblyProduct("JitterDemo")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyCopyright("Copyright © 2015 Xamarin Inc.")] 12 | [assembly: AssemblyTrademark("")] 13 | [assembly: AssemblyCulture("")] 14 | 15 | // Setting ComVisible to false makes the types in this assembly not visible 16 | // to COM components. If you need to access a type in this assembly from 17 | // COM, set the ComVisible attribute to true on that type. Only Windows 18 | // assemblies support COM. 19 | [assembly: ComVisible(false)] 20 | 21 | // On Windows, the following GUID is for the ID of the typelib if this 22 | // project is exposed to COM. On other platforms, it unique identifies the 23 | // title storage container when deploying this assembly to the device. 24 | [assembly: Guid("85e384b8-fbb9-4f95-992d-6c8dbdf6e5bb")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | [assembly: AssemblyVersion("1.0.0.0")] 34 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/QuadDrawer.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Xna.Framework; 2 | using Microsoft.Xna.Framework.Graphics; 3 | 4 | namespace JitterDemo 5 | { 6 | public class QuadDrawer : DrawableGameComponent 7 | { 8 | private Texture2D texture; 9 | private BasicEffect effect; 10 | 11 | private readonly float size = 100.0f; 12 | 13 | private VertexPositionNormalTexture[] vertices; 14 | private int[] indices; 15 | 16 | public QuadDrawer(Game game, float size) 17 | : base(game) 18 | { 19 | this.size = size; 20 | } 21 | 22 | public override void Initialize() 23 | { 24 | BuildVertices(); 25 | base.Initialize(); 26 | } 27 | 28 | private void BuildVertices() 29 | { 30 | vertices = new VertexPositionNormalTexture[4]; 31 | indices = new int[6]; 32 | 33 | vertices[0].Position = Vector3.Forward + Vector3.Left; 34 | vertices[0].TextureCoordinate = new Vector2(0.0f, 1.0f); 35 | vertices[1].Position = Vector3.Backward + Vector3.Left; 36 | vertices[1].TextureCoordinate = new Vector2(0.0f, 0.0f); 37 | vertices[2].Position = Vector3.Forward + Vector3.Right; 38 | vertices[2].TextureCoordinate = new Vector2(1.0f, 1.0f); 39 | vertices[3].Position = Vector3.Backward + Vector3.Right; 40 | vertices[3].TextureCoordinate = new Vector2(1.0f, 0.0f); 41 | 42 | for (int i = 0; i < vertices.Length; i++) 43 | { 44 | vertices[i].Normal = Vector3.Up; 45 | vertices[i].Position *= size; 46 | vertices[i].TextureCoordinate *= size; 47 | } 48 | 49 | indices[5] = 0; indices[4] = 1; indices[3] = 2; 50 | indices[2] = 2; indices[1] = 1; indices[0] = 3; 51 | } 52 | 53 | protected override void LoadContent() 54 | { 55 | texture = Game.Content.Load("checker"); 56 | effect = new BasicEffect(GraphicsDevice); 57 | effect.EnableDefaultLighting(); 58 | effect.SpecularColor = new Vector3(0.1f, 0.1f, 0.1f); 59 | 60 | effect.World = Matrix.Identity; 61 | effect.TextureEnabled = true; 62 | 63 | effect.Texture = texture; 64 | 65 | base.LoadContent(); 66 | } 67 | 68 | protected override void Dispose(bool disposing) 69 | { 70 | base.Dispose(disposing); 71 | } 72 | 73 | public override void Draw(GameTime gameTime) 74 | { 75 | var demo = Game as JitterDemo; 76 | 77 | GraphicsDevice.SamplerStates[0] = SamplerState.AnisotropicWrap; 78 | GraphicsDevice.DepthStencilState = DepthStencilState.Default; 79 | 80 | effect.View = demo.Camera.View; 81 | effect.Projection = demo.Camera.Projection; 82 | 83 | foreach (var pass in effect.CurrentTechnique.Passes) 84 | { 85 | pass.Apply(); 86 | 87 | GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, 88 | vertices, 0, 4, indices, 0, 2); 89 | } 90 | 91 | base.Draw(gameTime); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/BroadphaseStress.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | 5 | namespace JitterDemo.Scenes 6 | { 7 | internal class BroadphaseStress : Scene 8 | { 9 | public BroadphaseStress(JitterDemo demo) 10 | : base(demo) 11 | { 12 | } 13 | 14 | public override void Build() 15 | { 16 | var shape = new BoxShape(JVector.One); 17 | 18 | // CollisionSystemBrute 170 ms 19 | // CollisionSystemSAP 7 ms 20 | // CollisionSystemPersistenSAP 1 ms 21 | 22 | for (int i = 0; i < 15; i++) 23 | { 24 | for (int e = 0; e < 15; e++) 25 | { 26 | for (int k = 0; k < 15; k++) 27 | { 28 | var b = new RigidBody(shape); 29 | Demo.World.AddBody(b); 30 | b.Position = new JVector(i, e, k) * 2.0f; 31 | b.AffectedByGravity = false; 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Cardhouse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.Xna.Framework; 4 | using Jitter.Collision.Shapes; 5 | using Jitter.Dynamics; 6 | using Jitter.LinearMath; 7 | using System.Diagnostics; 8 | 9 | namespace JitterDemo.Scenes 10 | { 11 | internal class CardHouse : Scene 12 | { 13 | public CardHouse(JitterDemo demo) : base(demo) { } 14 | 15 | private static JVector cardHouseStartingPosition = new JVector(0, 0, 0); 16 | private const int cardHouseLayers = 10; // starting from 1 17 | 18 | private const double cardThickness = 0.05; 19 | private const double cardHeight = 3; 20 | private const double cardWidth = 2; 21 | private const float degree = 75; 22 | 23 | private const float angle = degree * (float)Math.PI / 180f; 24 | private const float oppositeAngle = (float)Math.PI - angle; 25 | private static readonly double cardThicknessVerticalMargin = cardThickness / 2 * Math.Sin(MathHelper.PiOver2 - angle); 26 | private static readonly double cardThicknessHorizontalMargin = cardThickness / 2 * Math.Cos(MathHelper.PiOver2 - angle); 27 | private static readonly float layerHeight = (float)((cardHeight * Math.Sin(angle)) + (2 * cardThicknessVerticalMargin)); 28 | private static readonly float cardSpacing = (float)((cardHeight * Math.Cos(angle)) + (2 * cardThicknessHorizontalMargin)); 29 | 30 | public override void Build() 31 | { 32 | Demo.World.ContactSettings.AllowedPenetration = 0.001f; 33 | Demo.World.ContactSettings.BiasFactor = 0.05f; 34 | 35 | // Demo.World.SetIterations(60, 5); 36 | AddGround(); 37 | 38 | for (int layer = 0; layer < cardHouseLayers; layer++) 39 | { 40 | int layerCards = (cardHouseLayers - layer) * 2; 41 | 42 | AddCardLayer( 43 | cardHouseStartingPosition 44 | + new JVector(cardSpacing * layer, (layerHeight + (float)(2 * cardThickness)) * layer, 0), 45 | layerCards); 46 | } 47 | } 48 | 49 | private void AddCardLayer(JVector startPosition, int angledCards) 50 | { 51 | Debug.Assert(angledCards % 2 == 0); 52 | 53 | foreach (int i in Enumerable.Range(0, angledCards)) 54 | { 55 | AddCard( 56 | startPosition + new JVector(cardSpacing * i, layerHeight / 2f, 0), 57 | (i % 2 == 0) ? angle : oppositeAngle); 58 | } 59 | 60 | for (float distance = 1.5f; distance < angledCards - 0.5; distance += 4) 61 | { 62 | AddCard(startPosition + new JVector(cardSpacing * distance, layerHeight, 0), 0); 63 | } 64 | 65 | for (float distance = 3.5f; distance < angledCards - 0.5; distance += 4) 66 | { 67 | AddCard(startPosition + new JVector(cardSpacing * distance, layerHeight + (float)cardThickness, 0), 0); 68 | } 69 | } 70 | 71 | private void AddCard(JVector position, float rollOrientation) 72 | { 73 | var body = new RigidBody(new BoxShape((float)cardHeight, (float)cardThickness, (float)cardWidth)) 74 | { 75 | Mass = 0.5f 76 | }; 77 | body.Material.Restitution = 0; 78 | body.Position = position; 79 | if (rollOrientation != 0) 80 | { 81 | body.Orientation = JMatrix.CreateFromYawPitchRoll(0, 0, rollOrientation); 82 | } 83 | 84 | Demo.World.AddBody(body); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Cloth.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Jitter.Collision.Shapes; 6 | using Jitter.Dynamics; 7 | using Jitter.LinearMath; 8 | using Jitter.Forces; 9 | using Jitter.Dynamics.Constraints; 10 | 11 | namespace JitterDemo.Scenes 12 | { 13 | public class Cloth : Scene 14 | { 15 | 16 | public Cloth(JitterDemo demo) 17 | : base(demo) 18 | { 19 | 20 | 21 | } 22 | 23 | public override void Build() 24 | { 25 | 26 | AddGround(); 27 | 28 | // we need some of them! 29 | Demo.World.SetIterations(5); 30 | 31 | PseudoCloth pc = new PseudoCloth(Demo.World, 20,20, 0.5f); 32 | 33 | BoxShape boxShape = new BoxShape(JVector.One); 34 | 35 | RigidBody[] boxes = new RigidBody[4]; 36 | 37 | int size = 19; 38 | 39 | for(int i=0;i<4;i++) 40 | { 41 | boxes[i] = new RigidBody(boxShape); 42 | boxes[i].Position = new JVector(i % 2 == 0 ? 10.0f : -0.5f, 10.5f, (i < 2) ? 10.0f : -0.5f); 43 | // Demo.World.AddBody(boxes[i]); 44 | 45 | 46 | 47 | if (i == 0) 48 | { 49 | 50 | pc.GetCorner(size, size).IsStatic = true; 51 | } 52 | else if (i == 1) 53 | { 54 | 55 | pc.GetCorner(size, 0).IsStatic = true; 56 | } 57 | else if (i == 2) 58 | { 59 | 60 | pc.GetCorner(0, size).IsStatic = true; 61 | } 62 | else if (i == 3) 63 | { 64 | 65 | pc.GetCorner(0, 0).IsStatic = true; 66 | } 67 | 68 | boxes[i].IsStatic = true; 69 | } 70 | 71 | RigidBody sphereBody = new RigidBody(new SphereShape(2.0f)); 72 | Demo.World.AddBody(sphereBody); 73 | sphereBody.Mass = 10.0f; 74 | sphereBody.Position = new JVector(5, 20, 5); 75 | 76 | //ConvexHullObject2 obj2 = new ConvexHullObject2(this.Demo); 77 | //Demo.Components.Add(obj2); 78 | 79 | //obj2.body.Position = new JVector(5, 30, 5); 80 | //Demo.World.AddBody(obj2.body); 81 | 82 | } 83 | 84 | public override void Destroy() 85 | { 86 | RemoveGround(); 87 | this.Demo.World.Clear(); 88 | } 89 | 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/ConvexDecomposition.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using Jitter.LinearMath; 5 | #if WINDOWS 6 | 7 | using System.Globalization; 8 | using Jitter.Collision.Shapes; 9 | using Jitter.Dynamics; 10 | 11 | namespace JitterDemo.Scenes 12 | { 13 | internal class ConvexDecomposition : Scene 14 | { 15 | public ConvexDecomposition(JitterDemo demo) 16 | : base(demo) 17 | { 18 | } 19 | 20 | public override void Build() 21 | { 22 | AddGround(); 23 | 24 | var shapes = BuildFromHACDTestObjFile(@"Content/ConvexDecomposition.obj"); 25 | 26 | var transformedShapes 27 | = new CompoundShape.TransformedShape[shapes.Count]; 28 | 29 | for (int i = 0; i < shapes.Count; i++) 30 | { 31 | transformedShapes[i] = new CompoundShape.TransformedShape 32 | { 33 | Shape = shapes[i], 34 | Orientation = JMatrix.Identity, 35 | Position = -1.0f * shapes[i].Shift 36 | }; 37 | } 38 | 39 | // Create one compound shape 40 | var cs = new CompoundShape(transformedShapes); 41 | 42 | for (int i = 0; i < 1; i++) 43 | { 44 | var compoundBody = new RigidBody(cs) 45 | { 46 | EnableDebugDraw = true, 47 | Position = new JVector(0, 5 + (i * 10), 0) - cs.Shift 48 | }; 49 | Demo.World.AddBody(compoundBody); 50 | } 51 | 52 | // Create several single bodies. 53 | for (int i = 0; i < shapes.Count; i++) 54 | { 55 | var body = new RigidBody(shapes[i]) 56 | { 57 | Position = (-1.0f * shapes[i].Shift) + new JVector(-10, 5, 0), 58 | EnableDebugDraw = true 59 | }; 60 | Demo.World.AddBody(body); 61 | } 62 | 63 | for (int i = 0; i < shapes.Count; i++) 64 | { 65 | var body = new RigidBody(shapes[i]) 66 | { 67 | Position = (-1.0f * shapes[i].Shift) + new JVector(-20, 5, 0), 68 | EnableDebugDraw = true, 69 | IsStatic = true 70 | }; 71 | Demo.World.AddBody(body); 72 | } 73 | } 74 | 75 | /// 76 | /// A really stupid parser for convex decomposed files made by testhacd.exe (see Other\hacdtest) 77 | /// 78 | public List BuildFromHACDTestObjFile(string path) 79 | { 80 | var shapes = new List(); 81 | 82 | string[] lines = File.ReadAllLines(path); 83 | Char[] splitter = new Char [] {' '}; 84 | 85 | var convexPoints = new List(); 86 | 87 | for (int i = 0; i < lines.Length; i++) 88 | { 89 | string line = lines[i]; 90 | 91 | if (line.StartsWith("v")) 92 | { 93 | string[] values = line.Split(splitter); 94 | 95 | var vertex = new JVector(float.Parse(values[1], NumberFormatInfo.InvariantInfo), 96 | float.Parse(values[2], NumberFormatInfo.InvariantInfo), 97 | float.Parse(values[3], NumberFormatInfo.InvariantInfo)); 98 | 99 | convexPoints.Add(vertex * 5f); 100 | } 101 | 102 | if(line.StartsWith("#")) 103 | { 104 | if(convexPoints.Count > 0) 105 | { 106 | var copyVertex = new List(convexPoints); 107 | convexPoints.Clear(); 108 | 109 | var cvhs = new ConvexHullShape(copyVertex); 110 | 111 | if(cvhs.Mass > 0.001f) shapes.Add(cvhs); 112 | } 113 | } 114 | } 115 | 116 | return shapes; 117 | } 118 | } 119 | } 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/CylinderWall.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | 5 | namespace JitterDemo.Scenes 6 | { 7 | internal class CylinderWall : Scene 8 | { 9 | public CylinderWall(JitterDemo demo) 10 | : base(demo) 11 | { 12 | } 13 | 14 | public override void Build() 15 | { 16 | AddGround(); 17 | 18 | for (int i = 0; i < 20; i++) 19 | { 20 | for (int e = 0; e < 20; e++) 21 | { 22 | var body = new RigidBody(new CylinderShape(1.0f, 0.5f)) 23 | { 24 | Position = new JVector((e * 1.01f) + ((i % 2 == 0) ? 0.5f : 0.0f), 0.5f + (i * 1.0f), 0.0f) 25 | }; 26 | Demo.World.AddBody(body); 27 | } 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Domino.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | 5 | namespace JitterDemo.Scenes 6 | { 7 | public class Domino : Scene 8 | { 9 | public Domino(JitterDemo demo) : base(demo) 10 | { 11 | } 12 | 13 | public override void Build() 14 | { 15 | //this.Demo.World.Solver = Jitter.World.SolverType.Sequential; 16 | 17 | AddGround(); 18 | 19 | var bShape = new BoxShape(0.5f, 4.0f, 2.0f); 20 | 21 | for (int i = 0; i < 10; i++) 22 | { 23 | var body = new RigidBody(bShape) 24 | { 25 | Position = new JVector(i * 2.0f, 2, 0) 26 | }; 27 | Demo.World.AddBody(body); 28 | } 29 | 30 | ground.Material.Restitution = 0.0f; 31 | ground.Material.StaticFriction = 0.4f; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/EmptyScene.cs: -------------------------------------------------------------------------------- 1 | namespace JitterDemo.Scenes 2 | { 3 | public class EmptyScene : Scene 4 | { 5 | public EmptyScene(JitterDemo demo) 6 | : base(demo) 7 | { 8 | } 9 | 10 | public override void Build() 11 | { 12 | AddGround(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Jenga.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | 5 | namespace JitterDemo.Scenes 6 | { 7 | internal class Jenga : Scene 8 | { 9 | public Jenga(JitterDemo demo) 10 | : base(demo) 11 | { 12 | } 13 | 14 | public override void Build() 15 | { 16 | AddGround(); 17 | 18 | for (int i = 0; i < 15; i++) 19 | { 20 | bool even = i % 2 == 0; 21 | 22 | for (int e = 0; e < 3; e++) 23 | { 24 | var size = even ? new JVector(1, 1, 3) : new JVector(3, 1, 1); 25 | var body = new RigidBody(new BoxShape(size)) 26 | { 27 | Position = new JVector(3.0f + (even ? e : 1.0f), i + 0.5f, -13.0f + (even ? 1.0f : e)) 28 | }; 29 | 30 | Demo.World.AddBody(body); 31 | } 32 | } 33 | 34 | //BoxShape bs = new BoxShape(10, 10, 0.01f); 35 | //RigidBody bb = new RigidBody(bs); 36 | 37 | //bb.Position = new JVector(10, 5, 0); 38 | 39 | //Demo.World.AddBody(bb); 40 | //bb.IsStatic = true; 41 | 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/NewtonCradle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Jitter.Collision.Shapes; 6 | using Jitter.Dynamics; 7 | using Jitter.LinearMath; 8 | using Jitter.Dynamics.Constraints; 9 | 10 | namespace JitterDemo.Scenes 11 | { 12 | public class NewtonCradle : Scene 13 | { 14 | 15 | public NewtonCradle(JitterDemo demo) 16 | : base(demo) 17 | { 18 | } 19 | 20 | public override void Build() 21 | { 22 | this.Demo.World.Solver = Jitter.World.SolverType.Sequential; 23 | 24 | AddGround(); 25 | 26 | RigidBody boxb = new RigidBody(new BoxShape(7,1,2)); 27 | boxb.Position = new JVector(3.0f,12,0); 28 | this.Demo.World.AddBody(boxb); 29 | boxb.Tag = BodyTag.DontDrawMe; 30 | 31 | boxb.IsStatic = true; 32 | 33 | this.Demo.World.Solver = Jitter.World.SolverType.Sequential; 34 | //this.Demo.World.SetDampingFactors(1.0f, 1.0f); 35 | 36 | SphereShape shape = new SphereShape(0.501f); 37 | 38 | for (int i = 0; i < 7; i++) 39 | { 40 | RigidBody body = new RigidBody(shape); 41 | body.Position = new JVector(i, 6, 0); 42 | 43 | DistanceConstraint dc1 = new DistanceConstraint(boxb, body, body.Position + JVector.Up * 6 + JVector.Backward * 5 + JVector.Down * 0.5f, body.Position); 44 | dc1.Softness = 1.0f; 45 | 46 | DistanceConstraint dc2 = new DistanceConstraint(boxb, body, body.Position + JVector.Up * 6 + JVector.Forward * 5 + JVector.Down * 0.5f, body.Position); 47 | dc2.Softness = 1.0f; 48 | 49 | dc1.BiasFactor = dc2.BiasFactor = 0.8f; 50 | 51 | dc1.IsMaxDistance = dc2.IsMaxDistance = false; 52 | 53 | this.Demo.World.AddBody(body); 54 | this.Demo.World.AddConstraint(dc1); 55 | this.Demo.World.AddConstraint(dc2); 56 | 57 | body.Restitution = 1.0f; 58 | body.StaticFriction = 1.0f; 59 | 60 | // this.Demo.World.SetDampingFactors(1.0f, 1.0f); 61 | } 62 | 63 | //for (int i = 0; i < 5; i++) 64 | //{ 65 | // RigidBody sBody = new RigidBody(new SphereShape(0.5f)); 66 | // sBody.Position = new JVector(0, 0.5f, i); 67 | // this.Demo.World.AddBody(sBody); 68 | // sBody.Restitution = 1.0f; 69 | // sBody.Friction = 0.0f; 70 | //} 71 | 72 | //for (int i = 0; i < 3; i++) 73 | //{ 74 | // RigidBody sBody = new RigidBody(new SphereShape(0.5f)); 75 | // sBody.Position = new JVector(0, 0.5f, 10 + i); 76 | // this.Demo.World.AddBody(sBody); 77 | // sBody.LinearVelocity = JVector.Forward * 3; 78 | // sBody.Restitution = 1.0f; 79 | // sBody.Friction = 0.0f; 80 | //} 81 | 82 | 83 | 84 | //this.Demo.World.SetDampingFactors(1, 1); 85 | 86 | 87 | } 88 | 89 | public override void Destroy() 90 | { 91 | this.Demo.World.Solver = Jitter.World.SolverType.Simultaneous; 92 | 93 | RemoveGround(); 94 | this.Demo.World.Clear(); 95 | } 96 | 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/PrismaticJointTest.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | using Jitter.Dynamics.Joints; 5 | 6 | namespace JitterDemo.Scenes 7 | { 8 | public class PrismaticJointTest : Scene 9 | { 10 | public PrismaticJointTest(JitterDemo demo) 11 | : base(demo) 12 | { 13 | } 14 | 15 | public override void Build() 16 | { 17 | AddGround(); 18 | 19 | var body1 = new RigidBody(new BoxShape(1, 1, 1)); 20 | var body2 = new RigidBody(new BoxShape(1, 1, 1)); 21 | 22 | body1.Position = new JVector(0, 7, 0); 23 | body2.Position = new JVector(0, 4, 0); 24 | 25 | // add a prismatic joint. 26 | // the minimum allowed distance is 3 27 | // the maximum allowed distance is also 3 28 | // => the body should be fixed on the slider 29 | var pj = new PrismaticJoint(Demo.World, body1, body2, 3, 3); 30 | 31 | // but we set very heigh softness (1.0f) to the minimum distance 32 | // so we have something like a suspension effect. 33 | pj.MaximumDistanceConstraint.Softness = 0.0f; 34 | pj.MinimumDistanceConstraint.Softness = 1.0f; 35 | pj.Activate(); 36 | 37 | Demo.World.AddBody(body1); 38 | Demo.World.AddBody(body2); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Pyramid.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | 5 | namespace JitterDemo.Scenes 6 | { 7 | internal class Pyramid : Scene 8 | { 9 | public Pyramid(JitterDemo demo) 10 | : base(demo) 11 | { 12 | } 13 | 14 | public override void Build() 15 | { 16 | AddGround(); 17 | 18 | for (int i = 0; i < 30; i++) 19 | { 20 | for (int e = i; e < 30; e++) 21 | { 22 | var body = new RigidBody(new BoxShape(new JVector(1.0f, 1.0f, 1.0f))) 23 | { 24 | Position = new JVector(((e - (i * 0.5f)) * 1.01f) + 7, 0.5f + (i * 1.0f), 3.0f) 25 | }; 26 | Demo.World.AddBody(body); 27 | //body.IsParticle = true; 28 | //body.AffectedByGravity = false; 29 | body.Material.Restitution = 0.0f; 30 | } 31 | } 32 | 33 | //BoxShape shape = new BoxShape(JVector.One); 34 | 35 | //for (int i = 0; i < 20; i++) 36 | //{ 37 | // for (int e = 0; e < 20; e++) 38 | // { 39 | // for (int k = 0; k < 20; k++) 40 | // { 41 | // RigidBody b = new RigidBody(shape); 42 | // Demo.World.AddBody(b); 43 | // b.Position = new JVector(i, e, k) * 2.0f; 44 | // b.AffectedByGravity = false; 45 | // } 46 | // } 47 | //} 48 | 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Ragdoll.cs: -------------------------------------------------------------------------------- 1 | using Jitter; 2 | using Jitter.Collision.Shapes; 3 | using Jitter.Dynamics; 4 | using Jitter.LinearMath; 5 | using Jitter.Dynamics.Constraints; 6 | using Jitter.Dynamics.Joints; 7 | 8 | namespace JitterDemo.Scenes 9 | { 10 | internal class Ragdoll : Scene 11 | { 12 | public Ragdoll(JitterDemo demo) 13 | : base(demo) 14 | { 15 | } 16 | 17 | public override void Build() 18 | { 19 | AddGround(); 20 | 21 | //RigidBody body = new RigidBody(new BoxShape(JVector.One * 3)); 22 | //body.Position = new JVector(0, 5, 0); 23 | //body.UseUserMassProperties(JMatrix.Zero, 1f, true); 24 | //Demo.World.AddBody(body); 25 | 26 | for (int i = 3; i < 8; i++) 27 | { 28 | for (int e = 3; e < 8; e++) 29 | { 30 | BuildRagdoll(Demo.World, new JVector((i * 6) - 25, 5, (e * 6) - 25)); 31 | } 32 | } 33 | } 34 | 35 | public void BuildRagdoll(World world, JVector position) 36 | { 37 | // the torso 38 | var torso = new RigidBody(new BoxShape(1.5f, 3, 0.5f)) 39 | { 40 | Position = position 41 | }; 42 | 43 | // the head 44 | var head = new RigidBody(new SphereShape(0.5f)) 45 | { 46 | Position = position + new JVector(0, 2.1f, 0) 47 | }; 48 | 49 | // connect head and torso 50 | var headTorso = new PointPointDistance(head, torso, 51 | position + new JVector(0, 1.6f, 0), position + new JVector(0, 1.5f, 0)); 52 | 53 | var arm1 = new RigidBody(new CapsuleShape(0.8f, 0.2f)) 54 | { 55 | Position = position + new JVector(1.0f, 0.75f, 0) 56 | }; 57 | 58 | var arm2 = new RigidBody(new CapsuleShape(0.8f, 0.2f)) 59 | { 60 | Position = position + new JVector(-1.0f, 0.75f, 0) 61 | }; 62 | 63 | var lowerarm1 = new RigidBody(new CapsuleShape(0.6f, 0.2f)) 64 | { 65 | Position = position + new JVector(1.0f, -0.45f, 0) 66 | }; 67 | 68 | var lowerarm2 = new RigidBody(new CapsuleShape(0.6f, 0.2f)) 69 | { 70 | Position = position + new JVector(-1.0f, -0.45f, 0) 71 | }; 72 | 73 | var arm1torso = new PointOnPoint(arm1, torso, position + new JVector(0.9f, 1.4f, 0)); 74 | var arm2torso = new PointOnPoint(arm2, torso, position + new JVector(-0.9f, 1.4f, 0)); 75 | 76 | var arm1Hinge = new HingeJoint(world, arm1, lowerarm1, position + new JVector(1.0f, 0.05f, 0), JVector.Right); 77 | var arm2Hinge = new HingeJoint(world, arm2, lowerarm2, position + new JVector(-1.0f, 0.05f, 0), JVector.Right); 78 | 79 | var leg1 = new RigidBody(new CapsuleShape(1.0f, 0.3f)) 80 | { 81 | Position = position + new JVector(-0.5f, -2.4f, 0) 82 | }; 83 | 84 | var leg2 = new RigidBody(new CapsuleShape(1.0f, 0.3f)) 85 | { 86 | Position = position + new JVector(0.5f, -2.4f, 0) 87 | }; 88 | 89 | var leg1torso = new PointOnPoint(leg1, torso, position + new JVector(-0.5f, -1.6f, 0)); 90 | var leg2torso = new PointOnPoint(leg2, torso, position + new JVector(+0.5f, -1.6f, 0)); 91 | 92 | var lowerleg1 = new RigidBody(new CapsuleShape(0.8f, 0.3f)) 93 | { 94 | Position = position + new JVector(-0.5f, -4.0f, 0) 95 | }; 96 | 97 | var lowerleg2 = new RigidBody(new CapsuleShape(0.8f, 0.3f)) 98 | { 99 | Position = position + new JVector(+0.5f, -4.0f, 0) 100 | }; 101 | 102 | var leg1Hinge = new HingeJoint(world, leg1, lowerleg1, position + new JVector(-0.5f, -3.35f, 0), JVector.Right); 103 | var leg2Hinge = new HingeJoint(world, leg2, lowerleg2, position + new JVector(0.5f, -3.35f, 0), JVector.Right); 104 | 105 | lowerleg1.IsActive = false; 106 | lowerleg2.IsActive = false; 107 | leg1.IsActive = false; 108 | leg2.IsActive = false; 109 | head.IsActive = false; 110 | torso.IsActive = false; 111 | arm1.IsActive = false; 112 | arm2.IsActive = false; 113 | lowerarm1.IsActive = false; 114 | lowerarm2.IsActive = false; 115 | 116 | world.AddBody(head); world.AddBody(torso); 117 | world.AddBody(arm1); world.AddBody(arm2); 118 | world.AddBody(lowerarm1); world.AddBody(lowerarm2); 119 | world.AddBody(leg1); world.AddBody(leg2); 120 | world.AddBody(lowerleg1); world.AddBody(lowerleg2); 121 | 122 | arm1Hinge.Activate(); arm2Hinge.Activate(); 123 | leg1Hinge.Activate(); leg2Hinge.Activate(); 124 | 125 | world.AddConstraint(headTorso); 126 | world.AddConstraint(arm1torso); 127 | world.AddConstraint(arm2torso); 128 | world.AddConstraint(leg1torso); 129 | world.AddConstraint(leg2torso); 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Restitution.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | 5 | namespace JitterDemo.Scenes 6 | { 7 | internal class Restitution : Scene 8 | { 9 | public Restitution(JitterDemo demo) 10 | : base(demo) 11 | { 12 | } 13 | 14 | public override void Build() 15 | { 16 | AddGround(); 17 | 18 | for (int i = 0; i < 11; i++) 19 | { 20 | var box = new RigidBody(new BoxShape(1,0.01f,1)); 21 | Demo.World.AddBody(box); 22 | var boxPos = new JVector(-15 + (i * 3) + 1, 5, 0); 23 | 24 | box.Position = boxPos; 25 | box.IsStatic = true; 26 | 27 | var sphere = new RigidBody(new SphereShape(0.5f)); 28 | Demo.World.AddBody(sphere); 29 | 30 | sphere.Position = boxPos + (JVector.Up * 30); 31 | sphere.EnableSpeculativeContacts = true; 32 | 33 | // set restitution 34 | sphere.Material.Restitution = box.Material.Restitution = 1.0f / 10.0f * i; 35 | sphere.LinearVelocity = new JVector(0, 0, 0); 36 | 37 | 38 | sphere.Damping = RigidBody.DampingType.Angular; 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Rope.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | using Jitter.Dynamics.Constraints; 5 | 6 | namespace JitterDemo.Scenes 7 | { 8 | internal class Rope : Scene 9 | { 10 | public Rope(JitterDemo demo) 11 | : base(demo) 12 | { 13 | } 14 | 15 | public override void Build() 16 | { 17 | AddGround(); 18 | 19 | RigidBody last = null; 20 | 21 | for (int i = 0; i < 12; i++) 22 | { 23 | var body = new RigidBody(new BoxShape(JVector.One)) 24 | { 25 | Position = new JVector((i * 1.5f) - 20, 0.5f, 0) 26 | }; 27 | 28 | var jpos2 = body.Position; 29 | 30 | Demo.World.AddBody(body); 31 | body.Update(); 32 | 33 | if (last != null) 34 | { 35 | var jpos3 = last.Position; 36 | 37 | JVector.Subtract(ref jpos2, ref jpos3, out var dif); 38 | JVector.Multiply(ref dif, 0.5f, out dif); 39 | JVector.Subtract(ref jpos2, ref dif, out dif); 40 | 41 | Constraint cons = new PointOnPoint(last, body, dif); 42 | Demo.World.AddConstraint(cons); 43 | } 44 | 45 | last = body; 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Scene.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Dynamics; 2 | using Jitter.LinearMath; 3 | using Jitter.Collision.Shapes; 4 | using JitterDemo.Vehicle; 5 | 6 | namespace JitterDemo.Scenes 7 | { 8 | public abstract class Scene 9 | { 10 | public JitterDemo Demo { get; } 11 | 12 | public Scene(JitterDemo demo) 13 | { 14 | Demo = demo; 15 | } 16 | 17 | public abstract void Build(); 18 | 19 | private QuadDrawer quadDrawer = null; 20 | protected RigidBody ground = null; 21 | protected CarObject car = null; 22 | 23 | public void AddGround() 24 | { 25 | ground = new RigidBody(new BoxShape(new JVector(200, 20, 200))) 26 | { 27 | Position = new JVector(0, -10, 0), 28 | Tag = BodyTag.DontDrawMe, 29 | IsStatic = true 30 | }; 31 | Demo.World.AddBody(ground); 32 | //ground.Restitution = 1.0f; 33 | ground.Material.KineticFriction = 0.0f; 34 | 35 | quadDrawer = new QuadDrawer(Demo,100); 36 | Demo.Components.Add(quadDrawer); 37 | } 38 | 39 | public void RemoveGround() 40 | { 41 | Demo.World.RemoveBody(ground); 42 | Demo.Components.Remove(quadDrawer); 43 | quadDrawer.Dispose(); 44 | } 45 | 46 | public void AddCar(JVector position) 47 | { 48 | car = new CarObject(Demo); 49 | Demo.Components.Add(car); 50 | 51 | car.carBody.Position = position; 52 | } 53 | 54 | public void RemoveCar() 55 | { 56 | Demo.World.RemoveBody(car.carBody); 57 | Demo.Components.Remove(quadDrawer); 58 | Demo.Components.Remove(car); 59 | } 60 | 61 | public virtual void Draw() { } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/SoftBodyJenga.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Jitter.Collision.Shapes; 3 | using Jitter.Dynamics; 4 | using Jitter.LinearMath; 5 | using Microsoft.Xna.Framework.Graphics; 6 | using Jitter.Collision; 7 | 8 | namespace JitterDemo.Scenes 9 | { 10 | internal class SoftBodyJenga : Scene 11 | { 12 | public SoftBodyJenga(JitterDemo demo) 13 | : base(demo) 14 | { 15 | } 16 | 17 | private void RemoveDuplicateVertices(List indices, 18 | List vertices) 19 | { 20 | var unique = new Dictionary(vertices.Count); 21 | var tbr = new Stack(vertices.Count / 3); 22 | 23 | // get all unique vertices and their indices 24 | for (int i = 0; i < vertices.Count; i++) 25 | { 26 | if (!unique.ContainsKey(vertices[i])) 27 | unique.Add(vertices[i], unique.Count); 28 | else tbr.Push(i); 29 | } 30 | 31 | // reconnect indices 32 | for (int i = 0; i < indices.Count; i++) 33 | { 34 | var tvi = indices[i]; 35 | 36 | tvi.I0 = unique[vertices[tvi.I0]]; 37 | tvi.I1 = unique[vertices[tvi.I1]]; 38 | tvi.I2 = unique[vertices[tvi.I2]]; 39 | 40 | indices[i] = tvi; 41 | } 42 | 43 | // remove duplicate vertices 44 | while (tbr.Count > 0) vertices.RemoveAt(tbr.Pop()); 45 | 46 | unique.Clear(); 47 | } 48 | 49 | public override void Build() 50 | { 51 | AddGround(); 52 | 53 | for (int i = 0; i < 15; i++) 54 | { 55 | bool even = i % 2 == 0; 56 | 57 | for (int e = 0; e < 3; e++) 58 | { 59 | var size = even ? new JVector(1, 1, 3) : new JVector(3, 1, 1); 60 | var body = new RigidBody(new BoxShape(size)) 61 | { 62 | Position = new JVector(3.0f + (even ? e : 1.0f), i + 0.5f, -5.0f + (even ? 1.0f : e)) 63 | }; 64 | 65 | Demo.World.AddBody(body); 66 | } 67 | } 68 | 69 | var model = Demo.Content.Load("torus"); 70 | 71 | var indices = new List(); 72 | var vertices = new List(); 73 | 74 | ConvexHullObject.ExtractData(vertices, indices, model); 75 | RemoveDuplicateVertices(indices, vertices); 76 | 77 | var softBody = new SoftBody(indices, vertices); 78 | 79 | softBody.Translate(new JVector(10, 5, 0)); 80 | softBody.Pressure = 1000.0f; 81 | softBody.SetSpringValues(0.2f, 0.005f); 82 | //softBody.SelfCollision = true; ; 83 | 84 | Demo.World.AddBody(softBody); 85 | 86 | var cloth = new SoftBody(20,20,0.4f); 87 | 88 | // ##### Uncomment for selfcollision, all 3 lines 89 | //cloth.SelfCollision = true; 90 | //cloth.TriangleExpansion = 0.05f; 91 | //cloth.VertexExpansion = 0.05f; 92 | 93 | cloth.Translate(new JVector(0, 10, 10)); 94 | 95 | cloth.Material.KineticFriction = 0.9f; 96 | cloth.Material.StaticFriction = 0.95f; 97 | 98 | cloth.VertexBodies[0].IsStatic = true; 99 | cloth.VertexBodies[380].IsStatic = true; 100 | cloth.VertexBodies[19].IsStatic = true; 101 | cloth.VertexBodies[399].IsStatic = true; 102 | 103 | cloth.SetSpringValues(SoftBody.SpringType.EdgeSpring, 0.1f, 0.01f); 104 | cloth.SetSpringValues(SoftBody.SpringType.ShearSpring, 0.1f, 0.03f); 105 | cloth.SetSpringValues(SoftBody.SpringType.BendSpring, 0.1f, 0.03f); 106 | 107 | // ###### Uncomment here for a better visualization 108 | // Demo.Components.Add(new ClothObject(Demo, cloth)); 109 | 110 | Demo.World.AddBody(cloth); 111 | } 112 | } 113 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Terrain.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.Xna.Framework; 3 | using Jitter.Collision.Shapes; 4 | using Jitter.Dynamics; 5 | using Jitter.LinearMath; 6 | 7 | namespace JitterDemo.Scenes 8 | { 9 | public class Terrain : Scene 10 | { 11 | private Primitives3D.TerrainPrimitive terrain; 12 | 13 | public Terrain(JitterDemo demo) 14 | : base(demo) 15 | { 16 | } 17 | 18 | public override void Build() 19 | { 20 | terrain = new Primitives3D.TerrainPrimitive(Demo.GraphicsDevice, 21 | (a, b) => 22 | { 23 | return (float)(Math.Cos(a * 0.2f) * Math.Sin(b * 0.2f) * 2.0f); 24 | }); 25 | 26 | var shape = new TerrainShape(terrain.heights, 1.0f, 1.0f); 27 | 28 | var body = new RigidBody(shape); 29 | body.Position -= new JVector(50, 0, 50); 30 | body.IsStatic = true; 31 | body.Tag = BodyTag.DontDrawMe; 32 | //body.EnableDebugDraw = true; 33 | Demo.World.AddBody(body); 34 | 35 | AddCar(new JVector(0, 4, 0)); 36 | } 37 | 38 | public override void Draw() 39 | { 40 | terrain.AddWorldMatrix(Matrix.CreateTranslation(-50, 0, -50)); 41 | Demo.BasicEffect.DiffuseColor = Color.Red.ToVector3(); 42 | terrain.Draw(Demo.BasicEffect); 43 | base.Draw(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Tower.cs: -------------------------------------------------------------------------------- 1 | using Jitter; 2 | using Microsoft.Xna.Framework; 3 | using Jitter.Collision.Shapes; 4 | using Jitter.Dynamics; 5 | 6 | namespace JitterDemo.Scenes 7 | { 8 | internal class Tower : Scene 9 | { 10 | public Tower(JitterDemo demo) 11 | : base(demo) 12 | { 13 | } 14 | 15 | public override void Build() 16 | { 17 | AddGround(); 18 | 19 | var world = Demo.World; 20 | 21 | var halfRotationStep = Matrix.CreateRotationY(MathHelper.Pi * 2.0f / 24.0f); 22 | var fullRotationStep = halfRotationStep * halfRotationStep; 23 | var orientation = Matrix.Identity; 24 | 25 | var shape = new BoxShape(2, 1, 1); 26 | 27 | //for (int i = 0; i < 15; i++) 28 | //{ 29 | // for (int e = 0; e < 15; e++) 30 | // { 31 | // for (int k = 0; k < 15; k++) 32 | // { 33 | // RigidBody b = new RigidBody(shape); 34 | // Demo.World.AddBody(b); 35 | // b.Position = new JVector(i, e, k) * 4.0f; 36 | // b.AffectedByGravity = true; 37 | // } 38 | // } 39 | //} 40 | 41 | for (int e = 0; e < 40; e++) 42 | { 43 | orientation *= halfRotationStep; 44 | 45 | for (int i = 0; i < 12; i++) 46 | { 47 | var position = Vector3.Transform( 48 | new Vector3(0, 0.5f + e, 6.5f), orientation); 49 | 50 | var body = new RigidBody(shape) 51 | { 52 | Orientation = Conversion.ToJitterMatrix(orientation), 53 | Position = Conversion.ToJitterVector(position) 54 | }; 55 | 56 | world.AddBody(body); 57 | 58 | orientation *= fullRotationStep; 59 | } 60 | } 61 | 62 | //for (int e = 0; e < 40; e++) 63 | //{ 64 | // orientation *= halfRotationStep; 65 | 66 | // for (int i = 0; i < 12; i++) 67 | // { 68 | // Vector3 position = Vector3.Transform( 69 | // new Vector3(0, 0.5f + e, 6.5f), orientation); 70 | 71 | // RigidBody body = new RigidBody(shape); 72 | // body.Orientation = Conversion.ToJitterMatrix(orientation); 73 | // body.Position = Conversion.ToJitterVector(position) + new JVector(20,0,0); 74 | 75 | // world.AddBody(body); 76 | 77 | // orientation *= fullRotationStep; 78 | // } 79 | //} 80 | 81 | //for (int e = 0; e < 40; e++) 82 | //{ 83 | // orientation *= halfRotationStep; 84 | 85 | // for (int i = 0; i < 12; i++) 86 | // { 87 | // Vector3 position = Vector3.Transform( 88 | // new Vector3(0, 0.5f + e, 6.5f), orientation); 89 | 90 | // RigidBody body = new RigidBody(shape); 91 | // body.Orientation = Conversion.ToJitterMatrix(orientation); 92 | // body.Position = Conversion.ToJitterVector(position) + new JVector(00, 0, -20); ; 93 | 94 | // world.AddBody(body); 95 | 96 | // orientation *= fullRotationStep; 97 | // } 98 | //} 99 | 100 | //for (int e = 0; e < 40; e++) 101 | //{ 102 | // orientation *= halfRotationStep; 103 | 104 | // for (int i = 0; i < 12; i++) 105 | // { 106 | // Vector3 position = Vector3.Transform( 107 | // new Vector3(0, 0.5f + e, 6.5f), orientation); 108 | 109 | // RigidBody body = new RigidBody(shape); 110 | // body.Orientation = Conversion.ToJitterMatrix(orientation); 111 | // body.Position = Conversion.ToJitterVector(position) + new JVector(20, 0, -20); 112 | 113 | // world.AddBody(body); 114 | 115 | // orientation *= fullRotationStep; 116 | // } 117 | //} 118 | 119 | //for (int i = 0; i < 15; i++) 120 | //{ 121 | // for (int k = 0; k < 15; k++) 122 | // { 123 | // for (int l = 0; l < 15; l++) 124 | // { 125 | // RigidBody body = new RigidBody(new BoxShape(1, 1, 1)); 126 | // this.Demo.World.AddBody(body); 127 | // body.AffectedByGravity = false; 128 | // body.Position = new JVector(i, k, l) * 2.0f; 129 | // body.Restitution = 1.0f; 130 | // body.Damping = RigidBody.DampingType.None; 131 | // body.IsActive = false; 132 | // } 133 | // } 134 | //} 135 | 136 | ground.Material.StaticFriction = 1.0f; 137 | ground.Material.KineticFriction = 1.0f; 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/TriangleMesh.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.Xna.Framework.Graphics; 4 | using Microsoft.Xna.Framework; 5 | using Jitter.LinearMath; 6 | using Jitter.Collision.Shapes; 7 | using Jitter.Dynamics; 8 | using Jitter.Collision; 9 | 10 | namespace JitterDemo.Scenes 11 | { 12 | public class TriangleMesh : Scene 13 | { 14 | private Model model; 15 | 16 | public TriangleMesh(JitterDemo demo) 17 | : base(demo) 18 | { 19 | } 20 | 21 | /// 22 | /// Helper Method to get the vertex and index List from the model. 23 | /// 24 | /// 25 | /// 26 | /// 27 | public void ExtractData(List vertices, List indices, Model model) 28 | { 29 | var bones_ = new Matrix[model.Bones.Count]; 30 | model.CopyAbsoluteBoneTransformsTo(bones_); 31 | foreach (var mm in model.Meshes) 32 | { 33 | var xform = bones_[mm.ParentBone.Index]; 34 | foreach (var mmp in mm.MeshParts) 35 | { 36 | int offset = vertices.Count; 37 | var a = new Vector3[mmp.NumVertices]; 38 | mmp.VertexBuffer.GetData(mmp.VertexOffset * mmp.VertexBuffer.VertexDeclaration.VertexStride, 39 | a, 0, mmp.NumVertices, mmp.VertexBuffer.VertexDeclaration.VertexStride); 40 | for (int i = 0; i != a.Length; ++i) 41 | Vector3.Transform(ref a[i], ref xform, out a[i]); 42 | vertices.AddRange(a); 43 | 44 | if (mmp.IndexBuffer.IndexElementSize != IndexElementSize.SixteenBits) 45 | throw new Exception( 46 | String.Format("Model uses 32-bit indices, which are not supported.")); 47 | short[] s = new short[mmp.PrimitiveCount * 3]; 48 | mmp.IndexBuffer.GetData(mmp.StartIndex * 2, s, 0, mmp.PrimitiveCount * 3); 49 | var tvi = new TriangleVertexIndices[mmp.PrimitiveCount]; 50 | for (int i = 0; i != tvi.Length; ++i) 51 | { 52 | tvi[i].I0 = s[(i * 3) + 0] + offset; 53 | tvi[i].I1 = s[(i * 3) + 1] + offset; 54 | tvi[i].I2 = s[(i * 3) + 2] + offset; 55 | } 56 | indices.AddRange(tvi); 57 | } 58 | } 59 | } 60 | 61 | public override void Draw() 62 | { 63 | var camera = Demo.Camera; 64 | 65 | foreach (var mesh in model.Meshes) 66 | { 67 | foreach (BasicEffect effect in mesh.Effects) 68 | { 69 | effect.World = boneTransforms[mesh.ParentBone.Index]; 70 | effect.View = camera.View; 71 | effect.Projection = camera.Projection; 72 | 73 | effect.EnableDefaultLighting(); 74 | effect.PreferPerPixelLighting = true; 75 | } 76 | mesh.Draw(); 77 | } 78 | } 79 | 80 | private Matrix[] boneTransforms; 81 | 82 | public override void Build() 83 | { 84 | model = Demo.Content.Load("staticmesh"); 85 | boneTransforms = new Matrix[model.Bones.Count]; 86 | model.CopyAbsoluteBoneTransformsTo(boneTransforms); 87 | 88 | var indices = new List(); 89 | var vertices = new List(); 90 | 91 | ExtractData(vertices, indices, model); 92 | 93 | var jvertices = new List(vertices.Count); 94 | foreach(var vertex in vertices) jvertices.Add(Conversion.ToJitterVector(vertex)); 95 | 96 | var octree = new Octree(jvertices, indices); 97 | 98 | var tms = new TriangleMeshShape(octree); 99 | var body = new RigidBody(tms) 100 | { 101 | IsStatic = true, 102 | //body.EnableDebugDraw = true; 103 | Tag = BodyTag.DontDrawMe 104 | }; 105 | 106 | Demo.World.AddBody(body); 107 | 108 | AddCar(new JVector(-20, 20, 0)); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/Scenes/Wall.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Collision.Shapes; 2 | using Jitter.Dynamics; 3 | using Jitter.LinearMath; 4 | 5 | namespace JitterDemo.Scenes 6 | { 7 | internal class Wall : Scene 8 | { 9 | public Wall(JitterDemo demo) 10 | : base(demo) 11 | { 12 | } 13 | 14 | public override void Build() 15 | { 16 | AddGround(); 17 | 18 | for (int k = 0; k < 1; k++) 19 | { 20 | for (int i = 0; i < 20; i++) 21 | { 22 | for (int e = 0; e < 20; e++) 23 | { 24 | var body = new RigidBody(new BoxShape(2, 1, 1)) 25 | { 26 | Position = new JVector((e * 2.01f) + ((i % 2 == 0) ? 1f : 0.0f), 0.5f + (i * 1.0f), k * 5) 27 | }; 28 | Demo.World.AddBody(body); 29 | } 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /samples/JitterDemo/JitterDemo/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /source/Jitter.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.24720.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jitter", "Jitter\Jitter.csproj", "{AA03EF1A-94F7-4D30-AB14-2092863FF923}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jitter.Portable", "Jitter\Jitter.Portable.csproj", "{AA03EF1A-94F7-4D30-AB14-2092863FF92A}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {AA03EF1A-94F7-4D30-AB14-2092863FF923}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {AA03EF1A-94F7-4D30-AB14-2092863FF92A}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /source/Jitter/ArrayResourcePool.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Jitter 4 | { 5 | public class ArrayResourcePool 6 | { 7 | private readonly Stack stack = new Stack(); 8 | 9 | private readonly int arrayLength; 10 | 11 | public ArrayResourcePool(int arrayLength) 12 | { 13 | this.arrayLength = arrayLength; 14 | } 15 | 16 | public void ResetResourcePool() 17 | { 18 | lock (stack) { stack.Clear(); } 19 | } 20 | 21 | public int Count => stack.Count; 22 | 23 | public void GiveBack(T[] obj) 24 | { 25 | lock (stack) { stack.Push(obj); } 26 | } 27 | 28 | public T[] GetNew() 29 | { 30 | T[] freeObj; 31 | 32 | lock (stack) 33 | { 34 | if (stack.Count == 0) 35 | { 36 | freeObj = new T[arrayLength]; 37 | stack.Push(freeObj); 38 | } 39 | 40 | freeObj = stack.Pop(); 41 | } 42 | 43 | return freeObj; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /source/Jitter/Collision/CollisionIsland.cs: -------------------------------------------------------------------------------- 1 | using Jitter.DataStructures; 2 | using Jitter.Dynamics; 3 | using Jitter.Dynamics.Constraints; 4 | using System.Collections.Generic; 5 | 6 | namespace Jitter.Collision 7 | { 8 | public class CollisionIsland 9 | { 10 | internal IslandManager islandManager; 11 | internal HashSet bodies = new HashSet(); 12 | internal HashSet arbiter = new HashSet(); 13 | internal HashSet constraints = new HashSet(); 14 | 15 | public ReadOnlyHashset Bodies { get; } 16 | public ReadOnlyHashset Arbiter { get; } 17 | public ReadOnlyHashset Constraints { get; } 18 | 19 | public CollisionIsland() 20 | { 21 | Bodies = new ReadOnlyHashset(bodies); 22 | Arbiter = new ReadOnlyHashset(arbiter); 23 | Constraints = new ReadOnlyHashset(constraints); 24 | } 25 | 26 | public bool IsActive() 27 | { 28 | var enumerator = bodies.GetEnumerator(); 29 | enumerator.MoveNext(); 30 | 31 | return enumerator.Current?.isActive == true; 32 | } 33 | 34 | public void SetStatus(bool active) 35 | { 36 | foreach (var body in bodies) 37 | { 38 | body.IsActive = active; 39 | if (active && !body.IsActive) 40 | { 41 | body.inactiveTime = 0.0f; 42 | } 43 | } 44 | } 45 | 46 | internal void ClearLists() 47 | { 48 | arbiter.Clear(); 49 | bodies.Clear(); 50 | constraints.Clear(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /source/Jitter/Collision/DynamicTreeNode.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | 3 | namespace Jitter.Collision 4 | { 5 | public struct DynamicTreeNode 6 | { 7 | public JBBox AABB; 8 | 9 | public float MinorRandomExtension; 10 | 11 | public int Child1; 12 | public int Child2; 13 | 14 | public int LeafCount; 15 | public int ParentOrNext; 16 | public T UserData; 17 | 18 | public bool IsLeaf() 19 | { 20 | return Child1 == DynamicTree.NullNode; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /source/Jitter/Collision/IBroadphaseEntity.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | 3 | namespace Jitter.Collision 4 | { 5 | public interface IBroadphaseEntity 6 | { 7 | JBBox BoundingBox { get; } 8 | bool IsStaticOrInactive { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/BoxShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | 4 | namespace Jitter.Collision.Shapes 5 | { 6 | public class BoxShape : Shape 7 | { 8 | private JVector size = JVector.Zero; 9 | private JVector halfSize = JVector.Zero; 10 | 11 | public JVector Size 12 | { 13 | get => size; 14 | set 15 | { 16 | size = value; 17 | UpdateShape(); 18 | } 19 | } 20 | 21 | public BoxShape(JVector size) 22 | { 23 | this.size = size; 24 | UpdateShape(); 25 | } 26 | 27 | public BoxShape(float length, float height, float width) 28 | { 29 | size = new JVector( 30 | length, 31 | height, 32 | width); 33 | UpdateShape(); 34 | } 35 | 36 | public override void UpdateShape() 37 | { 38 | halfSize = size * 0.5f; 39 | base.UpdateShape(); 40 | } 41 | 42 | public override void GetBoundingBox(in JMatrix orientation, out JBBox box) 43 | { 44 | JMath.Absolute(orientation, out var abs); 45 | var max = JVector.Transform(halfSize, abs); 46 | 47 | box = new JBBox( 48 | JVector.Negate(max), 49 | max); 50 | } 51 | 52 | public override void CalculateMassInertia() 53 | { 54 | mass = size.X * size.Y * size.Z; 55 | 56 | inertia = JMatrix.FromDiagonal( 57 | m11: 1.0f / 12.0f * mass * ((size.Y * size.Y) + (size.Z * size.Z)), 58 | m22: 1.0f / 12.0f * mass * ((size.X * size.X) + (size.Z * size.Z)), 59 | m33: 1.0f / 12.0f * mass * ((size.X * size.X) + (size.Y * size.Y))); 60 | 61 | geomCen = JVector.Zero; 62 | } 63 | 64 | public override void SupportMapping(in JVector direction, out JVector result) 65 | { 66 | result = new JVector( 67 | Math.Sign(direction.X) * halfSize.X, 68 | Math.Sign(direction.Y) * halfSize.Y, 69 | Math.Sign(direction.Z) * halfSize.Z); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/CapsuleShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | 4 | namespace Jitter.Collision.Shapes 5 | { 6 | public class CapsuleShape : Shape 7 | { 8 | private float length; 9 | private float radius; 10 | 11 | public float Length 12 | { 13 | get => length; 14 | set 15 | { 16 | length = value; 17 | UpdateShape(); 18 | } 19 | } 20 | 21 | public float Radius 22 | { 23 | get => radius; 24 | set 25 | { 26 | radius = value; 27 | UpdateShape(); 28 | } 29 | } 30 | 31 | public CapsuleShape(float length, float radius) 32 | { 33 | this.length = length; 34 | this.radius = radius; 35 | UpdateShape(); 36 | } 37 | 38 | public override void CalculateMassInertia() 39 | { 40 | float massSphere = 3.0f / 4.0f * JMath.Pi * radius * radius * radius; 41 | float massCylinder = JMath.Pi * radius * radius * length; 42 | 43 | mass = massCylinder + massSphere; 44 | 45 | inertia = JMatrix.FromDiagonal( 46 | m11: (1.0f / 4.0f * massCylinder * radius * radius) + (1.0f / 12.0f * massCylinder * length * length) + (2.0f / 5.0f * massSphere * radius * radius) + (1.0f / 4.0f * length * length * massSphere), 47 | m22: (1.0f / 2.0f * massCylinder * radius * radius) + (2.0f / 5.0f * massSphere * radius * radius), 48 | m33: (1.0f / 4.0f * massCylinder * radius * radius) + (1.0f / 12.0f * massCylinder * length * length) + (2.0f / 5.0f * massSphere * radius * radius) + (1.0f / 4.0f * length * length * massSphere)); 49 | } 50 | 51 | public override void SupportMapping(in JVector direction, out JVector result) 52 | { 53 | float r = JMath.Sqrt((direction.X * direction.X) + (direction.Z * direction.Z)); 54 | 55 | if (Math.Abs(direction.Y) > 0.0f) 56 | { 57 | JVector.Normalize(in direction, out var dir); 58 | JVector.Multiply(in dir, radius, out result); 59 | 60 | result = new JVector( 61 | result.X, 62 | result.Y + Math.Sign(direction.Y) * 0.5f * length, 63 | result.Z); 64 | } 65 | else if (r > 0.0f) 66 | { 67 | result = new JVector( 68 | direction.X / r * radius, 69 | 0.0f, 70 | direction.Z / r * radius); 71 | } 72 | else 73 | { 74 | result = new JVector(); 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/ConeShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | 4 | namespace Jitter.Collision.Shapes 5 | { 6 | public class ConeShape : Shape 7 | { 8 | private float height; 9 | private float radius; 10 | private float sina; 11 | 12 | public float Height 13 | { 14 | get => height; 15 | set 16 | { 17 | height = value; 18 | UpdateShape(); 19 | } 20 | } 21 | 22 | public float Radius 23 | { 24 | get => radius; 25 | set 26 | { 27 | radius = value; 28 | UpdateShape(); 29 | } 30 | } 31 | 32 | public ConeShape(float height, float radius) 33 | { 34 | this.height = height; 35 | this.radius = radius; 36 | 37 | UpdateShape(); 38 | } 39 | 40 | public override void UpdateShape() 41 | { 42 | sina = radius / JMath.Sqrt((radius * radius) + (height * height)); 43 | base.UpdateShape(); 44 | } 45 | 46 | public override void CalculateMassInertia() 47 | { 48 | mass = 1.0f / 3.0f * JMath.Pi * radius * radius * height; 49 | 50 | inertia = JMatrix.FromDiagonal( 51 | m11: 3.0f / 80.0f * mass * ((radius * radius) + (4 * height * height)), 52 | m22: 3.0f / 10.0f * mass * radius * radius, 53 | m33: 3.0f / 80.0f * mass * ((radius * radius) + (4 * height * height))); 54 | 55 | geomCen = JVector.Zero; 56 | } 57 | 58 | public override void SupportMapping(in JVector direction, out JVector result) 59 | { 60 | float sigma = JMath.Sqrt((direction.X * direction.X) + (direction.Z * direction.Z)); 61 | 62 | if (direction.Y > direction.Length() * sina) 63 | { 64 | result = new JVector( 65 | 0.0f, 66 | 2.0f / 3.0f * height, 67 | 0.0f); 68 | } 69 | else if (sigma > 0.0f) 70 | { 71 | result = new JVector( 72 | radius * direction.X / sigma, 73 | -(1.0f / 3.0f) * height, 74 | radius * direction.Z / sigma); 75 | } 76 | else 77 | { 78 | result = new JVector( 79 | 0.0f, 80 | -(1.0f / 3.0f) * height, 81 | 0.0f); 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/ConvexHullShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter.Collision.Shapes 5 | { 6 | public class ConvexHullShape : Shape 7 | { 8 | private readonly List vertices; 9 | private JVector shifted; 10 | 11 | public ConvexHullShape(List vertices) 12 | { 13 | this.vertices = vertices; 14 | UpdateShape(); 15 | } 16 | 17 | public JVector Shift => -1 * shifted; 18 | 19 | public override void CalculateMassInertia() 20 | { 21 | mass = CalculateMassInertia(this, out shifted, out inertia); 22 | } 23 | 24 | public override void SupportMapping(in JVector direction, out JVector result) 25 | { 26 | float maxDotProduct = float.MinValue; 27 | int maxIndex = 0; 28 | float dotProduct; 29 | 30 | for (int i = 0; i < vertices.Count; i++) 31 | { 32 | dotProduct = JVector.Dot(vertices[i], direction); 33 | if (dotProduct > maxDotProduct) 34 | { 35 | maxDotProduct = dotProduct; 36 | maxIndex = i; 37 | } 38 | } 39 | 40 | result = vertices[maxIndex] - shifted; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/CylinderShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | 4 | namespace Jitter.Collision.Shapes 5 | { 6 | public class CylinderShape : Shape 7 | { 8 | private float height; 9 | private float radius; 10 | 11 | public float Height 12 | { 13 | get => height; set 14 | { 15 | height = value; 16 | UpdateShape(); 17 | } 18 | } 19 | 20 | public float Radius 21 | { 22 | get => radius; set 23 | { 24 | radius = value; 25 | UpdateShape(); 26 | } 27 | } 28 | 29 | public CylinderShape(float height, float radius) 30 | { 31 | this.height = height; 32 | this.radius = radius; 33 | UpdateShape(); 34 | } 35 | 36 | public override void CalculateMassInertia() 37 | { 38 | mass = JMath.Pi * radius * radius * height; 39 | 40 | inertia = JMatrix.FromDiagonal( 41 | m11: (1.0f / 4.0f * mass * radius * radius) + (1.0f / 12.0f * mass * height * height), 42 | m22: 1.0f / 2.0f * mass * radius * radius, 43 | m33: (1.0f / 4.0f * mass * radius * radius) + (1.0f / 12.0f * mass * height * height)); 44 | } 45 | 46 | public override void SupportMapping(in JVector direction, out JVector result) 47 | { 48 | float sigma = JMath.Sqrt((direction.X * direction.X) + (direction.Z * direction.Z)); 49 | 50 | if (sigma > 0.0f) 51 | { 52 | result = new JVector( 53 | direction.X / sigma * radius, 54 | Math.Sign(direction.Y) * height * 0.5f, 55 | direction.Z / sigma * radius); 56 | } 57 | else 58 | { 59 | result = new JVector( 60 | 0.0f, 61 | Math.Sign(direction.Y) * height * 0.5f, 62 | 0.0f); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/MinkowskiSumShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Jitter.Collision.Shapes 6 | { 7 | public class MinkowskiSumShape : Shape 8 | { 9 | private JVector shifted; 10 | private readonly List shapes = new List(); 11 | 12 | public MinkowskiSumShape(IEnumerable shapes) 13 | { 14 | AddShapes(shapes); 15 | } 16 | 17 | public void AddShapes(IEnumerable shapes) 18 | { 19 | foreach (var shape in shapes) 20 | { 21 | if (shape is Multishape) 22 | { 23 | throw new Exception("Multishapes not supported by MinkowskiSumShape."); 24 | } 25 | 26 | this.shapes.Add(shape); 27 | } 28 | 29 | UpdateShape(); 30 | } 31 | 32 | public void AddShape(Shape shape) 33 | { 34 | if (shape is Multishape) 35 | { 36 | throw new Exception("Multishapes not supported by MinkowskiSumShape."); 37 | } 38 | 39 | shapes.Add(shape); 40 | 41 | UpdateShape(); 42 | } 43 | 44 | public bool Remove(Shape shape) 45 | { 46 | if (shapes.Count == 1) 47 | { 48 | throw new Exception("There must be at least one shape."); 49 | } 50 | 51 | bool result = shapes.Remove(shape); 52 | UpdateShape(); 53 | return result; 54 | } 55 | 56 | public JVector Shift() 57 | { 58 | return -1 * shifted; 59 | } 60 | 61 | public override void CalculateMassInertia() 62 | { 63 | mass = CalculateMassInertia(this, out shifted, out inertia); 64 | } 65 | 66 | public override void SupportMapping(in JVector direction, out JVector result) 67 | { 68 | var temp2 = JVector.Zero; 69 | 70 | for (int i = 0; i < shapes.Count; i++) 71 | { 72 | shapes[i].SupportMapping(in direction, out var temp1); 73 | JVector.Add( temp1, temp2, out temp2); 74 | } 75 | 76 | JVector.Subtract(temp2, shifted, out result); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/Multishape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | 5 | namespace Jitter.Collision.Shapes 6 | { 7 | public abstract class Multishape : Shape 8 | { 9 | public abstract void SetCurrentShape(int index); 10 | 11 | public abstract int Prepare(in JBBox box); 12 | 13 | public abstract int Prepare(in JVector rayOrigin, in JVector rayDelta); 14 | 15 | protected abstract Multishape CreateWorkingClone(); 16 | 17 | internal bool isClone; 18 | 19 | public bool IsClone => isClone; 20 | 21 | private Stack workingCloneStack = new Stack(); 22 | 23 | public Multishape RequestWorkingClone() 24 | { 25 | Debug.Assert(workingCloneStack.Count < 10, "Unusual size of the workingCloneStack. Forgot to call ReturnWorkingClone?"); 26 | Debug.Assert(!isClone, "Can't clone clones! Something wrong here!"); 27 | 28 | Multishape multiShape; 29 | 30 | lock (workingCloneStack) 31 | { 32 | if (workingCloneStack.Count == 0) 33 | { 34 | multiShape = CreateWorkingClone(); 35 | multiShape.workingCloneStack = workingCloneStack; 36 | workingCloneStack.Push(multiShape); 37 | } 38 | multiShape = workingCloneStack.Pop(); 39 | multiShape.isClone = true; 40 | } 41 | 42 | return multiShape; 43 | } 44 | 45 | public override void UpdateShape() 46 | { 47 | lock (workingCloneStack) 48 | { 49 | workingCloneStack.Clear(); 50 | } 51 | 52 | base.UpdateShape(); 53 | } 54 | 55 | public void ReturnWorkingClone() 56 | { 57 | Debug.Assert(isClone, "Only clones can be returned!"); 58 | lock (workingCloneStack) { workingCloneStack.Push(this); } 59 | } 60 | 61 | public override void GetBoundingBox(in JMatrix orientation, out JBBox box) 62 | { 63 | var helpBox = JBBox.LargeBox; 64 | int length = Prepare(helpBox); 65 | 66 | box = JBBox.SmallBox; 67 | 68 | for (int i = 0; i < length; i++) 69 | { 70 | SetCurrentShape(i); 71 | base.GetBoundingBox(orientation, out helpBox); 72 | JBBox.CreateMerged(box, helpBox, out box); 73 | } 74 | } 75 | 76 | public override void MakeHull(List triangleList, int generationThreshold) 77 | { 78 | } 79 | 80 | public override void CalculateMassInertia() 81 | { 82 | geomCen = JVector.Zero; 83 | 84 | inertia = JMatrix.Identity; 85 | 86 | JVector.Subtract(boundingBox.Max, boundingBox.Min, out var size); 87 | 88 | mass = size.X * size.Y * size.Z; 89 | 90 | inertia = JMatrix.FromDiagonal( 91 | m11: 1.0f / 12.0f * mass * ((size.Y * size.Y) + (size.Z * size.Z)), 92 | m22: 1.0f / 12.0f * mass * ((size.X * size.X) + (size.Z * size.Z)), 93 | m33: 1.0f / 12.0f * mass * ((size.X * size.X) + (size.Y * size.Y))); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/SphereShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | 3 | namespace Jitter.Collision.Shapes 4 | { 5 | public class SphereShape : Shape 6 | { 7 | private float radius = 1.0f; 8 | 9 | public float Radius 10 | { 11 | get => radius; set 12 | { 13 | radius = value; 14 | UpdateShape(); 15 | } 16 | } 17 | 18 | public SphereShape(float radius) 19 | { 20 | this.radius = radius; 21 | UpdateShape(); 22 | } 23 | 24 | public override void SupportMapping(in JVector direction, out JVector result) 25 | { 26 | result = direction; 27 | result = JVector.Normalize(result); 28 | 29 | JVector.Multiply(result, radius, out result); 30 | } 31 | 32 | public override void GetBoundingBox(in JMatrix orientation, out JBBox box) 33 | { 34 | box = new JBBox( 35 | new JVector(-radius, -radius, -radius), 36 | new JVector(radius, radius, radius)); 37 | } 38 | 39 | public override void CalculateMassInertia() 40 | { 41 | mass = 4.0f / 3.0f * JMath.Pi * radius * radius * radius; 42 | 43 | inertia = JMatrix.FromDiagonal( 44 | m11: 0.4f * mass * radius * radius, 45 | m22: 0.4f * mass * radius * radius, 46 | m33: 0.4f * mass * radius * radius); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /source/Jitter/Collision/Shapes/TriangleMeshShape.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter.Collision.Shapes 5 | { 6 | public class TriangleMeshShape : Multishape 7 | { 8 | private readonly List potentialTriangles = new List(); 9 | private readonly Octree octree; 10 | 11 | public float SphericalExpansion { get; set; } = 0.05f; 12 | 13 | public TriangleMeshShape(Octree octree) 14 | { 15 | this.octree = octree; 16 | UpdateShape(); 17 | } 18 | 19 | internal TriangleMeshShape() { } 20 | 21 | protected override Multishape CreateWorkingClone() 22 | { 23 | var clone = new TriangleMeshShape(octree) 24 | { 25 | SphericalExpansion = SphericalExpansion 26 | }; 27 | return clone; 28 | } 29 | 30 | public override int Prepare(in JBBox box) 31 | { 32 | potentialTriangles.Clear(); 33 | 34 | var exp = new JBBox( 35 | new JVector(box.Min.X - SphericalExpansion, box.Min.Y - SphericalExpansion, box.Min.Z - SphericalExpansion), 36 | new JVector(box.Max.X + SphericalExpansion, box.Max.Y + SphericalExpansion, box.Max.Z + SphericalExpansion)); 37 | 38 | octree.GetTrianglesIntersectingtAABox(potentialTriangles, exp); 39 | 40 | return potentialTriangles.Count; 41 | } 42 | 43 | public override void MakeHull(List triangleList, int generationThreshold) 44 | { 45 | var large = JBBox.LargeBox; 46 | 47 | var indices = new List(); 48 | octree.GetTrianglesIntersectingtAABox(indices, large); 49 | 50 | for (int i = 0; i < indices.Count; i++) 51 | { 52 | triangleList.Add(octree.GetVertex(octree.GetTriangleVertexIndex(i).I0)); 53 | triangleList.Add(octree.GetVertex(octree.GetTriangleVertexIndex(i).I1)); 54 | triangleList.Add(octree.GetVertex(octree.GetTriangleVertexIndex(i).I2)); 55 | } 56 | } 57 | 58 | public override int Prepare(in JVector rayOrigin, in JVector rayDelta) 59 | { 60 | potentialTriangles.Clear(); 61 | 62 | JVector.Normalize(rayDelta, out var expDelta); 63 | expDelta = rayDelta + (expDelta * SphericalExpansion); 64 | 65 | octree.GetTrianglesIntersectingRay(potentialTriangles, rayOrigin, expDelta); 66 | 67 | return potentialTriangles.Count; 68 | } 69 | 70 | private readonly JVector[] vecs = new JVector[3]; 71 | 72 | public override void SupportMapping(in JVector direction, out JVector result) 73 | { 74 | JVector.Normalize(direction, out var exp); 75 | exp *= SphericalExpansion; 76 | 77 | float min = JVector.Dot(vecs[0], direction); 78 | int minIndex = 0; 79 | float dot = JVector.Dot(vecs[1], direction); 80 | if (dot > min) 81 | { 82 | min = dot; 83 | minIndex = 1; 84 | } 85 | dot = JVector.Dot(vecs[2], direction); 86 | if (dot > min) 87 | { 88 | minIndex = 2; 89 | } 90 | 91 | result = vecs[minIndex] + exp; 92 | } 93 | 94 | public override void GetBoundingBox(in JMatrix orientation, out JBBox box) 95 | { 96 | box = octree.rootNodeBox; 97 | 98 | box = new JBBox( 99 | new JVector(box.Min.X - SphericalExpansion, box.Min.Y - SphericalExpansion, box.Min.Z - SphericalExpansion), 100 | new JVector(box.Max.X + SphericalExpansion, box.Max.Y + SphericalExpansion, box.Max.Z + SphericalExpansion)); 101 | 102 | box = box.Transform(orientation); 103 | } 104 | 105 | public bool FlipNormals { get; set; } 106 | 107 | public override void SetCurrentShape(int index) 108 | { 109 | vecs[0] = octree.GetVertex(octree.tris[potentialTriangles[index]].I0); 110 | vecs[1] = octree.GetVertex(octree.tris[potentialTriangles[index]].I1); 111 | vecs[2] = octree.GetVertex(octree.tris[potentialTriangles[index]].I2); 112 | 113 | var sum = vecs[0]; 114 | JVector.Add(sum, vecs[1], out sum); 115 | JVector.Add(sum, vecs[2], out sum); 116 | JVector.Multiply(sum, 1.0f / 3.0f, out sum); 117 | 118 | geomCen = sum; 119 | 120 | JVector.Subtract(vecs[1], vecs[0], out sum); 121 | JVector.Subtract(vecs[2], vecs[0], out normal); 122 | JVector.Cross(sum, normal, out normal); 123 | 124 | if (FlipNormals) 125 | { 126 | normal = JVector.Negate(normal); 127 | } 128 | } 129 | 130 | private JVector normal = JVector.Up; 131 | 132 | public void CollisionNormal(out JVector normal) 133 | { 134 | normal = this.normal; 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /source/Jitter/Collision/TriangleVertexIndices.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace Jitter.Collision 6 | { 7 | public struct TriangleVertexIndices 8 | { 9 | public int I0; 10 | public int I1; 11 | public int I2; 12 | 13 | public TriangleVertexIndices(int i0, int i1, int i2) 14 | { 15 | I0 = i0; 16 | I1 = i1; 17 | I2 = i2; 18 | } 19 | 20 | public void Set(int i0, int i1, int i2) 21 | { 22 | I0 = i0; I1 = i1; I2 = i2; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /source/Jitter/DataStructures/ReadOnlyHashset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter.DataStructures 5 | { 6 | public class ReadOnlyHashset : IEnumerable, IEnumerable 7 | { 8 | private readonly HashSet hashset; 9 | 10 | public ReadOnlyHashset(HashSet hashset) { this.hashset = hashset; } 11 | 12 | public IEnumerator GetEnumerator() 13 | { 14 | return hashset.GetEnumerator(); 15 | } 16 | 17 | IEnumerator IEnumerable.GetEnumerator() 18 | { 19 | return hashset.GetEnumerator(); 20 | } 21 | 22 | public int Count => hashset.Count; 23 | 24 | public bool Contains(T item) { return hashset.Contains(item); } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/ArbiterKey.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter.Dynamics 5 | { 6 | public struct ArbiterKey 7 | { 8 | internal RigidBody body1, body2; 9 | 10 | public ArbiterKey(RigidBody body1, RigidBody body2) 11 | { 12 | this.body1 = body1; 13 | this.body2 = body2; 14 | } 15 | 16 | internal void SetBodies(RigidBody body1, RigidBody body2) 17 | { 18 | this.body1 = body1; 19 | this.body2 = body2; 20 | } 21 | 22 | public override bool Equals(object obj) 23 | { 24 | var other = (ArbiterKey)obj; 25 | return (other.body1.Equals(body1) && other.body2.Equals(body2)) 26 | || (other.body1.Equals(body2) && other.body2.Equals(body1)); 27 | } 28 | 29 | public override int GetHashCode() 30 | { 31 | return body1.GetHashCode() + body2.GetHashCode(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/ArbiterKeyComparer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter.Dynamics 5 | { 6 | 7 | internal class ArbiterKeyComparer : IEqualityComparer 8 | { 9 | public bool Equals(ArbiterKey x, ArbiterKey y) 10 | { 11 | return (x.body1.Equals(y.body1) && x.body2.Equals(y.body2)) 12 | || (x.body1.Equals(y.body2) && x.body2.Equals(y.body1)); 13 | } 14 | 15 | public int GetHashCode(ArbiterKey obj) 16 | { 17 | return obj.body1.GetHashCode() + obj.body2.GetHashCode(); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/ArbiterMap.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter.Dynamics 5 | { 6 | public class ArbiterMap : IEnumerable 7 | { 8 | private readonly Dictionary dictionary = 9 | new Dictionary(2048, arbiterKeyComparer); 10 | 11 | private ArbiterKey lookUpKey; 12 | private static readonly ArbiterKeyComparer arbiterKeyComparer = new ArbiterKeyComparer(); 13 | 14 | public ArbiterMap() 15 | { 16 | lookUpKey = new ArbiterKey(null, null); 17 | } 18 | 19 | public bool LookUpArbiter(RigidBody body1, RigidBody body2, out Arbiter arbiter) 20 | { 21 | lookUpKey.SetBodies(body1, body2); 22 | return dictionary.TryGetValue(lookUpKey, out arbiter); 23 | } 24 | 25 | public Dictionary.ValueCollection Arbiters => dictionary.Values; 26 | 27 | internal void Add(ArbiterKey key, Arbiter arbiter) 28 | { 29 | dictionary.Add(key, arbiter); 30 | } 31 | 32 | internal void Clear() 33 | { 34 | dictionary.Clear(); 35 | } 36 | 37 | internal void Remove(Arbiter arbiter) 38 | { 39 | lookUpKey.SetBodies(arbiter.body1, arbiter.body2); 40 | dictionary.Remove(lookUpKey); 41 | } 42 | 43 | public bool ContainsArbiter(RigidBody body1, RigidBody body2) 44 | { 45 | lookUpKey.SetBodies(body1, body2); 46 | return dictionary.ContainsKey(lookUpKey); 47 | } 48 | 49 | public IEnumerator GetEnumerator() 50 | { 51 | return dictionary.Values.GetEnumerator(); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Constraint.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Jitter.Dynamics.Constraints 5 | { 6 | public abstract class Constraint : IConstraint, IDebugDrawable, IComparable 7 | { 8 | internal RigidBody body1; 9 | internal RigidBody body2; 10 | 11 | public RigidBody Body1 => body1; 12 | 13 | public RigidBody Body2 => body2; 14 | 15 | private static int instanceCount; 16 | private readonly int instance; 17 | 18 | public Constraint(RigidBody body1, RigidBody body2) 19 | { 20 | this.body1 = body1; 21 | this.body2 = body2; 22 | 23 | instance = Interlocked.Increment(ref instanceCount); 24 | 25 | body1?.Update(); 26 | body2?.Update(); 27 | } 28 | 29 | public abstract void PrepareForIteration(float timestep); 30 | 31 | public abstract void Iterate(); 32 | 33 | public int CompareTo(Constraint other) 34 | { 35 | if (other.instance < instance) 36 | { 37 | return -1; 38 | } 39 | else if (other.instance > instance) 40 | { 41 | return 1; 42 | } 43 | else 44 | { 45 | return 0; 46 | } 47 | } 48 | 49 | public virtual void DebugDraw(IDebugDrawer drawer) 50 | { 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Constraints/FixedAngle.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | 4 | namespace Jitter.Dynamics.Constraints 5 | { 6 | public class FixedAngle : Constraint 7 | { 8 | private JVector accumulatedImpulse; 9 | 10 | private JMatrix initialOrientation1; 11 | private JMatrix initialOrientation2; 12 | 13 | public FixedAngle(RigidBody body1, RigidBody body2) : base(body1, body2) 14 | { 15 | initialOrientation1 = body1.orientation; 16 | initialOrientation2 = body2.orientation; 17 | } 18 | 19 | public JVector AppliedImpulse => accumulatedImpulse; 20 | 21 | public JMatrix InitialOrientationBody1 22 | { 23 | get => initialOrientation1; 24 | set => initialOrientation1 = value; 25 | } 26 | 27 | public JMatrix InitialOrientationBody2 28 | { 29 | get => initialOrientation2; 30 | set => initialOrientation2 = value; 31 | } 32 | 33 | public float Softness { get; set; } 34 | 35 | public float BiasFactor { get; set; } = 0.05f; 36 | 37 | private JMatrix effectiveMass; 38 | private JVector bias; 39 | private float softnessOverDt; 40 | 41 | public override void PrepareForIteration(float timestep) 42 | { 43 | effectiveMass = body1.invInertiaWorld + body2.invInertiaWorld; 44 | 45 | softnessOverDt = Softness / timestep; 46 | 47 | effectiveMass = JMatrix.FromDiagonal( 48 | m11: effectiveMass.M11 + softnessOverDt, 49 | m22: effectiveMass.M22 + softnessOverDt, 50 | m33: effectiveMass.M33 + softnessOverDt); 51 | 52 | JMatrix.Inverse(effectiveMass, out effectiveMass); 53 | 54 | JMatrix.Multiply(initialOrientation1, initialOrientation2, out var orientationDifference); 55 | JMatrix.Transpose(orientationDifference, out orientationDifference); 56 | 57 | var q = orientationDifference * body2.invOrientation * body1.orientation; 58 | JVector axis; 59 | 60 | float x = q.M32 - q.M23; 61 | float y = q.M13 - q.M31; 62 | float z = q.M21 - q.M12; 63 | 64 | float r = JMath.Sqrt((x * x) + (y * y) + (z * z)); 65 | float t = q.M11 + q.M22 + q.M33; 66 | 67 | float angle = (float)Math.Atan2(r, t - 1); 68 | axis = new JVector(x, y, z) * angle; 69 | 70 | if (r != 0.0f) 71 | { 72 | axis = axis * (1.0f / r); 73 | } 74 | 75 | bias = axis * BiasFactor * (-1.0f / timestep); 76 | 77 | if (!body1.IsStatic) 78 | { 79 | body1.angularVelocity += JVector.Transform(accumulatedImpulse, body1.invInertiaWorld); 80 | } 81 | 82 | if (!body2.IsStatic) 83 | { 84 | body2.angularVelocity += JVector.Transform(-1.0f * accumulatedImpulse, body2.invInertiaWorld); 85 | } 86 | } 87 | 88 | public override void Iterate() 89 | { 90 | var jv = body1.angularVelocity - body2.angularVelocity; 91 | 92 | var softnessVector = accumulatedImpulse * softnessOverDt; 93 | 94 | var lambda = -1.0f * JVector.Transform(jv + bias + softnessVector, effectiveMass); 95 | 96 | accumulatedImpulse += lambda; 97 | 98 | if (!body1.IsStatic) 99 | { 100 | body1.angularVelocity += JVector.Transform(lambda, body1.invInertiaWorld); 101 | } 102 | 103 | if (!body2.IsStatic) 104 | { 105 | body2.angularVelocity += JVector.Transform(-1.0f * lambda, body2.invInertiaWorld); 106 | } 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Constraints/PointOnLine.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | 3 | namespace Jitter.Dynamics.Constraints 4 | { 5 | public class PointOnLine : Constraint 6 | { 7 | private JVector lineNormal; 8 | private JVector localAnchor1; 9 | private JVector localAnchor2; 10 | private JVector r1; 11 | private JVector r2; 12 | 13 | public PointOnLine(RigidBody body1, RigidBody body2, JVector lineStartPointBody1, JVector pointBody2) : base(body1, body2) 14 | { 15 | JVector.Subtract(lineStartPointBody1, body1.position, out localAnchor1); 16 | JVector.Subtract(pointBody2, body2.position, out localAnchor2); 17 | 18 | JVector.Transform(localAnchor1, body1.invOrientation, out localAnchor1); 19 | JVector.Transform(localAnchor2, body2.invOrientation, out localAnchor2); 20 | 21 | lineNormal = JVector.Normalize(lineStartPointBody1 - pointBody2); 22 | } 23 | 24 | public float AppliedImpulse { get; private set; } 25 | 26 | public float Softness { get; set; } 27 | 28 | public float BiasFactor { get; set; } = 0.5f; 29 | 30 | private float effectiveMass; 31 | private float bias; 32 | private float softnessOverDt; 33 | private readonly JVector[] jacobian = new JVector[4]; 34 | 35 | public override void PrepareForIteration(float timestep) 36 | { 37 | JVector.Transform(localAnchor1, body1.orientation, out r1); 38 | JVector.Transform(localAnchor2, body2.orientation, out r2); 39 | 40 | JVector.Add(body1.position, r1, out var p1); 41 | JVector.Add(body2.position, r2, out var p2); 42 | JVector.Subtract(p2, p1, out _); 43 | 44 | var l = JVector.Transform(lineNormal, body1.orientation); 45 | l = JVector.Normalize(l); 46 | 47 | var t = (p1 - p2) % l; 48 | if (t.LengthSquared() != 0.0f) 49 | { 50 | t = JVector.Normalize(t); 51 | } 52 | 53 | t %= l; 54 | 55 | jacobian[0] = t; 56 | jacobian[1] = (r1 + p2 - p1) % t; 57 | jacobian[2] = -1.0f * t; 58 | jacobian[3] = -1.0f * r2 % t; 59 | 60 | effectiveMass = body1.inverseMass + body2.inverseMass 61 | + (JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1]) 62 | + (JVector.Transform(jacobian[3], body2.invInertiaWorld) * jacobian[3]); 63 | 64 | softnessOverDt = Softness / timestep; 65 | effectiveMass += softnessOverDt; 66 | 67 | if (effectiveMass != 0) 68 | { 69 | effectiveMass = 1.0f / effectiveMass; 70 | } 71 | 72 | bias = -(l % (p2 - p1)).Length() * BiasFactor * (1.0f / timestep); 73 | 74 | if (!body1.isStatic) 75 | { 76 | body1.linearVelocity += body1.inverseMass * AppliedImpulse * jacobian[0]; 77 | body1.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[1], body1.invInertiaWorld); 78 | } 79 | 80 | if (!body2.isStatic) 81 | { 82 | body2.linearVelocity += body2.inverseMass * AppliedImpulse * jacobian[2]; 83 | body2.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[3], body2.invInertiaWorld); 84 | } 85 | } 86 | 87 | public override void Iterate() 88 | { 89 | float jv = 90 | (body1.linearVelocity * jacobian[0]) 91 | + (body1.angularVelocity * jacobian[1]) 92 | + (body2.linearVelocity * jacobian[2]) 93 | + (body2.angularVelocity * jacobian[3]); 94 | 95 | float softnessScalar = AppliedImpulse * softnessOverDt; 96 | 97 | float lambda = -effectiveMass * (jv + bias + softnessScalar); 98 | 99 | AppliedImpulse += lambda; 100 | 101 | if (!body1.isStatic) 102 | { 103 | body1.linearVelocity += body1.inverseMass * lambda * jacobian[0]; 104 | body1.angularVelocity += JVector.Transform(lambda * jacobian[1], body1.invInertiaWorld); 105 | } 106 | 107 | if (!body2.isStatic) 108 | { 109 | body2.linearVelocity += body2.inverseMass * lambda * jacobian[2]; 110 | body2.angularVelocity += JVector.Transform(lambda * jacobian[3], body2.invInertiaWorld); 111 | } 112 | } 113 | 114 | public override void DebugDraw(IDebugDrawer drawer) 115 | { 116 | drawer.DrawLine(body1.position + r1, 117 | body1.position + r1 + (JVector.Transform(lineNormal, body1.orientation) * 100.0f)); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Constraints/PointOnPoint.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | 3 | namespace Jitter.Dynamics.Constraints 4 | { 5 | public class PointOnPoint : Constraint 6 | { 7 | private readonly JVector localAnchor1; 8 | private readonly JVector localAnchor2; 9 | private JVector r1; 10 | private JVector r2; 11 | 12 | public PointOnPoint(RigidBody body1, RigidBody body2, JVector anchor) : base(body1, body2) 13 | { 14 | JVector.Subtract(anchor, body1.position, out localAnchor1); 15 | JVector.Subtract(anchor, body2.position, out localAnchor2); 16 | 17 | JVector.Transform(localAnchor1, body1.invOrientation, out localAnchor1); 18 | JVector.Transform(localAnchor2, body2.invOrientation, out localAnchor2); 19 | } 20 | 21 | public float AppliedImpulse { get; private set; } 22 | 23 | public float Softness { get; set; } = 0.01f; 24 | 25 | public float BiasFactor { get; set; } = 0.05f; 26 | 27 | private float effectiveMass; 28 | private float bias; 29 | private float softnessOverDt; 30 | private readonly JVector[] jacobian = new JVector[4]; 31 | 32 | public override void PrepareForIteration(float timestep) 33 | { 34 | JVector.Transform(localAnchor1, body1.orientation, out r1); 35 | JVector.Transform(localAnchor2, body2.orientation, out r2); 36 | 37 | JVector.Add(body1.position, r1, out var p1); 38 | JVector.Add(body2.position, r2, out var p2); 39 | 40 | JVector.Subtract(p2, p1, out var dp); 41 | 42 | float deltaLength = dp.Length(); 43 | 44 | var n = p2 - p1; 45 | if (n.LengthSquared() != 0.0f) 46 | { 47 | n = JVector.Normalize(n); 48 | } 49 | 50 | jacobian[0] = -1.0f * n; 51 | jacobian[1] = -1.0f * (r1 % n); 52 | jacobian[2] = 1.0f * n; 53 | jacobian[3] = r2 % n; 54 | 55 | effectiveMass = body1.inverseMass + body2.inverseMass 56 | + (JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1]) 57 | + (JVector.Transform(jacobian[3], body2.invInertiaWorld) * jacobian[3]); 58 | 59 | softnessOverDt = Softness / timestep; 60 | effectiveMass += softnessOverDt; 61 | 62 | effectiveMass = 1.0f / effectiveMass; 63 | 64 | bias = deltaLength * BiasFactor * (1.0f / timestep); 65 | 66 | if (!body1.isStatic) 67 | { 68 | body1.linearVelocity += body1.inverseMass * AppliedImpulse * jacobian[0]; 69 | body1.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[1], body1.invInertiaWorld); 70 | } 71 | 72 | if (!body2.isStatic) 73 | { 74 | body2.linearVelocity += body2.inverseMass * AppliedImpulse * jacobian[2]; 75 | body2.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[3], body2.invInertiaWorld); 76 | } 77 | } 78 | 79 | public override void Iterate() 80 | { 81 | float jv = 82 | (body1.linearVelocity * jacobian[0]) 83 | + (body1.angularVelocity * jacobian[1]) 84 | + (body2.linearVelocity * jacobian[2]) 85 | + (body2.angularVelocity * jacobian[3]); 86 | 87 | float softnessScalar = AppliedImpulse * softnessOverDt; 88 | 89 | float lambda = -effectiveMass * (jv + bias + softnessScalar); 90 | 91 | AppliedImpulse += lambda; 92 | 93 | if (!body1.isStatic) 94 | { 95 | body1.linearVelocity += body1.inverseMass * lambda * jacobian[0]; 96 | body1.angularVelocity += JVector.Transform(lambda * jacobian[1], body1.invInertiaWorld); 97 | } 98 | 99 | if (!body2.isStatic) 100 | { 101 | body2.linearVelocity += body2.inverseMass * lambda * jacobian[2]; 102 | body2.angularVelocity += JVector.Transform(lambda * jacobian[3], body2.invInertiaWorld); 103 | } 104 | } 105 | 106 | public override void DebugDraw(IDebugDrawer drawer) 107 | { 108 | drawer.DrawLine(body1.position, body1.position + r1); 109 | drawer.DrawLine(body2.position, body2.position + r2); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Constraints/SingleBody/FixedAngle.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | 4 | namespace Jitter.Dynamics.Constraints.SingleBody 5 | { 6 | public class FixedAngle : Constraint 7 | { 8 | private JMatrix orientation; 9 | private JVector accumulatedImpulse; 10 | 11 | public FixedAngle(RigidBody body1) : base(body1, null) 12 | { 13 | orientation = body1.orientation; 14 | } 15 | 16 | public float Softness { get; set; } 17 | 18 | public float BiasFactor { get; set; } = 0.05f; 19 | 20 | public JMatrix InitialOrientation { get => orientation; set => orientation = value; } 21 | 22 | private JMatrix effectiveMass; 23 | private JVector bias; 24 | private float softnessOverDt; 25 | 26 | public override void PrepareForIteration(float timestep) 27 | { 28 | effectiveMass = body1.invInertiaWorld; 29 | 30 | softnessOverDt = Softness / timestep; 31 | 32 | effectiveMass = JMatrix.FromDiagonal( 33 | m11: effectiveMass.M11 + softnessOverDt, 34 | m22: effectiveMass.M22 + softnessOverDt, 35 | m33: effectiveMass.M33 + softnessOverDt); 36 | 37 | JMatrix.Inverse(effectiveMass, out effectiveMass); 38 | 39 | var q = JMatrix.Transpose(orientation) * body1.orientation; 40 | 41 | float x = q.M32 - q.M23; 42 | float y = q.M13 - q.M31; 43 | float z = q.M21 - q.M12; 44 | 45 | float r = JMath.Sqrt((x * x) + (y * y) + (z * z)); 46 | float t = q.M11 + q.M22 + q.M33; 47 | 48 | float angle = (float)Math.Atan2(r, t - 1); 49 | var axis = new JVector(x, y, z) * angle; 50 | 51 | if (r != 0.0f) 52 | { 53 | axis *= 1.0f / r; 54 | } 55 | 56 | bias = axis * BiasFactor * (-1.0f / timestep); 57 | 58 | if (!body1.IsStatic) 59 | { 60 | body1.angularVelocity += JVector.Transform(accumulatedImpulse, body1.invInertiaWorld); 61 | } 62 | } 63 | 64 | public override void Iterate() 65 | { 66 | var jv = body1.angularVelocity; 67 | 68 | var softnessVector = accumulatedImpulse * softnessOverDt; 69 | 70 | var lambda = -1.0f * JVector.Transform(jv + bias + softnessVector, effectiveMass); 71 | 72 | accumulatedImpulse += lambda; 73 | 74 | if (!body1.IsStatic) 75 | { 76 | body1.angularVelocity += JVector.Transform(lambda, body1.invInertiaWorld); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Constraints/SingleBody/PointOnLine.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | using System; 3 | 4 | namespace Jitter.Dynamics.Constraints.SingleBody 5 | { 6 | public class PointOnLine : Constraint 7 | { 8 | private readonly JVector localAnchor1; 9 | private JVector r1; 10 | 11 | private JVector lineNormal = JVector.Right; 12 | private JVector anchor; 13 | 14 | public PointOnLine(RigidBody body, JVector localAnchor, JVector lineDirection) : base(body, null) 15 | { 16 | if (lineDirection.LengthSquared() == 0.0f) 17 | { 18 | throw new ArgumentException("Line direction can't be zero", nameof(lineDirection)); 19 | } 20 | 21 | localAnchor1 = localAnchor; 22 | anchor = body.position + JVector.Transform(localAnchor, body.orientation); 23 | 24 | lineNormal = lineDirection; 25 | lineNormal = JVector.Normalize(lineNormal); 26 | } 27 | 28 | public JVector Anchor { get => anchor; set => anchor = value; } 29 | 30 | public JVector Axis 31 | { 32 | get => lineNormal; 33 | set 34 | { 35 | lineNormal = value; 36 | lineNormal = JVector.Normalize(lineNormal); 37 | } 38 | } 39 | 40 | public float Softness { get; set; } 41 | 42 | public float BiasFactor { get; set; } = 0.5f; 43 | 44 | private float effectiveMass; 45 | private float accumulatedImpulse; 46 | private float bias; 47 | private float softnessOverDt; 48 | private readonly JVector[] jacobian = new JVector[2]; 49 | 50 | public override void PrepareForIteration(float timestep) 51 | { 52 | JVector.Transform(localAnchor1, body1.orientation, out r1); 53 | 54 | JVector.Add(body1.position, r1, out var p1); 55 | 56 | JVector.Subtract(p1, anchor, out var dp); 57 | 58 | var l = lineNormal; 59 | 60 | var t = (p1 - anchor) % l; 61 | if (t.LengthSquared() != 0.0f) 62 | { 63 | t = JVector.Normalize(t); 64 | } 65 | 66 | t %= l; 67 | 68 | jacobian[0] = t; 69 | jacobian[1] = r1 % t; 70 | 71 | effectiveMass = body1.inverseMass 72 | + (JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1]); 73 | 74 | softnessOverDt = Softness / timestep; 75 | effectiveMass += softnessOverDt; 76 | 77 | if (effectiveMass != 0) 78 | { 79 | effectiveMass = 1.0f / effectiveMass; 80 | } 81 | 82 | bias = -(l % (p1 - anchor)).Length() * BiasFactor * (1.0f / timestep); 83 | 84 | if (!body1.isStatic) 85 | { 86 | body1.linearVelocity += body1.inverseMass * accumulatedImpulse * jacobian[0]; 87 | body1.angularVelocity += JVector.Transform(accumulatedImpulse * jacobian[1], body1.invInertiaWorld); 88 | } 89 | } 90 | 91 | public override void Iterate() 92 | { 93 | float jv = 94 | (body1.linearVelocity * jacobian[0]) 95 | + (body1.angularVelocity * jacobian[1]); 96 | 97 | float softnessScalar = accumulatedImpulse * softnessOverDt; 98 | 99 | float lambda = -effectiveMass * (jv + bias + softnessScalar); 100 | 101 | accumulatedImpulse += lambda; 102 | 103 | if (!body1.isStatic) 104 | { 105 | body1.linearVelocity += body1.inverseMass * lambda * jacobian[0]; 106 | body1.angularVelocity += JVector.Transform(lambda * jacobian[1], body1.invInertiaWorld); 107 | } 108 | } 109 | 110 | public override void DebugDraw(IDebugDrawer drawer) 111 | { 112 | drawer.DrawLine(anchor - (lineNormal * 50.0f), anchor + (lineNormal * 50.0f)); 113 | drawer.DrawLine(body1.position, body1.position + r1); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Constraints/SingleBody/PointOnPoint.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | 3 | namespace Jitter.Dynamics.Constraints.SingleBody 4 | { 5 | public class PointOnPoint : Constraint 6 | { 7 | private JVector localAnchor1; 8 | private JVector anchor; 9 | 10 | private JVector r1; 11 | 12 | public PointOnPoint(RigidBody body, JVector localAnchor) : base(body, null) 13 | { 14 | localAnchor1 = localAnchor; 15 | 16 | anchor = body.position + JVector.Transform(localAnchor, body.orientation); 17 | } 18 | 19 | public float AppliedImpulse { get; private set; } 20 | 21 | public float Softness { get; set; } = 0.01f; 22 | 23 | public JVector Anchor { get => anchor; set => anchor = value; } 24 | 25 | public float BiasFactor { get; set; } = 0.1f; 26 | 27 | private float effectiveMass; 28 | private float bias; 29 | private float softnessOverDt; 30 | private readonly JVector[] jacobian = new JVector[2]; 31 | 32 | public override void PrepareForIteration(float timestep) 33 | { 34 | JVector.Transform(localAnchor1, body1.orientation, out r1); 35 | JVector.Add( body1.position, r1, out var p1); 36 | JVector.Subtract(p1, anchor, out var dp); 37 | 38 | float deltaLength = dp.Length(); 39 | 40 | var n = anchor - p1; 41 | if (n.LengthSquared() != 0.0f) 42 | { 43 | n = JVector.Normalize(n); 44 | } 45 | 46 | jacobian[0] = -1.0f * n; 47 | jacobian[1] = -1.0f * (r1 % n); 48 | 49 | effectiveMass = body1.inverseMass + (JVector.Transform(jacobian[1], body1.invInertiaWorld) * jacobian[1]); 50 | 51 | softnessOverDt = Softness / timestep; 52 | effectiveMass += softnessOverDt; 53 | 54 | effectiveMass = 1.0f / effectiveMass; 55 | 56 | bias = deltaLength * BiasFactor * (1.0f / timestep); 57 | 58 | if (!body1.isStatic) 59 | { 60 | body1.linearVelocity += body1.inverseMass * AppliedImpulse * jacobian[0]; 61 | body1.angularVelocity += JVector.Transform(AppliedImpulse * jacobian[1], body1.invInertiaWorld); 62 | } 63 | } 64 | 65 | public override void Iterate() 66 | { 67 | float jv = 68 | (body1.linearVelocity * jacobian[0]) 69 | + (body1.angularVelocity * jacobian[1]); 70 | 71 | float softnessScalar = AppliedImpulse * softnessOverDt; 72 | 73 | float lambda = -effectiveMass * (jv + bias + softnessScalar); 74 | 75 | AppliedImpulse += lambda; 76 | 77 | if (!body1.isStatic) 78 | { 79 | body1.linearVelocity += body1.inverseMass * lambda * jacobian[0]; 80 | body1.angularVelocity += JVector.Transform(lambda * jacobian[1], body1.invInertiaWorld); 81 | } 82 | } 83 | 84 | public override void DebugDraw(IDebugDrawer drawer) 85 | { 86 | drawer.DrawPoint(anchor); 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/ContactSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Jitter.Dynamics 2 | { 3 | public class ContactSettings 4 | { 5 | public enum MaterialCoefficientMixingType { TakeMaximum, TakeMinimum, UseAverage } 6 | 7 | internal float maximumBias = 10.0f; 8 | internal float bias = 0.25f; 9 | internal float minVelocity = 0.001f; 10 | internal float allowedPenetration = 0.01f; 11 | internal float breakThreshold = 0.01f; 12 | 13 | internal MaterialCoefficientMixingType materialMode = MaterialCoefficientMixingType.UseAverage; 14 | 15 | public float MaximumBias { get => maximumBias; set => maximumBias = value; } 16 | 17 | public float BiasFactor { get => bias; set => bias = value; } 18 | 19 | public float MinimumVelocity { get => minVelocity; set => minVelocity = value; } 20 | 21 | public float AllowedPenetration { get => allowedPenetration; set => allowedPenetration = value; } 22 | 23 | public float BreakThreshold { get => breakThreshold; set => breakThreshold = value; } 24 | 25 | public MaterialCoefficientMixingType MaterialCoefficientMixing { get => materialMode; set => materialMode = value; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/IConstraint.cs: -------------------------------------------------------------------------------- 1 | namespace Jitter.Dynamics 2 | { 3 | public interface IConstraint 4 | { 5 | 6 | RigidBody Body1 { get; } 7 | 8 | RigidBody Body2 { get; } 9 | 10 | /// 11 | /// Called once before iteration starts. 12 | /// 13 | /// The simulation timestep 14 | void PrepareForIteration(float timestep); 15 | 16 | /// 17 | /// Iteratively solve this constraint. 18 | /// 19 | void Iterate(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Joints/HingeJoint.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Dynamics.Constraints; 2 | using Jitter.LinearMath; 3 | 4 | namespace Jitter.Dynamics.Joints 5 | { 6 | public class HingeJoint : Joint 7 | { 8 | private readonly PointOnPoint[] worldPointConstraint; 9 | 10 | public PointOnPoint PointConstraint1 => worldPointConstraint[0]; 11 | public PointOnPoint PointConstraint2 => worldPointConstraint[1]; 12 | 13 | public HingeJoint(World world, RigidBody body1, RigidBody body2, JVector position, JVector hingeAxis) : base(world) 14 | { 15 | worldPointConstraint = new PointOnPoint[2]; 16 | 17 | hingeAxis *= 0.5f; 18 | 19 | var pos1 = position; JVector.Add(pos1, hingeAxis, out pos1); 20 | var pos2 = position; JVector.Subtract(pos2, hingeAxis, out pos2); 21 | 22 | worldPointConstraint[0] = new PointOnPoint(body1, body2, pos1); 23 | worldPointConstraint[1] = new PointOnPoint(body1, body2, pos2); 24 | } 25 | 26 | public PointOnPoint PointOnPointConstraint1 => worldPointConstraint[0]; 27 | 28 | public PointOnPoint PointOnPointConstraint2 => worldPointConstraint[1]; 29 | 30 | public float AppliedImpulse => worldPointConstraint[0].AppliedImpulse + worldPointConstraint[1].AppliedImpulse; 31 | 32 | public override void Activate() 33 | { 34 | World.AddConstraint(worldPointConstraint[0]); 35 | World.AddConstraint(worldPointConstraint[1]); 36 | } 37 | 38 | public override void Deactivate() 39 | { 40 | World.RemoveConstraint(worldPointConstraint[0]); 41 | World.RemoveConstraint(worldPointConstraint[1]); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Joints/Joint.cs: -------------------------------------------------------------------------------- 1 | namespace Jitter.Dynamics.Joints 2 | { 3 | public abstract class Joint 4 | { 5 | public World World { get; } 6 | 7 | public Joint(World world) 8 | { 9 | World = world; 10 | } 11 | 12 | public abstract void Activate(); 13 | 14 | public abstract void Deactivate(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Joints/LimitedHingeJoint.cs: -------------------------------------------------------------------------------- 1 | using Jitter.Dynamics.Constraints; 2 | using Jitter.LinearMath; 3 | 4 | namespace Jitter.Dynamics.Joints 5 | { 6 | public class LimitedHingeJoint : Joint 7 | { 8 | private readonly PointOnPoint[] worldPointConstraint; 9 | 10 | public PointOnPoint PointConstraint1 => worldPointConstraint[0]; 11 | public PointOnPoint PointConstraint2 => worldPointConstraint[1]; 12 | 13 | public PointPointDistance DistanceConstraint { get; } 14 | 15 | public LimitedHingeJoint(World world, RigidBody body1, RigidBody body2, JVector position, JVector hingeAxis, float hingeFwdAngle, float hingeBckAngle) : base(world) 16 | { 17 | worldPointConstraint = new PointOnPoint[2]; 18 | 19 | hingeAxis *= 0.5f; 20 | 21 | var pos1 = position; 22 | JVector.Add(pos1, hingeAxis, out pos1); 23 | var pos2 = position; 24 | JVector.Subtract(pos2, hingeAxis, out pos2); 25 | 26 | worldPointConstraint[0] = new PointOnPoint(body1, body2, pos1); 27 | worldPointConstraint[1] = new PointOnPoint(body1, body2, pos2); 28 | 29 | hingeAxis = JVector.Normalize(hingeAxis); 30 | 31 | var perpDir = JVector.Up; 32 | 33 | if (JVector.Dot(perpDir, hingeAxis) > 0.1f) 34 | { 35 | perpDir = JVector.Right; 36 | } 37 | 38 | var sideAxis = JVector.Cross(hingeAxis, perpDir); 39 | perpDir = JVector.Cross(sideAxis, hingeAxis); 40 | perpDir = JVector.Normalize(perpDir); 41 | 42 | float len = 10.0f * 3; 43 | 44 | var hingeRelAnchorPos0 = perpDir * len; 45 | 46 | float angleToMiddle = 0.5f * (hingeFwdAngle - hingeBckAngle); 47 | var hingeRelAnchorPos1 = JVector.Transform(hingeRelAnchorPos0, JMatrix.CreateFromAxisAngle(hingeAxis, -angleToMiddle / 360.0f * 2.0f * JMath.Pi)); 48 | 49 | float hingeHalfAngle = 0.5f * (hingeFwdAngle + hingeBckAngle); 50 | float allowedDistance = len * 2.0f * (float)System.Math.Sin(hingeHalfAngle * 0.5f / 360.0f * 2.0f * JMath.Pi); 51 | 52 | var hingePos = body1.Position; 53 | var relPos0c = hingePos + hingeRelAnchorPos0; 54 | var relPos1c = hingePos + hingeRelAnchorPos1; 55 | 56 | DistanceConstraint = new PointPointDistance(body1, body2, relPos0c, relPos1c) 57 | { 58 | Distance = allowedDistance, 59 | Behavior = PointPointDistance.DistanceBehavior.LimitMaximumDistance 60 | }; 61 | } 62 | 63 | public override void Activate() 64 | { 65 | World.AddConstraint(worldPointConstraint[0]); 66 | World.AddConstraint(worldPointConstraint[1]); 67 | World.AddConstraint(DistanceConstraint); 68 | } 69 | 70 | public override void Deactivate() 71 | { 72 | World.RemoveConstraint(worldPointConstraint[0]); 73 | World.RemoveConstraint(worldPointConstraint[1]); 74 | World.RemoveConstraint(DistanceConstraint); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Joints/PrismaticJoint.cs: -------------------------------------------------------------------------------- 1 |  2 | using Jitter.Dynamics.Constraints; 3 | using Jitter.LinearMath; 4 | 5 | namespace Jitter.Dynamics.Joints 6 | { 7 | public class PrismaticJoint : Joint 8 | { 9 | public PointPointDistance MaximumDistanceConstraint { get; } 10 | public PointPointDistance MinimumDistanceConstraint { get; } 11 | 12 | public FixedAngle FixedAngleConstraint { get; } 13 | public PointOnLine PointOnLineConstraint { get; } 14 | 15 | public PrismaticJoint(World world, RigidBody body1, RigidBody body2) : base(world) 16 | { 17 | FixedAngleConstraint = new FixedAngle(body1, body2); 18 | PointOnLineConstraint = new PointOnLine(body1, body2, body1.position, body2.position); 19 | } 20 | 21 | public PrismaticJoint(World world, RigidBody body1, RigidBody body2, float minimumDistance, float maximumDistance) 22 | : base(world) 23 | { 24 | FixedAngleConstraint = new FixedAngle(body1, body2); 25 | PointOnLineConstraint = new PointOnLine(body1, body2, body1.position, body2.position); 26 | 27 | MinimumDistanceConstraint = new PointPointDistance(body1, body2, body1.position, body2.position) 28 | { 29 | Behavior = PointPointDistance.DistanceBehavior.LimitMinimumDistance, 30 | Distance = minimumDistance 31 | }; 32 | 33 | MaximumDistanceConstraint = new PointPointDistance(body1, body2, body1.position, body2.position) 34 | { 35 | Behavior = PointPointDistance.DistanceBehavior.LimitMaximumDistance, 36 | Distance = maximumDistance 37 | }; 38 | } 39 | 40 | public PrismaticJoint(World world, RigidBody body1, RigidBody body2, JVector pointOnBody1, JVector pointOnBody2) 41 | : base(world) 42 | { 43 | FixedAngleConstraint = new FixedAngle(body1, body2); 44 | PointOnLineConstraint = new PointOnLine(body1, body2, pointOnBody1, pointOnBody2); 45 | } 46 | 47 | public PrismaticJoint(World world, RigidBody body1, RigidBody body2, JVector pointOnBody1, JVector pointOnBody2, float maximumDistance, float minimumDistance) 48 | : base(world) 49 | { 50 | FixedAngleConstraint = new FixedAngle(body1, body2); 51 | PointOnLineConstraint = new PointOnLine(body1, body2, pointOnBody1, pointOnBody2); 52 | } 53 | 54 | public override void Activate() 55 | { 56 | if (MaximumDistanceConstraint != null) 57 | { 58 | World.AddConstraint(MaximumDistanceConstraint); 59 | } 60 | 61 | if (MinimumDistanceConstraint != null) 62 | { 63 | World.AddConstraint(MinimumDistanceConstraint); 64 | } 65 | 66 | World.AddConstraint(FixedAngleConstraint); 67 | World.AddConstraint(PointOnLineConstraint); 68 | } 69 | 70 | public override void Deactivate() 71 | { 72 | if (MaximumDistanceConstraint != null) 73 | { 74 | World.RemoveConstraint(MaximumDistanceConstraint); 75 | } 76 | 77 | if (MinimumDistanceConstraint != null) 78 | { 79 | World.RemoveConstraint(MinimumDistanceConstraint); 80 | } 81 | 82 | World.RemoveConstraint(FixedAngleConstraint); 83 | World.RemoveConstraint(PointOnLineConstraint); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /source/Jitter/Dynamics/Material.cs: -------------------------------------------------------------------------------- 1 | namespace Jitter.Dynamics 2 | { 3 | public class Material 4 | { 5 | internal float kineticFriction = 0.3f; 6 | internal float staticFriction = 0.6f; 7 | internal float restitution; 8 | 9 | public float Restitution 10 | { 11 | get => restitution; 12 | set => restitution = value; 13 | } 14 | 15 | public float StaticFriction 16 | { 17 | get => staticFriction; 18 | set => staticFriction = value; 19 | } 20 | 21 | public float KineticFriction 22 | { 23 | get => kineticFriction; 24 | set => kineticFriction = value; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/Jitter/IDebugDraw.cs: -------------------------------------------------------------------------------- 1 | using Jitter.LinearMath; 2 | 3 | namespace Jitter 4 | { 5 | public interface IDebugDrawable 6 | { 7 | void DebugDraw(IDebugDrawer drawer); 8 | } 9 | 10 | public interface IDebugDrawer 11 | { 12 | void DrawLine(JVector start, JVector end); 13 | void DrawPoint(JVector pos); 14 | void DrawTriangle(JVector pos1, JVector pos2, JVector pos3); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /source/Jitter/Jitter.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | netstandard2.0 4 | JitterPhysics 5 | Copyright (c) 2019 Thorben Linneweber, Matthew Leibowitz, Flurin Feuerstein 6 | 0.2.0.0 7 | Thorben Linneweber, Matthew Leibowitz, Flurin Feuerstein 8 | 9 | Realtime physics engine for .NET 10 | Jitter Physics is a fast and lightweight physics engine written in C# 11 | LICENSE.md 12 | true 13 | https://github.com/fxredeemer/jitterphysics 14 | Jitter, Physics, 3D 15 | true 16 | 17 | 18 | 19 | 20 | 21 | 22 | True 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /source/Jitter/LinearMath/JConvexHull.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter.LinearMath 5 | { 6 | public static class JConvexHull 7 | { 8 | public enum Approximation 9 | { 10 | Level1 = 6, 11 | Level2 = 7, 12 | Level3 = 8, 13 | Level4 = 9, 14 | Level5 = 10, 15 | Level6 = 11, 16 | Level7 = 12, 17 | Level8 = 13, 18 | Level9 = 15, 19 | Level10 = 20, 20 | Level15 = 25, 21 | Level20 = 30 22 | } 23 | 24 | public static int[] Build(List pointCloud, Approximation factor) 25 | { 26 | var allIndices = new List(); 27 | 28 | int steps = (int)factor; 29 | 30 | for (int thetaIndex = 0; thetaIndex < steps; thetaIndex++) 31 | { 32 | float theta = JMath.Pi / (steps - 1) * thetaIndex; 33 | float sinTheta = (float)Math.Sin(theta); 34 | float cosTheta = (float)Math.Cos(theta); 35 | 36 | for (int phiIndex = 0; phiIndex < steps; phiIndex++) 37 | { 38 | float phi = (2.0f * JMath.Pi / (steps - 0) * phiIndex) - JMath.Pi; 39 | float sinPhi = (float)Math.Sin(phi); 40 | float cosPhi = (float)Math.Cos(phi); 41 | 42 | var dir = new JVector(sinTheta * cosPhi, cosTheta, sinTheta * sinPhi); 43 | 44 | int index = FindExtremePoint(pointCloud, dir); 45 | allIndices.Add(index); 46 | } 47 | } 48 | 49 | allIndices.Sort(); 50 | 51 | for (int i = 1; i < allIndices.Count; i++) 52 | { 53 | if (allIndices[i - 1] == allIndices[i]) 54 | { 55 | allIndices.RemoveAt(i - 1); i--; 56 | } 57 | } 58 | 59 | return allIndices.ToArray(); 60 | } 61 | 62 | private static int FindExtremePoint(List points, in JVector dir) 63 | { 64 | int index = 0; 65 | float current = float.MinValue; 66 | 67 | JVector point; 68 | float value; 69 | 70 | for (int i = 1; i < points.Count; i++) 71 | { 72 | point = points[i]; 73 | 74 | value = JVector.Dot(point, dir); 75 | if (value > current) 76 | { 77 | current = value; index = i; 78 | } 79 | } 80 | 81 | return index; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /source/Jitter/LinearMath/JMath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Jitter.LinearMath 4 | { 5 | public sealed class JMath 6 | { 7 | public const float Pi = 3.1415926535f; 8 | public const float PiOver2 = 1.570796326794f; 9 | public const float Epsilon = 1.192092896e-012f; 10 | 11 | public static float Sqrt(float number) 12 | { 13 | return (float)Math.Sqrt(number); 14 | } 15 | 16 | public static float Cos(float number) 17 | { 18 | return (float)Math.Cos(number); 19 | } 20 | 21 | public static float Sin(float number) 22 | { 23 | return (float)Math.Sin(number); 24 | } 25 | 26 | public static float Max(float val1, float val2) 27 | { 28 | return (val1 > val2) ? val1 : val2; 29 | } 30 | 31 | public static float Min(float val1, float val2) 32 | { 33 | return (val1 < val2) ? val1 : val2; 34 | } 35 | 36 | public static float Max(float val1, float val2, float val3) 37 | { 38 | float max12 = (val1 > val2) ? val1 : val2; 39 | return (max12 > val3) ? max12 : val3; 40 | } 41 | 42 | public static float Clamp(float value, float min, float max) 43 | { 44 | value = (value > max) ? max : value; 45 | value = (value < min) ? min : value; 46 | return value; 47 | } 48 | 49 | public static JMatrix Absolute(in JMatrix matrix) 50 | { 51 | Absolute(matrix, out var absolute); 52 | return absolute; 53 | } 54 | 55 | public static void Absolute(in JMatrix matrix, out JMatrix result) 56 | { 57 | result = new JMatrix( 58 | m11: Math.Abs(matrix.M11), 59 | m12: Math.Abs(matrix.M12), 60 | m13: Math.Abs(matrix.M13), 61 | m21: Math.Abs(matrix.M21), 62 | m22: Math.Abs(matrix.M22), 63 | m23: Math.Abs(matrix.M23), 64 | m31: Math.Abs(matrix.M31), 65 | m32: Math.Abs(matrix.M32), 66 | m33: Math.Abs(matrix.M33)); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /source/Jitter/ResourcePool.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Jitter 5 | { 6 | public class ResourcePool 7 | { 8 | private readonly Stack stack = new Stack(); 9 | 10 | public void ResetResourcePool() 11 | { 12 | lock (stack) 13 | { 14 | stack.Clear(); 15 | } 16 | } 17 | 18 | public int Count => stack.Count; 19 | 20 | public void GiveBack(T obj) 21 | { 22 | lock (stack) 23 | { 24 | stack.Push(obj); 25 | } 26 | } 27 | 28 | public T GetNew() 29 | { 30 | T freeObj; 31 | 32 | lock (stack) 33 | { 34 | if (stack.Count == 0) 35 | { 36 | freeObj = Activator.CreateInstance(); 37 | stack.Push(freeObj); 38 | } 39 | 40 | freeObj = stack.Pop(); 41 | } 42 | 43 | return freeObj; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /source/Jitter/ThreadManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading; 4 | 5 | #if PORTABLE 6 | using System.Threading.Tasks; 7 | using Thread = System.Threading.Tasks.Task; 8 | #endif 9 | 10 | namespace Jitter 11 | { 12 | public sealed class ThreadManager 13 | { 14 | public const int ThreadsPerProcessor = 1; 15 | 16 | private ManualResetEvent waitHandleA, waitHandleB; 17 | private ManualResetEvent currentWaitHandle; 18 | private readonly List> tasks = new List>(); 19 | private readonly List parameters = new List(); 20 | 21 | private Thread[] threads; 22 | private int currentTaskIndex, waitingThreadCount; 23 | 24 | internal int threadCount; 25 | 26 | public int ThreadCount { private set => threadCount = value; get => threadCount; } 27 | 28 | private static ThreadManager instance; 29 | 30 | public static ThreadManager Instance 31 | { 32 | get 33 | { 34 | if (instance == null) 35 | { 36 | instance = new ThreadManager(); 37 | instance.Initialize(); 38 | } 39 | 40 | return instance; 41 | } 42 | } 43 | 44 | private ThreadManager() { } 45 | 46 | private void Initialize() 47 | { 48 | threadCount = Environment.ProcessorCount * ThreadsPerProcessor; 49 | 50 | threads = new Thread[threadCount]; 51 | waitHandleA = new ManualResetEvent(false); 52 | waitHandleB = new ManualResetEvent(false); 53 | 54 | currentWaitHandle = waitHandleA; 55 | 56 | var initWaitHandle = new AutoResetEvent(false); 57 | 58 | for (int i = 1; i < threads.Length; i++) 59 | { 60 | threads[i] = NewThread(() => 61 | { 62 | initWaitHandle.Set(); 63 | ThreadProc(); 64 | }); 65 | 66 | threads[i].Start(); 67 | initWaitHandle.WaitOne(); 68 | } 69 | } 70 | 71 | public void Execute() 72 | { 73 | currentTaskIndex = 0; 74 | waitingThreadCount = 0; 75 | 76 | currentWaitHandle.Set(); 77 | PumpTasks(); 78 | 79 | while (waitingThreadCount < threads.Length - 1) 80 | { 81 | ThreadSleep(0); 82 | } 83 | 84 | currentWaitHandle.Reset(); 85 | currentWaitHandle = (currentWaitHandle == waitHandleA) ? waitHandleB : waitHandleA; 86 | 87 | tasks.Clear(); 88 | parameters.Clear(); 89 | } 90 | 91 | public void AddTask(Action task, object param) 92 | { 93 | tasks.Add(task); 94 | parameters.Add(param); 95 | } 96 | 97 | private void ThreadProc() 98 | { 99 | while (true) 100 | { 101 | Interlocked.Increment(ref waitingThreadCount); 102 | waitHandleA.WaitOne(); 103 | PumpTasks(); 104 | 105 | Interlocked.Increment(ref waitingThreadCount); 106 | waitHandleB.WaitOne(); 107 | PumpTasks(); 108 | } 109 | } 110 | 111 | private void PumpTasks() 112 | { 113 | int count = tasks.Count; 114 | 115 | while (currentTaskIndex < count) 116 | { 117 | int taskIndex = currentTaskIndex; 118 | 119 | if (taskIndex == Interlocked.CompareExchange(ref currentTaskIndex, taskIndex + 1, taskIndex) 120 | && taskIndex < count) 121 | { 122 | tasks[taskIndex](parameters[taskIndex]); 123 | } 124 | } 125 | } 126 | 127 | private static void ThreadSleep(int dueTime) 128 | { 129 | #if PORTABLE 130 | Task.Delay(dueTime).Wait(); 131 | #else 132 | Thread.Sleep(dueTime); 133 | #endif 134 | } 135 | 136 | #if PORTABLE 137 | private delegate void ThreadStart(); 138 | #endif 139 | 140 | private static Thread NewThread(ThreadStart action) 141 | { 142 | #if PORTABLE 143 | return new Thread(action.Invoke, TaskCreationOptions.LongRunning); 144 | #else 145 | return new Thread(action) { IsBackground = true }; 146 | #endif 147 | } 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /tools/hacdtest/ReadMe.txt: -------------------------------------------------------------------------------- 1 | This project contains source code and a sample program to perform 2 | Hierarchical approximate convex decomposition (HACD) based on the 3 | work of Khaled Mamou 4 | 5 | Released: July 7, 2011 6 | 7 | This source has been modified by John W. Ratcliff to add the 8 | following features: 9 | 10 | (1) Removed ALL of the STL code 11 | (2) Provided a stripped down implementation of the STL map/set 12 | based on the EASTL written by Paul Pedriana 13 | (3) Provides a single compatibility header file called 14 | 'PxSimpleTypes.h' that allows you to capture all memory 15 | allocations define all data types. 16 | (4) Provides a simple wrapper API that is easy to use. 17 | 18 | The source is provided with a solution and project file 19 | for Visual Studio 2008. 20 | 21 | Most all of the code should compile on any platform with 22 | relatively few changes required. 23 | 24 | The source code for HACD is located in: 25 | 26 | .\HACD\include : Internal private header files 27 | .\HACD\public : Public interface and wrapper API 28 | .\HACD\src : Implementation sources 29 | 30 | To run the sample; from the command line just type: 31 | 32 | TestHACD hornbug.obj -c 500 -m 5 -merge 5 33 | 34 | You can experiment with different concavity levels. 35 | 36 | The test application will load the Wavefront OBJ sample file 37 | 'hornbug.obj' and output the convex hulls as a Wavefront OBJ file 38 | called 'ConvexDecomposition.obj' which you can view in any mesh viewer. 39 | 40 | Send questions/comments to John W. Ratcliff at 41 | 42 | mailto:jratcliffscarab@gmail.com 43 | -------------------------------------------------------------------------------- /tools/hacdtest/TestHACD.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flurin137/jitterphysics/61b68656d72bbd41c46a959a0d66ccd48d55f0ae/tools/hacdtest/TestHACD.exe --------------------------------------------------------------------------------