├── .DS_Store
├── .gitignore
├── Box2DNet.sln
├── LICENSE
├── README.md
├── deps
└── cimgui
│ ├── linux-x64
│ └── cimgui.so
│ ├── osx-x64
│ └── cimgui.dylib
│ ├── win-x64
│ └── cimgui.dll
│ └── win-x86
│ └── cimgui.dll
├── doc
└── install-vulkan.md
├── examples
├── .DS_Store
├── HelloWorld
│ ├── .DS_Store
│ ├── HelloWorld.csproj
│ └── Program.cs
└── Testbed
│ ├── Framework
│ ├── ContactState.cs
│ ├── DebugViewBase.cs
│ ├── DebugViewXNA.cs
│ ├── GameSettings.cs
│ ├── KeyboardManager.cs
│ ├── PrimitiveBatch.cs
│ ├── Rand.cs
│ ├── Settings.cs
│ ├── Test.cs
│ ├── TestEntries.cs
│ └── TestEntry.cs
│ ├── Game1.cs
│ ├── Program.cs
│ ├── Shaders
│ ├── GLSL
│ │ ├── imgui-frag.glsl
│ │ └── imgui-vertex.glsl
│ ├── HLSL
│ │ ├── imgui-frag.hlsl
│ │ ├── imgui-frag.hlsl.bytes
│ │ ├── imgui-vertex.hlsl
│ │ └── imgui-vertex.hlsl.bytes
│ ├── Metal
│ │ ├── imgui-frag.metal
│ │ ├── imgui-frag.metallib
│ │ ├── imgui-vertex.metal
│ │ └── imgui-vertex.metallib
│ └── SPIR-V
│ │ ├── generate-spirv.bat
│ │ ├── imgui-frag.glsl
│ │ ├── imgui-frag.spv
│ │ ├── imgui-vertex.glsl
│ │ └── imgui-vertex.spv
│ ├── Testbed.csproj
│ └── Tests
│ ├── Bridge.cs
│ ├── Car.cs
│ └── SimpleTest.cs
└── src
├── .DS_Store
└── Box2DNet
├── .DS_Store
├── Box2DNet.csproj
├── Box2DXDebug.cs
├── Collision
├── BroadPhase.cs
├── Collision.CollideCircle.cs
├── Collision.CollideEdge.cs
├── Collision.CollidePoly.cs
├── Collision.Distance.cs
├── Collision.TimeOfImpact.cs
├── Collision.cs
├── PairManager.cs
└── Shapes
│ ├── CircleShape.cs
│ ├── EdgeShape.cs
│ ├── PolygonShape.cs
│ └── Shape.cs
├── Common
├── Mar33.cs
├── Mat22.cs
├── Math.cs
├── Settings.cs
├── Sweep.cs
├── Transform.cs
├── Utils.cs
├── Vec2.cs
├── Vec3.cs
└── XForm.cs
└── Dynamics
├── Body.cs
├── ContactManager.cs
├── Contacts
├── CircleContact.cs
├── Contact.cs
├── ContactSolver.cs
├── EdgeAndCircleContact.cs
├── NullContact.cs
├── PolyAndCircleContact.cs
├── PolyAndEdgeContact.cs
└── PolyContact.cs
├── Controllers
├── BuoyancyController.cs
├── ConstantAccelController.cs
├── ConstantForceController.cs
├── Controller.cs
├── GravityController.cs
└── TensorDampingController.cs
├── Fixture.cs
├── Island.cs
├── Joints
├── DistanceJoint.cs
├── GearJoint.cs
├── Joint.cs
├── LineJoint.cs
├── MouseJoint.cs
├── PrismaticJoint.cs
├── PulleyJoint.cs
└── RevoluteJoint.cs
├── World.cs
└── WorldCallbacks.cs
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/.DS_Store
--------------------------------------------------------------------------------
/.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 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
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 | *.VC.db
84 | *.VC.VC.opendb
85 |
86 | # Visual Studio profiler
87 | *.psess
88 | *.vsp
89 | *.vspx
90 | *.sap
91 |
92 | # TFS 2012 Local Workspace
93 | $tf/
94 |
95 | # Guidance Automation Toolkit
96 | *.gpState
97 |
98 | # ReSharper is a .NET coding add-in
99 | _ReSharper*/
100 | *.[Rr]e[Ss]harper
101 | *.DotSettings.user
102 |
103 | # JustCode is a .NET coding add-in
104 | .JustCode
105 |
106 | # TeamCity is a build add-in
107 | _TeamCity*
108 |
109 | # DotCover is a Code Coverage Tool
110 | *.dotCover
111 |
112 | # NCrunch
113 | _NCrunch_*
114 | .*crunch*.local.xml
115 | nCrunchTemp_*
116 |
117 | # MightyMoose
118 | *.mm.*
119 | AutoTest.Net/
120 |
121 | # Web workbench (sass)
122 | .sass-cache/
123 |
124 | # Installshield output folder
125 | [Ee]xpress/
126 |
127 | # DocProject is a documentation generator add-in
128 | DocProject/buildhelp/
129 | DocProject/Help/*.HxT
130 | DocProject/Help/*.HxC
131 | DocProject/Help/*.hhc
132 | DocProject/Help/*.hhk
133 | DocProject/Help/*.hhp
134 | DocProject/Help/Html2
135 | DocProject/Help/html
136 |
137 | # Click-Once directory
138 | publish/
139 |
140 | # Publish Web Output
141 | *.[Pp]ublish.xml
142 | *.azurePubxml
143 | # TODO: Comment the next line if you want to checkin your web deploy settings
144 | # but database connection strings (with potential passwords) will be unencrypted
145 | *.pubxml
146 | *.publishproj
147 |
148 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
149 | # checkin your Azure Web App publish settings, but sensitive information contained
150 | # in these scripts will be unencrypted
151 | PublishScripts/
152 |
153 | # NuGet Packages
154 | *.nupkg
155 | # The packages folder can be ignored because of Package Restore
156 | **/packages/*
157 | # except build/, which is used as an MSBuild target.
158 | !**/packages/build/
159 | # Uncomment if necessary however generally it will be regenerated when needed
160 | #!**/packages/repositories.config
161 | # NuGet v3's project.json files produces more ignoreable files
162 | *.nuget.props
163 | *.nuget.targets
164 |
165 | # Microsoft Azure Build Output
166 | csx/
167 | *.build.csdef
168 |
169 | # Microsoft Azure Emulator
170 | ecf/
171 | rcf/
172 |
173 | # Windows Store app package directories and files
174 | AppPackages/
175 | BundleArtifacts/
176 | Package.StoreAssociation.xml
177 | _pkginfo.txt
178 |
179 | # Visual Studio cache files
180 | # files ending in .cache can be ignored
181 | *.[Cc]ache
182 | # but keep track of directories ending in .cache
183 | !*.[Cc]ache/
184 |
185 | # Others
186 | ClientBin/
187 | ~$*
188 | *~
189 | *.dbmdl
190 | *.dbproj.schemaview
191 | *.pfx
192 | *.publishsettings
193 | node_modules/
194 | orleans.codegen.cs
195 |
196 | # Since there are multiple workflows, uncomment next line to ignore bower_components
197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
198 | #bower_components/
199 |
200 | # RIA/Silverlight projects
201 | Generated_Code/
202 |
203 | # Backup & report files from converting an old project file
204 | # to a newer Visual Studio version. Backup files are not needed,
205 | # because we have git ;-)
206 | _UpgradeReport_Files/
207 | Backup*/
208 | UpgradeLog*.XML
209 | UpgradeLog*.htm
210 |
211 | # SQL Server files
212 | *.mdf
213 | *.ldf
214 |
215 | # Business Intelligence projects
216 | *.rdl.data
217 | *.bim.layout
218 | *.bim_*.settings
219 |
220 | # Microsoft Fakes
221 | FakesAssemblies/
222 |
223 | # GhostDoc plugin setting file
224 | *.GhostDoc.xml
225 |
226 | # Node.js Tools for Visual Studio
227 | .ntvs_analysis.dat
228 |
229 | # Visual Studio 6 build log
230 | *.plg
231 |
232 | # Visual Studio 6 workspace options file
233 | *.opt
234 |
235 | # Visual Studio LightSwitch build output
236 | **/*.HTMLClient/GeneratedArtifacts
237 | **/*.DesktopClient/GeneratedArtifacts
238 | **/*.DesktopClient/ModelManifest.xml
239 | **/*.Server/GeneratedArtifacts
240 | **/*.Server/ModelManifest.xml
241 | _Pvt_Extensions
242 |
243 | # Paket dependency manager
244 | .paket/paket.exe
245 | paket-files/
246 |
247 | # FAKE - F# Make
248 | .fake/
249 |
250 | # JetBrains Rider
251 | .idea/
252 | *.sln.iml
253 |
254 | .DS_Store
255 |
--------------------------------------------------------------------------------
/Box2DNet.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26124.0
5 | MinimumVisualStudioVersion = 15.0.26124.0
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04EF37E0-B0CD-4A85-ACAA-53B7C0E8B5C5}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Box2DNet", "src\Box2DNet\Box2DNet.csproj", "{C20791D0-F341-44A8-B6C1-50049A29B158}"
9 | EndProject
10 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{BB66E02A-0B91-4D4C-80F6-D0686B124992}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloWorld", "examples\HelloWorld\HelloWorld.csproj", "{DD567358-C46A-4354-B7E9-7479EF9B6236}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestBed", "examples\TestBed\TestBed.csproj", "{46D4436A-8750-4F01-8790-4028AF2D1127}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Debug|x64 = Debug|x64
20 | Debug|x86 = Debug|x86
21 | Release|Any CPU = Release|Any CPU
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
29 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Debug|x64.ActiveCfg = Debug|Any CPU
32 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Debug|x64.Build.0 = Debug|Any CPU
33 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Debug|x86.ActiveCfg = Debug|Any CPU
34 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Debug|x86.Build.0 = Debug|Any CPU
35 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Release|Any CPU.Build.0 = Release|Any CPU
37 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Release|x64.ActiveCfg = Release|Any CPU
38 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Release|x64.Build.0 = Release|Any CPU
39 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Release|x86.ActiveCfg = Release|Any CPU
40 | {C20791D0-F341-44A8-B6C1-50049A29B158}.Release|x86.Build.0 = Release|Any CPU
41 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Debug|x64.ActiveCfg = Debug|Any CPU
44 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Debug|x64.Build.0 = Debug|Any CPU
45 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Debug|x86.ActiveCfg = Debug|Any CPU
46 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Debug|x86.Build.0 = Debug|Any CPU
47 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Release|Any CPU.ActiveCfg = Release|Any CPU
48 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Release|Any CPU.Build.0 = Release|Any CPU
49 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Release|x64.ActiveCfg = Release|Any CPU
50 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Release|x64.Build.0 = Release|Any CPU
51 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Release|x86.ActiveCfg = Release|Any CPU
52 | {DD567358-C46A-4354-B7E9-7479EF9B6236}.Release|x86.Build.0 = Release|Any CPU
53 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
54 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Debug|Any CPU.Build.0 = Debug|Any CPU
55 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Debug|x64.ActiveCfg = Debug|Any CPU
56 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Debug|x64.Build.0 = Debug|Any CPU
57 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Debug|x86.ActiveCfg = Debug|Any CPU
58 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Debug|x86.Build.0 = Debug|Any CPU
59 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Release|x64.ActiveCfg = Release|Any CPU
62 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Release|x64.Build.0 = Release|Any CPU
63 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Release|x86.ActiveCfg = Release|Any CPU
64 | {46D4436A-8750-4F01-8790-4028AF2D1127}.Release|x86.Build.0 = Release|Any CPU
65 | EndGlobalSection
66 | GlobalSection(NestedProjects) = preSolution
67 | {C20791D0-F341-44A8-B6C1-50049A29B158} = {04EF37E0-B0CD-4A85-ACAA-53B7C0E8B5C5}
68 | {DD567358-C46A-4354-B7E9-7479EF9B6236} = {BB66E02A-0B91-4D4C-80F6-D0686B124992}
69 | {46D4436A-8750-4F01-8790-4028AF2D1127} = {BB66E02A-0B91-4D4C-80F6-D0686B124992}
70 | EndGlobalSection
71 | EndGlobal
72 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 zhu yu
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Box2DNet
2 | Fork from http://code.google.com/p/box2dx/
3 |
4 | Box2DNet is a C# port of Box2D - Erin Catto's 2D Physics Engine. You can find original C++ version on www.box2d.org
5 |
--------------------------------------------------------------------------------
/deps/cimgui/linux-x64/cimgui.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/deps/cimgui/linux-x64/cimgui.so
--------------------------------------------------------------------------------
/deps/cimgui/osx-x64/cimgui.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/deps/cimgui/osx-x64/cimgui.dylib
--------------------------------------------------------------------------------
/deps/cimgui/win-x64/cimgui.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/deps/cimgui/win-x64/cimgui.dll
--------------------------------------------------------------------------------
/deps/cimgui/win-x86/cimgui.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/deps/cimgui/win-x86/cimgui.dll
--------------------------------------------------------------------------------
/doc/install-vulkan.md:
--------------------------------------------------------------------------------
1 | 1. Download [vulkansdk-macos-1.0.xx.0.tar.gz](https://vulkan.lunarg.com/sdk/home#sdk/downloadConfirm/latest/mac/vulkan-sdk.tar.gz)
2 | 2. `tar -xzf vulkan-sdk.tar.gz`
3 | 3. set environment variables(in `~/.profile` file):
4 | ```bash
5 | export VK_SDK=~/vulkansdk-macos-1.1.85.0/macOS
6 | export PATH=$VK_SDK/bin:$PATH
7 | export DYLD_LIBRARY_PATH=$VK_SDK/lib:$DYLD_LIBRARY_PATH
8 | export VK_LAYER_PATH=$VK_SDK/etc/vulkan/explicit_layers.d
9 | export VK_ICD_FILENAMES=$VK_SDK/etc/vulkan/icd.d/MoltenVK_icd.json
10 | ```
--------------------------------------------------------------------------------
/examples/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/.DS_Store
--------------------------------------------------------------------------------
/examples/HelloWorld/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/HelloWorld/.DS_Store
--------------------------------------------------------------------------------
/examples/HelloWorld/HelloWorld.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Exe
9 | netcoreapp2.1
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/HelloWorld/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 | using Box2DNet.Dynamics;
4 | using Box2DNet.Dynamics;
5 | using Box2DNet.Collision;
6 | using Box2DNet.Common;
7 |
8 | namespace HelloWorld
9 | {
10 | class Program
11 | {
12 | // This is a simple example of building and running a simulation
13 | // using Box2DNet. Here we create a large ground box and a small dynamic
14 | // box.
15 | static void Main(string[] args)
16 | {
17 | // Define the size of the world. Simulation will still work
18 | // if bodies reach the end of the world, but it will be slower.
19 | AABB worldAABB = new AABB
20 | {
21 | UpperBound = new Vector2(100, 100),
22 | LowerBound = new Vector2(-100, -100)
23 | };
24 |
25 | // Define the gravity vector.
26 | Vector2 gravity = new Vector2(0.0f, -10.0f);
27 |
28 | // Do we want to let bodies sleep?
29 | bool doSleep = true;
30 |
31 | // Construct a world object, which will hold and simulate the rigid bodies.
32 | World world = new World(worldAABB, gravity, doSleep);
33 |
34 | // Define the ground body.
35 | BodyDef groundBodyDef = new BodyDef();
36 | groundBodyDef.Position = new Vector2(0.0f, -10.0f);
37 |
38 | // Call the body factory which creates the ground box shape.
39 | // The body is also added to the world.
40 | Body groundBody = world.CreateBody(groundBodyDef);
41 |
42 | // Define the ground box shape.
43 | PolygonDef groundShapeDef = new PolygonDef();
44 |
45 | // The extents are the half-widths of the box.
46 | groundShapeDef.SetAsBox(50.0f, 10.0f);
47 |
48 | // Add the ground shape to the ground body.
49 | groundBody.CreateFixture(groundShapeDef);
50 |
51 | // Define the dynamic body. We set its position and call the body factory.
52 | BodyDef bodyDef = new BodyDef();
53 | bodyDef.Position = new Vector2(0.0f, 4.0f);
54 | Body body = world.CreateBody(bodyDef);
55 |
56 | // Define another box shape for our dynamic body.
57 | PolygonDef shapeDef = new PolygonDef();
58 | shapeDef.SetAsBox(1.0f, 1.0f);
59 |
60 | // Set the box density to be non-zero, so it will be dynamic.
61 | shapeDef.Density = 1.0f;
62 |
63 | // Override the default friction.
64 | shapeDef.Friction = 0.3f;
65 |
66 | // Add the shape to the body.
67 | body.CreateFixture(shapeDef);
68 |
69 | // Now tell the dynamic body to compute it's mass properties base
70 | // on its shape.
71 | body.SetMassFromShapes();
72 |
73 | // Prepare for simulation. Typically we use a time step of 1/60 of a
74 | // second (60Hz) and 10 iterations. This provides a high quality simulation
75 | // in most game scenarios.
76 | float timeStep = 1.0f / 60.0f;
77 | int velocityIterations = 8;
78 | int positionIterations = 1;
79 |
80 | // This is our little game loop.
81 | for (int i = 0; i < 100; ++i)
82 | {
83 | // Instruct the world to perform a single step of simulation. It is
84 | // generally best to keep the time step and iterations fixed.
85 | world.Step(timeStep, velocityIterations, positionIterations);
86 |
87 | // Now print the position and angle of the body.
88 | Vector2 position = body.GetPosition();
89 | float angle = body.GetAngle();
90 |
91 | Console.WriteLine("Step: {3} - X: {0}, Y: {1}, Angle: {2}", new object[] { position.X.ToString(), position.Y.ToString(), angle.ToString(), i.ToString() });
92 | }
93 |
94 | // When the world destructor is called, all bodies and joints are freed. This can
95 | // create orphaned pointers, so be careful about your world management.
96 | Console.ReadLine();
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/ContactState.cs:
--------------------------------------------------------------------------------
1 | namespace Testbed.Framework
2 | {
3 | public enum ContactState
4 | {
5 | ContactAdded,
6 | ContactPersisted,
7 | ContactRemoved
8 | }
9 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/DebugViewBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 | using Box2DNet.Common;
4 | using Box2DNet.Dynamics;
5 |
6 | namespace Testbed.Framework
7 | {
8 | [Flags]
9 | public enum DebugViewFlags
10 | {
11 | ///
12 | /// Draw shapes.
13 | ///
14 | Shape = (1 << 0),
15 |
16 | ///
17 | /// Draw joint connections.
18 | ///
19 | Joint = (1 << 1),
20 |
21 | ///
22 | /// Draw axis aligned bounding boxes.
23 | ///
24 | AABB = (1 << 2),
25 |
26 | ///
27 | /// Draw broad-phase pairs.
28 | ///
29 | //Pair = (1 << 3),
30 |
31 | ///
32 | /// Draw center of mass frame.
33 | ///
34 | CenterOfMass = (1 << 4),
35 |
36 | ///
37 | /// Draw useful debug data such as timings and number of bodies, joints, contacts and more.
38 | ///
39 | DebugPanel = (1 << 5),
40 |
41 | ///
42 | /// Draw contact points between colliding bodies.
43 | ///
44 | ContactPoints = (1 << 6),
45 |
46 | ///
47 | /// Draw contact normals. Need ContactPoints to be enabled first.
48 | ///
49 | ContactNormals = (1 << 7),
50 |
51 | ///
52 | /// Draws the vertices of polygons.
53 | ///
54 | PolygonPoints = (1 << 8),
55 |
56 | ///
57 | /// Draws the performance graph.
58 | ///
59 | PerformanceGraph = (1 << 9),
60 |
61 | ///
62 | /// Draws controllers.
63 | ///
64 | Controllers = (1 << 10)
65 | }
66 |
67 | /// Implement and register this class with a World to provide debug drawing of physics
68 | /// entities in your game.
69 | public abstract class DebugViewBase
70 | {
71 | protected DebugViewBase(World world)
72 | {
73 | World = world;
74 | }
75 |
76 | protected World World { get; private set; }
77 |
78 | ///
79 | /// Gets or sets the debug view flags.
80 | ///
81 | /// The flags.
82 | public DebugViewFlags Flags { get; set; }
83 |
84 | ///
85 | /// Append flags to the current flags.
86 | ///
87 | /// The flags.
88 | public void AppendFlags(DebugViewFlags flags)
89 | {
90 | Flags |= flags;
91 | }
92 |
93 | ///
94 | /// Remove flags from the current flags.
95 | ///
96 | /// The flags.
97 | public void RemoveFlags(DebugViewFlags flags)
98 | {
99 | Flags &= ~flags;
100 | }
101 |
102 | ///
103 | /// Draw a closed polygon provided in CCW order.
104 | ///
105 | /// The vertices.
106 | /// The vertex count.
107 | /// The red value.
108 | /// The blue value.
109 | /// The green value.
110 | public abstract void DrawPolygon(Vector2[] vertices, int count, float red, float blue, float green, bool closed = true);
111 |
112 | ///
113 | /// Draw a solid closed polygon provided in CCW order.
114 | ///
115 | /// The vertices.
116 | /// The vertex count.
117 | /// The red value.
118 | /// The blue value.
119 | /// The green value.
120 | public abstract void DrawSolidPolygon(Vector2[] vertices, int count, float red, float blue, float green);
121 |
122 | ///
123 | /// Draw a circle.
124 | ///
125 | /// The center.
126 | /// The radius.
127 | /// The red value.
128 | /// The blue value.
129 | /// The green value.
130 | public abstract void DrawCircle(Vector2 center, float radius, float red, float blue, float green);
131 |
132 | ///
133 | /// Draw a solid circle.
134 | ///
135 | /// The center.
136 | /// The radius.
137 | /// The axis.
138 | /// The red value.
139 | /// The blue value.
140 | /// The green value.
141 | public abstract void DrawSolidCircle(Vector2 center, float radius, Vector2 axis, float red, float blue,
142 | float green);
143 |
144 | ///
145 | /// Draw a line segment.
146 | ///
147 | /// The start.
148 | /// The end.
149 | /// The red value.
150 | /// The blue value.
151 | /// The green value.
152 | public abstract void DrawSegment(Vector2 start, Vector2 end, float red, float blue, float green);
153 |
154 | ///
155 | /// Draw a transform. Choose your own length scale.
156 | ///
157 | /// The transform.
158 | public abstract void DrawTransform(ref Transform transform);
159 | }
160 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/GameSettings.cs:
--------------------------------------------------------------------------------
1 | namespace Testbed.Framework
2 | {
3 | public class GameSettings
4 | {
5 | public float Hz;
6 | public bool Pause;
7 | public bool SingleStep;
8 |
9 | public GameSettings()
10 | {
11 |
12 | Hz = 60.0f;
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/KeyboardManager.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework.Input;
2 |
3 | namespace Testbed.Framework
4 | {
5 | public class KeyboardManager
6 | {
7 | internal KeyboardState _newKeyboardState;
8 | internal KeyboardState _oldKeyboardState;
9 |
10 | public bool IsNewKeyPress(Keys key)
11 | {
12 | return _newKeyboardState.IsKeyDown(key) && _oldKeyboardState.IsKeyUp(key);
13 | }
14 |
15 | public bool IsKeyDown(Keys key)
16 | {
17 | return _newKeyboardState.IsKeyDown(key);
18 | }
19 |
20 | internal bool IsKeyUp(Keys key)
21 | {
22 | return _newKeyboardState.IsKeyUp(key);
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/PrimitiveBatch.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.Xna.Framework;
3 | using Microsoft.Xna.Framework.Graphics;
4 |
5 | namespace Testbed.Framework
6 | {
7 | public class PrimitiveBatch : IDisposable
8 | {
9 | private const int DefaultBufferSize = 500;
10 |
11 | // a basic effect, which contains the shaders that we will use to draw our
12 | // primitives.
13 | private BasicEffect _basicEffect;
14 |
15 | // the device that we will issue draw calls to.
16 | private GraphicsDevice _device;
17 |
18 | // hasBegun is flipped to true once Begin is called, and is used to make
19 | // sure users don't call End before Begin is called.
20 | private bool _hasBegun;
21 |
22 | private bool _isDisposed;
23 | private VertexPositionColor[] _lineVertices;
24 | private int _lineVertsCount;
25 | private VertexPositionColor[] _triangleVertices;
26 | private int _triangleVertsCount;
27 |
28 | public PrimitiveBatch(GraphicsDevice graphicsDevice, int bufferSize = DefaultBufferSize)
29 | {
30 | if (graphicsDevice == null)
31 | throw new ArgumentNullException("graphicsDevice");
32 |
33 | _device = graphicsDevice;
34 |
35 | _triangleVertices = new VertexPositionColor[bufferSize - bufferSize % 3];
36 | _lineVertices = new VertexPositionColor[bufferSize - bufferSize % 2];
37 |
38 | // set up a new basic effect, and enable vertex colors.
39 | _basicEffect = new BasicEffect(graphicsDevice);
40 | _basicEffect.VertexColorEnabled = true;
41 | }
42 |
43 | #region IDisposable Members
44 |
45 | public void Dispose()
46 | {
47 | Dispose(true);
48 | GC.SuppressFinalize(this);
49 | }
50 |
51 | #endregion
52 |
53 | public void SetProjection(ref Matrix projection)
54 | {
55 | _basicEffect.Projection = projection;
56 | }
57 |
58 | protected virtual void Dispose(bool disposing)
59 | {
60 | if (disposing && !_isDisposed)
61 | {
62 | if (_basicEffect != null)
63 | _basicEffect.Dispose();
64 |
65 | _isDisposed = true;
66 | }
67 | }
68 |
69 |
70 | ///
71 | /// Begin is called to tell the PrimitiveBatch what kind of primitives will be
72 | /// drawn, and to prepare the graphics card to render those primitives.
73 | ///
74 | /// The projection.
75 | /// The view.
76 | public void Begin(ref Matrix projection, ref Matrix view)
77 | {
78 | if (_hasBegun)
79 | throw new InvalidOperationException("End must be called before Begin can be called again.");
80 |
81 | //tell our basic effect to begin.
82 | _basicEffect.Projection = projection;
83 | _basicEffect.View = view;
84 | _basicEffect.CurrentTechnique.Passes[0].Apply();
85 |
86 | // flip the error checking boolean. It's now ok to call AddVertex, Flush,
87 | // and End.
88 | _hasBegun = true;
89 | }
90 |
91 | public bool IsReady()
92 | {
93 | return _hasBegun;
94 | }
95 |
96 | public void AddVertex(Vector2 vertex, Color color, PrimitiveType primitiveType)
97 | {
98 | if (!_hasBegun)
99 | throw new InvalidOperationException("Begin must be called before AddVertex can be called.");
100 |
101 | if (primitiveType == PrimitiveType.LineStrip || primitiveType == PrimitiveType.TriangleStrip)
102 | throw new NotSupportedException("The specified primitiveType is not supported by PrimitiveBatch.");
103 |
104 | if (primitiveType == PrimitiveType.TriangleList)
105 | {
106 | if (_triangleVertsCount >= _triangleVertices.Length)
107 | FlushTriangles();
108 |
109 | _triangleVertices[_triangleVertsCount].Position = new Vector3(vertex, -0.1f);
110 | _triangleVertices[_triangleVertsCount].Color = color;
111 | _triangleVertsCount++;
112 | }
113 |
114 | if (primitiveType == PrimitiveType.LineList)
115 | {
116 | if (_lineVertsCount >= _lineVertices.Length)
117 | FlushLines();
118 |
119 | _lineVertices[_lineVertsCount].Position = new Vector3(vertex, 0f);
120 | _lineVertices[_lineVertsCount].Color = color;
121 | _lineVertsCount++;
122 | }
123 | }
124 |
125 | ///
126 | /// End is called once all the primitives have been drawn using AddVertex.
127 | /// it will call Flush to actually submit the draw call to the graphics card, and
128 | /// then tell the basic effect to end.
129 | ///
130 | public void End()
131 | {
132 | if (!_hasBegun)
133 | {
134 | throw new InvalidOperationException("Begin must be called before End can be called.");
135 | }
136 |
137 | // Draw whatever the user wanted us to draw
138 | FlushTriangles();
139 | FlushLines();
140 |
141 | _hasBegun = false;
142 | }
143 |
144 | private void FlushTriangles()
145 | {
146 | if (!_hasBegun)
147 | {
148 | throw new InvalidOperationException("Begin must be called before Flush can be called.");
149 | }
150 | if (_triangleVertsCount >= 3)
151 | {
152 | int primitiveCount = _triangleVertsCount / 3;
153 | // submit the draw call to the graphics card
154 | _device.SamplerStates[0] = SamplerState.AnisotropicClamp;
155 | _device.DrawUserPrimitives(PrimitiveType.TriangleList, _triangleVertices, 0, primitiveCount);
156 | _triangleVertsCount -= primitiveCount * 3;
157 | }
158 | }
159 |
160 | private void FlushLines()
161 | {
162 | if (!_hasBegun)
163 | {
164 | throw new InvalidOperationException("Begin must be called before Flush can be called.");
165 | }
166 | if (_lineVertsCount >= 2)
167 | {
168 | int primitiveCount = _lineVertsCount / 2;
169 | // submit the draw call to the graphics card
170 | _device.SamplerStates[0] = SamplerState.AnisotropicClamp;
171 | _device.DrawUserPrimitives(PrimitiveType.LineList, _lineVertices, 0, primitiveCount);
172 | _lineVertsCount -= primitiveCount * 2;
173 | }
174 | }
175 | }
176 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/Rand.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Testbed.Framework
4 | {
5 | public static class Rand
6 | {
7 | private static readonly Random Random = new Random();
8 |
9 | ///
10 | /// Random number in range [-1,1]
11 | ///
12 | ///
13 | public static float RandomFloat()
14 | {
15 | return (float)(Random.NextDouble() * 2.0 - 1.0);
16 | }
17 |
18 | ///
19 | /// Random floating point number in range [lo, hi]
20 | ///
21 | /// The lo.
22 | /// The hi.
23 | ///
24 | public static float RandomFloat(float lo, float hi)
25 | {
26 | float r = (float)Random.NextDouble();
27 | r = (hi - lo) * r + lo;
28 | return r;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/Test.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Box2DNet.Collision;
3 | using Box2DNet.Dynamics;
4 | using Microsoft.Xna.Framework;
5 | using Microsoft.Xna.Framework.Input;
6 |
7 | namespace Testbed.Framework
8 | {
9 | public class Test
10 | {
11 | internal DebugViewXNA DebugView;
12 | internal int StepCount;
13 | internal World World;
14 | private FixedMouseJoint _fixedMouseJoint;
15 | internal int TextLine;
16 |
17 | protected Test()
18 | {
19 | World = new World(new Vector2(0.0f, -10.0f));
20 |
21 | TextLine = 30;
22 |
23 | World.JointRemoved += JointRemoved;
24 | World.ContactManager.PreSolve += PreSolve;
25 | World.ContactManager.PostSolve += PostSolve;
26 |
27 | StepCount = 0;
28 | }
29 |
30 | public Game1 GameInstance { protected get; set; }
31 |
32 | public virtual void Initialize()
33 | {
34 | DebugView = new DebugViewXNA(World);
35 | DebugView.LoadContent(GameInstance.GraphicsDevice, GameInstance.Content);
36 | }
37 |
38 | protected virtual void JointRemoved(Joint joint)
39 | {
40 | if (_fixedMouseJoint == joint)
41 | _fixedMouseJoint = null;
42 | }
43 |
44 | public void DrawTitle(int x, int y, string title)
45 | {
46 | DebugView.DrawString(x, y, title);
47 | }
48 |
49 | public virtual void Update(GameSettings settings, GameTime gameTime)
50 | {
51 | float timeStep = Math.Min((float)gameTime.ElapsedGameTime.TotalMilliseconds * 0.001f, (1f / 30f));
52 |
53 | if (settings.Pause)
54 | {
55 | if (settings.SingleStep)
56 | settings.SingleStep = false;
57 | else
58 | timeStep = 0.0f;
59 |
60 | DrawString("****PAUSED****");
61 | }
62 | else
63 | World.Step(timeStep);
64 |
65 | if (timeStep > 0.0f)
66 | ++StepCount;
67 | }
68 |
69 | public virtual void Keyboard(KeyboardManager keyboardManager)
70 | {
71 | if (keyboardManager.IsNewKeyPress(Keys.F11))
72 | WorldSerializer.Serialize(World, "out.xml");
73 |
74 | if (keyboardManager.IsNewKeyPress(Keys.F12))
75 | {
76 | World = WorldSerializer.Deserialize("out.xml");
77 | Initialize();
78 | }
79 | }
80 |
81 | public virtual void Gamepad(GamePadState state, GamePadState oldState)
82 | {
83 | }
84 |
85 | public virtual void Mouse(MouseState state, MouseState oldState)
86 | {
87 | Vector2 position = GameInstance.ConvertScreenToWorld(state.X, state.Y);
88 |
89 | if (state.LeftButton == ButtonState.Released && oldState.LeftButton == ButtonState.Pressed)
90 | MouseUp();
91 | else if (state.LeftButton == ButtonState.Pressed && oldState.LeftButton == ButtonState.Released)
92 | MouseDown(position);
93 |
94 | MouseMove(position);
95 | }
96 |
97 | private void MouseDown(Vector2 p)
98 | {
99 | if (_fixedMouseJoint != null)
100 | return;
101 |
102 | Fixture fixture = World.TestPoint(p);
103 |
104 | if (fixture != null)
105 | {
106 | Body body = fixture.Body;
107 | _fixedMouseJoint = new FixedMouseJoint(body, p);
108 | _fixedMouseJoint.MaxForce = 1000.0f * body.Mass;
109 | World.AddJoint(_fixedMouseJoint);
110 | body.Awake = true;
111 | }
112 | }
113 |
114 | private void MouseUp()
115 | {
116 | if (_fixedMouseJoint != null)
117 | {
118 | World.RemoveJoint(_fixedMouseJoint);
119 | _fixedMouseJoint = null;
120 | }
121 | }
122 |
123 | private void MouseMove(Vector2 p)
124 | {
125 | if (_fixedMouseJoint != null)
126 | _fixedMouseJoint.WorldAnchorB = p;
127 | }
128 |
129 | protected virtual void PreSolve(Contact contact, ref Manifold oldManifold)
130 | {
131 | }
132 |
133 | protected virtual void PostSolve(Contact contact, ContactVelocityConstraint impulse)
134 | {
135 | }
136 |
137 | protected void DrawString(string text)
138 | {
139 | DebugView.DrawString(50, TextLine, text);
140 | TextLine += 15;
141 | }
142 | }
143 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/TestEntries.cs:
--------------------------------------------------------------------------------
1 | using Testbed.Tests;
2 |
3 | namespace Testbed.Framework
4 | {
5 | public static class TestEntries
6 | {
7 | public static readonly TestEntry[] TestList =
8 | {
9 |
10 | new TestEntry {Name = "Car", CreateTest = Car.Create},
11 |
12 | new TestEntry {Name = "Bridge", CreateTest = Bridge.Create},
13 |
14 | new TestEntry {Name = "Simple Test", CreateTest = SimpleTest.Create},
15 |
16 | new TestEntry {Name = null, CreateTest = null}
17 | };
18 | }
19 | }
--------------------------------------------------------------------------------
/examples/Testbed/Framework/TestEntry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Testbed.Framework
4 | {
5 | public struct TestEntry
6 | {
7 | public Func CreateTest;
8 | public string Name;
9 | }
10 | }
--------------------------------------------------------------------------------
/examples/Testbed/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Testbed
4 | {
5 | class Program
6 | {
7 | static void Main(string[] args)
8 | {
9 | using (var game = new Game1())
10 | {
11 | game.Run();
12 | }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/GLSL/imgui-frag.glsl:
--------------------------------------------------------------------------------
1 | #version 330 core
2 |
3 | uniform sampler2D FontTexture;
4 |
5 | in vec4 color;
6 | in vec2 texCoord;
7 |
8 | out vec4 outputColor;
9 |
10 | void main()
11 | {
12 | outputColor = color * texture(FontTexture, texCoord);
13 | }
14 |
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/GLSL/imgui-vertex.glsl:
--------------------------------------------------------------------------------
1 | #version 330 core
2 |
3 | uniform ProjectionMatrixBuffer
4 | {
5 | mat4 projection_matrix;
6 | };
7 |
8 | in vec2 in_position;
9 | in vec2 in_texCoord;
10 | in vec4 in_color;
11 |
12 | out vec4 color;
13 | out vec2 texCoord;
14 |
15 | void main()
16 | {
17 | gl_Position = projection_matrix * vec4(in_position, 0, 1);
18 | color = in_color;
19 | texCoord = in_texCoord;
20 | }
21 |
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/HLSL/imgui-frag.hlsl:
--------------------------------------------------------------------------------
1 | struct PS_INPUT
2 | {
3 | float4 pos : SV_POSITION;
4 | float4 col : COLOR0;
5 | float2 uv : TEXCOORD0;
6 | };
7 |
8 | Texture2D FontTexture : register(t0);
9 | sampler FontSampler : register(s0);
10 |
11 | float4 FS(PS_INPUT input) : SV_Target
12 | {
13 | float4 out_col = input.col * FontTexture.Sample(FontSampler, input.uv);
14 | return out_col;
15 | }
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/HLSL/imgui-frag.hlsl.bytes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/Testbed/Shaders/HLSL/imgui-frag.hlsl.bytes
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/HLSL/imgui-vertex.hlsl:
--------------------------------------------------------------------------------
1 | cbuffer ProjectionMatrixBuffer : register(b0)
2 | {
3 | float4x4 ProjectionMatrix;
4 | };
5 |
6 | struct VS_INPUT
7 | {
8 | float2 pos : POSITION;
9 | float2 uv : TEXCOORD0;
10 | float4 col : COLOR0;
11 | };
12 |
13 | struct PS_INPUT
14 | {
15 | float4 pos : SV_POSITION;
16 | float4 col : COLOR0;
17 | float2 uv : TEXCOORD0;
18 | };
19 |
20 | PS_INPUT VS(VS_INPUT input)
21 | {
22 | PS_INPUT output;
23 | output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));
24 | output.col = input.col;
25 | output.uv = input.uv;
26 | return output;
27 | }
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/HLSL/imgui-vertex.hlsl.bytes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/Testbed/Shaders/HLSL/imgui-vertex.hlsl.bytes
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/Metal/imgui-frag.metal:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace metal;
3 |
4 | struct PS_INPUT
5 | {
6 | float4 pos [[ position ]];
7 | float4 col;
8 | float2 uv;
9 | };
10 |
11 | fragment float4 FS(
12 | PS_INPUT input [[ stage_in ]],
13 | texture2d FontTexture [[ texture(0) ]],
14 | sampler FontSampler [[ sampler(0) ]])
15 | {
16 | float4 out_col = input.col * FontTexture.sample(FontSampler, input.uv);
17 | return out_col;
18 | }
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/Metal/imgui-frag.metallib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/Testbed/Shaders/Metal/imgui-frag.metallib
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/Metal/imgui-vertex.metal:
--------------------------------------------------------------------------------
1 | #include
2 | using namespace metal;
3 |
4 | struct VS_INPUT
5 | {
6 | float2 pos [[ attribute(0) ]];
7 | float2 uv [[ attribute(1) ]];
8 | float4 col [[ attribute(2) ]];
9 | };
10 |
11 | struct PS_INPUT
12 | {
13 | float4 pos [[ position ]];
14 | float4 col;
15 | float2 uv;
16 | };
17 |
18 | vertex PS_INPUT VS(
19 | VS_INPUT input [[ stage_in ]],
20 | constant float4x4 &ProjectionMatrix [[ buffer(1) ]])
21 | {
22 | PS_INPUT output;
23 | output.pos = ProjectionMatrix * float4(input.pos.xy, 0.f, 1.f);
24 | output.col = input.col;
25 | output.uv = input.uv;
26 | return output;
27 | }
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/Metal/imgui-vertex.metallib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/Testbed/Shaders/Metal/imgui-vertex.metallib
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/SPIR-V/generate-spirv.bat:
--------------------------------------------------------------------------------
1 | glslangvalidator -V imgui-vertex.glsl -o imgui-vertex.spv -S vert
2 | glslangvalidator -V imgui-frag.glsl -o imgui-frag.spv -S frag
3 |
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/SPIR-V/imgui-frag.glsl:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | #extension GL_ARB_separate_shader_objects : enable
4 | #extension GL_ARB_shading_language_420pack : enable
5 |
6 | layout(set = 1, binding = 0) uniform texture2D FontTexture;
7 | layout(set = 0, binding = 1) uniform sampler FontSampler;
8 |
9 | layout (location = 0) in vec4 color;
10 | layout (location = 1) in vec2 texCoord;
11 | layout (location = 0) out vec4 outputColor;
12 |
13 | void main()
14 | {
15 | outputColor = color * texture(sampler2D(FontTexture, FontSampler), texCoord);
16 | }
17 |
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/SPIR-V/imgui-frag.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/Testbed/Shaders/SPIR-V/imgui-frag.spv
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/SPIR-V/imgui-vertex.glsl:
--------------------------------------------------------------------------------
1 | #version 450
2 |
3 | #extension GL_ARB_separate_shader_objects : enable
4 | #extension GL_ARB_shading_language_420pack : enable
5 |
6 | layout (location = 0) in vec2 vsin_position;
7 | layout (location = 1) in vec2 vsin_texCoord;
8 | layout (location = 2) in vec4 vsin_color;
9 |
10 | layout (binding = 0) uniform Projection
11 | {
12 | mat4 projection;
13 | };
14 |
15 | layout (location = 0) out vec4 vsout_color;
16 | layout (location = 1) out vec2 vsout_texCoord;
17 |
18 | out gl_PerVertex
19 | {
20 | vec4 gl_Position;
21 | };
22 |
23 | void main()
24 | {
25 | gl_Position = projection * vec4(vsin_position, 0, 1);
26 | vsout_color = vsin_color;
27 | vsout_texCoord = vsin_texCoord;
28 | gl_Position.y = -gl_Position.y;
29 | }
30 |
--------------------------------------------------------------------------------
/examples/Testbed/Shaders/SPIR-V/imgui-vertex.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/examples/Testbed/Shaders/SPIR-V/imgui-vertex.spv
--------------------------------------------------------------------------------
/examples/Testbed/Testbed.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | netcoreapp2.1
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/Testbed/Tests/Bridge.cs:
--------------------------------------------------------------------------------
1 | using Box2DNet.Collision;
2 | using Box2DNet.Dynamics;
3 | using Testbed.Framework;
4 |
5 | namespace Testbed.Tests
6 | {
7 | public class Bridge : Test
8 | {
9 | private const int Count = 30;
10 |
11 | private BridgeTest()
12 | {
13 | Body ground;
14 | {
15 | ground = new Body(World);
16 |
17 | EdgeShape shape = new EdgeShape(new Vector2(-40.0f, 0.0f), new Vector2(40.0f, 0.0f));
18 | ground.CreateFixture(shape);
19 | }
20 | {
21 | Vertices box = PolygonTools.CreateRectangle(0.5f, 0.125f);
22 | PolygonShape shape = new PolygonShape(box, 20);
23 |
24 | Body prevBody = ground;
25 | for (int i = 0; i < Count; ++i)
26 | {
27 | Body body = BodyFactory.CreateBody(World);
28 | body.BodyType = Body.BodyType.Dynamic;
29 | body.Position = new Vector2(-14.5f + 1.0f * i, 5.0f);
30 |
31 | Fixture fixture = body.CreateFixture(shape);
32 | fixture.Friction = 0.2f;
33 |
34 | Vector2 anchor = new Vector2(-15f + 1.0f * i, 5.0f);
35 | RevoluteJoint jd = new RevoluteJoint(prevBody, body, anchor, true);
36 | World.AddJoint(jd);
37 |
38 | prevBody = body;
39 | }
40 |
41 | Vector2 anchor2 = new Vector2(-15.0f + 1.0f * Count, 5.0f);
42 | RevoluteJoint jd2 = new RevoluteJoint(ground, prevBody, anchor2, true);
43 | World.AddJoint(jd2);
44 | }
45 |
46 | Vertices vertices = new Vertices(3);
47 | vertices.Add(new Vector2(-0.5f, 0.0f));
48 | vertices.Add(new Vector2(0.5f, 0.0f));
49 | vertices.Add(new Vector2(0.0f, 1.5f));
50 |
51 | for (int i = 0; i < 2; ++i)
52 | {
53 | PolygonShape shape = new PolygonShape(vertices, 1);
54 |
55 | Body body = BodyFactory.CreateBody(World);
56 | body.BodyType = Body.BodyType.Dynamic;
57 | body.Position = new Vector2(-8.0f + 8.0f * i, 12.0f);
58 |
59 | body.CreateFixture(shape);
60 | }
61 |
62 | for (int i = 0; i < 3; ++i)
63 | {
64 | CircleShape shape = new CircleShape(0.5f, 1);
65 |
66 | Body body = BodyFactory.CreateBody(World);
67 | body.BodyType = Body.BodyType.Dynamic;
68 | body.Position = new Vector2(-6.0f + 6.0f * i, 10.0f);
69 |
70 | body.CreateFixture(shape);
71 | }
72 | }
73 |
74 | internal static Test Create()
75 | {
76 | return new BridgeTest();
77 | }
78 | }
79 | }
--------------------------------------------------------------------------------
/examples/Testbed/Tests/Car.cs:
--------------------------------------------------------------------------------
1 | using Box2DNet.Common;
2 | using Box2DNet.Dynamics;
3 | using Testbed.Framework;
4 | using Settings = Testbed.Framework.Settings;
5 |
6 | namespace Testbed.Tests
7 | {
8 | public class Car : Test
9 | {
10 | Body _leftWheel;
11 | Body _rightWheel;
12 | Body _vehicle;
13 | RevoluteJoint _leftJoint;
14 | RevoluteJoint _rightJoint;
15 |
16 | public Car()
17 | {
18 | { // car body
19 | PolygonDef poly1 = new PolygonDef(), poly2 = new PolygonDef();
20 |
21 | // bottom half
22 | poly1.VertexCount = 5;
23 | poly1.Vertices[4].Set(-2.2f, -0.74f);
24 | poly1.Vertices[3].Set(-2.2f, 0);
25 | poly1.Vertices[2].Set(1.0f, 0);
26 | poly1.Vertices[1].Set(2.2f, -0.2f);
27 | poly1.Vertices[0].Set(2.2f, -0.74f);
28 | poly1.Filter.GroupIndex = -1;
29 |
30 | poly1.Density = 20.0f;
31 | poly1.Friction = 0.68f;
32 | poly1.Filter.GroupIndex = -1;
33 |
34 | // top half
35 | poly2.VertexCount = 4;
36 | poly2.Vertices[3].Set(-1.7f, 0);
37 | poly2.Vertices[2].Set(-1.3f, 0.7f);
38 | poly2.Vertices[1].Set(0.5f, 0.74f);
39 | poly2.Vertices[0].Set(1.0f, 0);
40 | poly2.Filter.GroupIndex = -1;
41 |
42 | poly2.Density = 5.0f;
43 | poly2.Friction = 0.68f;
44 | poly2.Filter.GroupIndex = -1;
45 |
46 | BodyDef bd = new BodyDef();
47 | bd.Position.Set(-35.0f, 2.8f);
48 |
49 | _vehicle = _world.CreateBody(bd);
50 | _vehicle.CreateFixture(poly1);
51 | _vehicle.CreateFixture(poly2);
52 | _vehicle.SetMassFromShapes();
53 | }
54 |
55 | { // vehicle wheels
56 | CircleDef circ = new CircleDef();
57 | circ.Density = 40.0f;
58 | circ.Radius = 0.38608f;
59 | circ.Friction = 0.8f;
60 | circ.Filter.GroupIndex = -1;
61 |
62 | BodyDef bd = new BodyDef();
63 | bd.AllowSleep = false;
64 | bd.Position.Set(-33.8f, 2.0f);
65 |
66 | _rightWheel = _world.CreateBody(bd);
67 | _rightWheel.CreateFixture(circ);
68 | _rightWheel.SetMassFromShapes();
69 |
70 | bd.Position.Set(-36.2f, 2.0f);
71 | _leftWheel = _world.CreateBody(bd);
72 | _leftWheel.CreateFixture(circ);
73 | _leftWheel.SetMassFromShapes();
74 | }
75 |
76 | { // join wheels to chassis
77 | Vec2 anchor = new Vec2();
78 | RevoluteJointDef jd = new RevoluteJointDef();
79 | jd.Initialize(_vehicle, _leftWheel, _leftWheel.GetWorldCenter());
80 | jd.CollideConnected = false;
81 | jd.EnableMotor = true;
82 | jd.MaxMotorTorque = 10.0f;
83 | jd.MotorSpeed = 0.0f;
84 | _leftJoint = (RevoluteJoint)_world.CreateJoint(jd);
85 |
86 | jd.Initialize(_vehicle, _rightWheel, _rightWheel.GetWorldCenter());
87 | jd.CollideConnected = false;
88 | _rightJoint = (RevoluteJoint)_world.CreateJoint(jd);
89 | }
90 |
91 | { // ground
92 | PolygonDef box = new PolygonDef();
93 | box.SetAsBox(19.5f, 0.5f);
94 | box.Friction = 0.62f;
95 |
96 | BodyDef bd = new BodyDef();
97 | bd.Position.Set(-25.0f, 1.0f);
98 |
99 | Body ground = _world.CreateBody(bd);
100 | ground.CreateFixture(box);
101 | }
102 |
103 | { // more ground
104 | PolygonDef box = new PolygonDef();
105 | BodyDef bd = new BodyDef();
106 |
107 | box.SetAsBox(9.5f, 0.5f, Vec2.Zero, 0.1f * Box2DNet.Common.Settings.Pi);
108 | box.Friction = 0.62f;
109 | bd.Position.Set(27.0f - 30.0f, 3.1f);
110 |
111 | Body ground = _world.CreateBody(bd);
112 | ground.CreateFixture(box);
113 | }
114 |
115 | { // more ground
116 | PolygonDef box = new PolygonDef();
117 | BodyDef bd = new BodyDef();
118 |
119 | box.SetAsBox(9.5f, 0.5f, Vec2.Zero, -0.1f * Box2DNet.Common.Settings.Pi);
120 | box.Friction = 0.62f;
121 | bd.Position.Set(55.0f - 30.0f, 3.1f);
122 |
123 | Body ground = _world.CreateBody(bd);
124 | ground.CreateFixture(box);
125 | }
126 |
127 | { // more ground
128 | PolygonDef box = new PolygonDef();
129 | BodyDef bd = new BodyDef();
130 |
131 | box.SetAsBox(9.5f, 0.5f, Vec2.Zero, 0.03f * Box2DNet.Common.Settings.Pi);
132 | box.Friction = 0.62f;
133 | bd.Position.Set(41.0f, 2.0f);
134 |
135 | Body ground = _world.CreateBody(bd);
136 | ground.CreateFixture(box);
137 | }
138 |
139 | { // more ground
140 | PolygonDef box = new PolygonDef();
141 | BodyDef bd = new BodyDef();
142 |
143 | box.SetAsBox(5.0f, 0.5f, Vec2.Zero, 0.15f * Box2DNet.Common.Settings.Pi);
144 | box.Friction = 0.62f;
145 | bd.Position.Set(50.0f, 4.0f);
146 |
147 | Body ground = _world.CreateBody(bd);
148 | ground.CreateFixture(box);
149 | }
150 |
151 | { // more ground
152 | PolygonDef box = new PolygonDef();
153 | BodyDef bd = new BodyDef();
154 |
155 | box.SetAsBox(20.0f, 0.5f);
156 | box.Friction = 0.62f;
157 | bd.Position.Set(85.0f, 2.0f);
158 |
159 | Body ground = _world.CreateBody(bd);
160 | ground.CreateFixture(box);
161 | }
162 | }
163 |
164 | public static Test Create()
165 | {
166 | return new Car();
167 | }
168 |
169 | public override void Keyboard(System.Windows.Forms.Keys key)
170 | {
171 | switch (key)
172 | {
173 | case System.Windows.Forms.Keys.A:
174 | _leftJoint.SetMaxMotorTorque(800.0f);
175 | _leftJoint.MotorSpeed = 12.0f;
176 | break;
177 |
178 | case System.Windows.Forms.Keys.S:
179 | _leftJoint.SetMaxMotorTorque(100.0f);
180 | _leftJoint.MotorSpeed = 0.0f;
181 | break;
182 |
183 | case System.Windows.Forms.Keys.D:
184 | _leftJoint.SetMaxMotorTorque(1200.0f);
185 | _leftJoint.MotorSpeed = -36.0f;
186 | break;
187 | }
188 | }
189 |
190 | public override void Step(Settings settings)
191 | {
192 | OpenGLDebugDraw.DrawString(5, _textLine, "Keys: left = a, brake = s, right = d");
193 | _textLine += 15;
194 |
195 | base.Step(settings);
196 | }
197 | }
198 | }
--------------------------------------------------------------------------------
/examples/Testbed/Tests/SimpleTest.cs:
--------------------------------------------------------------------------------
1 | using Box2DNet.Dynamics;
2 | using Testbed.Framework;
3 |
4 | namespace Testbed.Tests
5 | {
6 | public class SimpleTest : Test
7 | {
8 | public SimpleTest()
9 | {
10 | // Define the ground body.
11 | BodyDef groundBodyDef = new BodyDef();
12 | groundBodyDef.Position.Set(0.0f, -10.0f);
13 |
14 | // Call the body factory which creates the ground box shape.
15 | // The body is also added to the world.
16 | Body groundBody = _world.CreateBody(groundBodyDef);
17 |
18 | // Define the ground box shape.
19 | PolygonDef groundShapeDef = new PolygonDef();
20 |
21 | // The extents are the half-widths of the box.
22 | groundShapeDef.SetAsBox(50.0f, 10.0f);
23 |
24 | // Add the ground shape to the ground body.
25 | groundBody.CreateFixture(groundShapeDef);
26 |
27 | for (int i = 0; i < 1; i++)
28 | {
29 | // Define the dynamic body. We set its position and call the body factory.
30 | BodyDef bodyDef = new BodyDef();
31 | bodyDef.Position.Set(0.0f, 4.0f * (i + 1));
32 | Body body = _world.CreateBody(bodyDef);
33 |
34 | // Define another box shape for our dynamic body.
35 | PolygonDef shapeDef = new PolygonDef();
36 | shapeDef.SetAsBox(1.0f, 1.0f);
37 |
38 | // Set the box density to be non-zero, so it will be dynamic.
39 | shapeDef.Density = 1.0f;
40 |
41 | // Override the default friction.
42 | shapeDef.Friction = 0.3f;
43 |
44 | // Add the shape to the body.
45 | body.CreateFixture(shapeDef);
46 |
47 | // Now tell the dynamic body to compute it's mass properties base
48 | // on its shape.
49 | body.SetMassFromShapes();
50 | }
51 |
52 | }
53 |
54 | public static Test Create()
55 | {
56 | return new SimpleTest();
57 | }
58 | }
59 | }
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/src/.DS_Store
--------------------------------------------------------------------------------
/src/Box2DNet/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codeyu/Box2DNet/46d00a414950b54a393d0571bb5fdd0235f7d167/src/Box2DNet/.DS_Store
--------------------------------------------------------------------------------
/src/Box2DNet/Box2DNet.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/Box2DNet/Box2DXDebug.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System; using System.Numerics;
20 | using System.Text;
21 | using System.Diagnostics;
22 | using System.Collections.Generic;
23 |
24 | namespace Box2DNet
25 | {
26 | public static class Box2DNetDebug
27 | {
28 | [Conditional("DEBUG")]
29 | public static void Assert(bool condition)
30 | {
31 | if (!condition)
32 | {
33 | condition = condition;
34 | }
35 | // Debug.Assert(condition);
36 | }
37 |
38 | [Conditional("DEBUG")]
39 | public static void Assert(bool condition, string message)
40 | {
41 | if (!condition)
42 | {
43 | condition = condition;
44 | }
45 | Debug.Assert(condition, message);
46 | }
47 |
48 | [Conditional("DEBUG")]
49 | public static void Assert(bool condition, string message, string detailMessage)
50 | {
51 | if (!condition)
52 | {
53 | condition = condition;
54 | }
55 | Debug.Assert(condition, message, detailMessage);
56 | }
57 |
58 | public static void ThrowBox2DNetException(String message)
59 | {
60 | string msg = $"Error: {message}";
61 | throw new Exception(msg);
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Collision/Collision.CollideCircle.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Common;
23 | using System.Numerics;
24 |
25 | using Transform = Box2DNet.Common.Transform;
26 | using System.Numerics;
27 | namespace Box2DNet.Collision
28 | {
29 | public partial class Collision
30 | {
31 | public static void CollideCircles(ref Manifold manifold, CircleShape circle1, Transform xf1, CircleShape circle2, Transform xf2)
32 | {
33 | manifold.PointCount = 0;
34 |
35 | Vector2 p1 = xf1.TransformPoint(circle1._position);
36 | Vector2 p2 = xf2.TransformPoint(circle2._position);
37 |
38 | Vector2 d = p2 - p1;
39 | float distSqr = Vector2.Dot(d, d);
40 | float radius = circle1._radius + circle2._radius;
41 | if (distSqr > radius * radius)
42 | {
43 | return;
44 | }
45 |
46 | manifold.Type = ManifoldType.Circles;
47 | manifold.LocalPoint = circle1._position;
48 | manifold.LocalPlaneNormal = Vector2.Zero;
49 | manifold.PointCount = 1;
50 |
51 | manifold.Points[0].LocalPoint = circle2._position;
52 | manifold.Points[0].ID.Key = 0;
53 | }
54 |
55 | public static void CollidePolygonAndCircle(ref Manifold manifold, PolygonShape polygon, Transform xf1, CircleShape circle, Transform xf2)
56 | {
57 | manifold.PointCount = 0;
58 |
59 | // Compute circle position in the frame of the polygon.
60 | Vector2 c = xf2.TransformPoint(circle._position);
61 | Vector2 cLocal = xf1.InverseTransformPoint(c);
62 |
63 | // Find the min separating edge.
64 | int normalIndex = 0;
65 | float separation = -Settings.FLT_MAX;
66 | float radius = polygon._radius + circle._radius;
67 | int vertexCount = polygon._vertexCount;
68 | Vector2[] vertices = polygon._vertices;
69 | Vector2[] normals = polygon._normals;
70 |
71 | for (int i = 0; i < vertexCount; ++i)
72 | {
73 | float s = Vector2.Dot(normals[i], cLocal - vertices[i]);
74 | if (s > radius)
75 | {
76 | // Early out.
77 | return;
78 | }
79 |
80 | if (s > separation)
81 | {
82 | separation = s;
83 | normalIndex = i;
84 | }
85 | }
86 |
87 | // Vertices that subtend the incident face.
88 | int vertIndex1 = normalIndex;
89 | int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0;
90 | Vector2 v1 = vertices[vertIndex1];
91 | Vector2 v2 = vertices[vertIndex2];
92 |
93 | // If the center is inside the polygon ...
94 | if (separation < Common.Settings.FLT_EPSILON)
95 | {
96 | manifold.PointCount = 1;
97 | manifold.Type = ManifoldType.FaceA;
98 | manifold.LocalPlaneNormal = normals[normalIndex];
99 | manifold.LocalPoint = 0.5f * (v1 + v2);
100 | manifold.Points[0].LocalPoint = circle._position;
101 | manifold.Points[0].ID.Key = 0;
102 | return;
103 | }
104 |
105 | // Compute barycentric coordinates
106 | float u1 = Vector2.Dot(cLocal - v1, v2 - v1);
107 | float u2 = Vector2.Dot(cLocal - v2, v1 - v2);
108 | if (u1 <= 0.0f)
109 | {
110 | if ((cLocal - v1).LengthSquared() > radius * radius)
111 | {
112 | return;
113 | }
114 |
115 | manifold.PointCount = 1;
116 | manifold.Type = ManifoldType.FaceA;
117 | manifold.LocalPlaneNormal = cLocal - v1;
118 | manifold.LocalPlaneNormal.Normalize();
119 | manifold.LocalPoint = v1;
120 | manifold.Points[0].LocalPoint = circle._position;
121 | manifold.Points[0].ID.Key = 0;
122 | }
123 | else if (u2 <= 0.0f)
124 | {
125 | if ((cLocal - v2).LengthSquared() > radius * radius)
126 | {
127 | return;
128 | }
129 |
130 | manifold.PointCount = 1;
131 | manifold.Type = ManifoldType.FaceA;
132 | manifold.LocalPlaneNormal = cLocal - v2;
133 | manifold.LocalPlaneNormal.Normalize();
134 | manifold.LocalPoint = v2;
135 | manifold.Points[0].LocalPoint = circle._position;
136 | manifold.Points[0].ID.Key = 0;
137 | }
138 | else
139 | {
140 | Vector2 faceCenter = 0.5f * (v1 + v2);
141 | float separation_ = Vector2.Dot(cLocal - faceCenter, normals[vertIndex1]);
142 | if (separation_ > radius)
143 | {
144 | return;
145 | }
146 |
147 | manifold.PointCount = 1;
148 | manifold.Type = ManifoldType.FaceA;
149 | manifold.LocalPlaneNormal = normals[vertIndex1];
150 | manifold.LocalPoint = faceCenter;
151 | manifold.Points[0].LocalPoint = circle._position;
152 | manifold.Points[0].ID.Key = 0;
153 | }
154 | }
155 | }
156 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Collision/Collision.CollideEdge.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Common;
23 |
24 |
25 | using Transform = Box2DNet.Common.Transform;
26 | using System.Numerics;
27 | namespace Box2DNet.Collision
28 | {
29 | public partial class Collision
30 | {
31 | // This implements 2-sided edge vs circle collision.
32 | public static void CollideEdgeAndCircle(ref Manifold manifold, EdgeShape edge, Transform transformA, CircleShape circle, Transform transformB)
33 | {
34 | manifold.PointCount = 0;
35 | Vector2 cLocal = Common.Math.MulT(transformA, Common.Math.Mul(transformB, circle._position));
36 | Vector2 normal = edge._normal;
37 | Vector2 v1 = edge._v1;
38 | Vector2 v2 = edge._v2;
39 | float radius = edge._radius + circle._radius;
40 |
41 | // Barycentric coordinates
42 | float u1 = Vector2.Dot(cLocal - v1, v2 - v1);
43 | float u2 = Vector2.Dot(cLocal - v2, v1 - v2);
44 |
45 | if (u1 <= 0.0f)
46 | {
47 | // Behind v1
48 | if ((cLocal- v1).LengthSquared() > radius * radius)
49 | {
50 | return;
51 | }
52 |
53 | manifold.PointCount = 1;
54 | manifold.Type = ManifoldType.FaceA;
55 | manifold.LocalPlaneNormal = cLocal - v1;
56 | manifold.LocalPlaneNormal.Normalize();
57 | manifold.LocalPoint = v1;
58 | manifold.Points[0].LocalPoint = circle._position;
59 | manifold.Points[0].ID.Key = 0;
60 | }
61 | else if (u2 <= 0.0f)
62 | {
63 | // Ahead of v2
64 | if ((cLocal- v2).LengthSquared() > radius * radius)
65 | {
66 | return;
67 | }
68 |
69 | manifold.PointCount = 1;
70 | manifold.Type = ManifoldType.FaceA;
71 | manifold.LocalPlaneNormal = cLocal - v2;
72 | manifold.LocalPlaneNormal.Normalize();
73 | manifold.LocalPoint = v2;
74 | manifold.Points[0].LocalPoint = circle._position;
75 | manifold.Points[0].ID.Key = 0;
76 | }
77 | else
78 | {
79 | float separation = Vector2.Dot(cLocal - v1, normal);
80 | if (separation < -radius || radius < separation)
81 | {
82 | return;
83 | }
84 |
85 | manifold.PointCount = 1;
86 | manifold.Type = ManifoldType.FaceA;
87 | manifold.LocalPlaneNormal = separation < 0.0f ? -normal : normal;
88 | manifold.LocalPoint = 0.5f * (v1 + v2);
89 | manifold.Points[0].LocalPoint = circle._position;
90 | manifold.Points[0].ID.Key = 0;
91 | }
92 | }
93 |
94 | // Polygon versus 2-sided edge.
95 | public static void CollidePolyAndEdge(ref Manifold manifold, PolygonShape polygon, Transform TransformA, EdgeShape edge, Transform TransformB)
96 | {
97 | PolygonShape polygonB = new PolygonShape();
98 | polygonB.SetAsEdge(edge._v1, edge._v2);
99 |
100 | CollidePolygons(ref manifold, polygon, TransformA, polygonB, TransformB);
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/Box2DNet/Collision/Shapes/CircleShape.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Common;
23 | using System.Numerics;
24 |
25 | using Transform = Box2DNet.Common.Transform;
26 |
27 | namespace Box2DNet.Collision
28 | {
29 | ///
30 | /// A circle shape.
31 | ///
32 | public class CircleShape : Shape
33 | {
34 | // Position
35 | internal Vector2 _position;
36 |
37 | public CircleShape()
38 | {
39 | _type = ShapeType.CircleShape;
40 | }
41 |
42 | public override bool TestPoint(Transform xf, Vector2 p)
43 | {
44 | Vector2 center = xf.position + xf.TransformDirection(_position);
45 | Vector2 d = p - center;
46 | return Vector2.Dot(d, d) <= _radius * _radius;
47 | }
48 |
49 | // Collision Detection in Interactive 3D Environments by Gino van den Bergen
50 | // From Section 3.1.2
51 | // x = s + a * r
52 | // norm(x) = radius
53 | public override SegmentCollide TestSegment(Transform xf, out float lambda, out Vector2 normal, Segment segment, float maxLambda)
54 | {
55 | lambda = 0f;
56 | normal = Vector2.Zero;
57 |
58 | Vector2 position = xf.position + xf.TransformDirection(_position);
59 | Vector2 s = segment.P1 - position;
60 | float b = Vector2.Dot(s, s) - _radius * _radius;
61 |
62 | // Does the segment start inside the circle?
63 | if (b < 0.0f)
64 | {
65 | lambda = 0f;
66 | return SegmentCollide.StartInsideCollide;
67 | }
68 |
69 | // Solve quadratic equation.
70 | Vector2 r = segment.P2 - segment.P1;
71 | float c = Vector2.Dot(s, r);
72 | float rr = Vector2.Dot(r, r);
73 | float sigma = c * c - rr * b;
74 |
75 | // Check for negative discriminant and short segment.
76 | if (sigma < 0.0f || rr < Common.Settings.FLT_EPSILON)
77 | {
78 | return SegmentCollide.MissCollide;
79 | }
80 |
81 | // Find the point of intersection of the line with the circle.
82 | float a = -(c + Common.Math.Sqrt(sigma));
83 |
84 | // Is the intersection point on the segment?
85 | if (0.0f <= a && a <= maxLambda * rr)
86 | {
87 | a /= rr;
88 | lambda = a;
89 | normal = s + a * r;
90 | normal.Normalize();
91 | return SegmentCollide.HitCollide;
92 | }
93 |
94 | return SegmentCollide.MissCollide;
95 | }
96 |
97 | public override void ComputeAABB(out AABB aabb, Transform xf)
98 | {
99 | aabb = new AABB();
100 |
101 | Vector2 p = xf.position + xf.TransformDirection(_position);
102 | aabb.LowerBound = new Vector2(p.X - _radius, p.Y - _radius);
103 | aabb.UpperBound = new Vector2(p.X + _radius, p.Y + _radius);
104 | }
105 |
106 | public override void ComputeMass(out MassData massData, float density)
107 | {
108 | massData = new MassData();
109 |
110 | massData.Mass = density * (float)System.Math.PI * _radius * _radius;
111 | massData.Center = _position;
112 |
113 | // inertia about the local origin
114 | massData.I = massData.Mass * (0.5f * _radius * _radius + Vector2.Dot(_position, _position));
115 | }
116 |
117 | public override float ComputeSubmergedArea(Vector2 normal, float offset, Transform xf, out Vector2 c)
118 | {
119 | Vector2 p = xf.TransformPoint(_position);
120 | float l = -(Vector2.Dot(normal, p) - offset);
121 | if (l < -_radius + Box2DNet.Common.Settings.FLT_EPSILON)
122 | {
123 | //Completely dry
124 | c = new Vector2();
125 | return 0;
126 | }
127 | if (l > _radius)
128 | {
129 | //Completely wet
130 | c = p;
131 | return Box2DNet.Common.Settings.Pi * _radius * _radius;
132 | }
133 |
134 | //Magic
135 | float r2 = _radius * _radius;
136 | float l2 = l * l;
137 | float area = r2 * ((float)System.Math.Asin(l / _radius) + Box2DNet.Common.Settings.Pi / 2) +
138 | l * Box2DNet.Common.Math.Sqrt(r2 - l2);
139 | float com = -2.0f / 3.0f * (float)System.Math.Pow(r2 - l2, 1.5f) / area;
140 |
141 | c.X = p.X + normal.X * com;
142 | c.Y = p.Y + normal.Y * com;
143 |
144 | return area;
145 | }
146 |
147 | ///
148 | /// Get the supporting vertex index in the given direction.
149 | ///
150 | public override int GetSupport(Vector2 d)
151 | {
152 | return 0;
153 | }
154 |
155 | ///
156 | /// Get the supporting vertex in the given direction.
157 | ///
158 | public override Vector2 GetSupportVertex(Vector2 d)
159 | {
160 | return _position;
161 | }
162 |
163 | ///
164 | /// Get a vertex by index. Used by Distance.
165 | ///
166 | public override Vector2 GetVertex(int index)
167 | {
168 | Box2DNetDebug.Assert(index == 0);
169 | return _position;
170 | }
171 |
172 | public override float ComputeSweepRadius(Vector2 pivot)
173 | {
174 | return Box2DNet.Common.Math.Distance(_position, pivot);
175 | }
176 |
177 | ///
178 | /// Get the vertex count.
179 | ///
180 | public int VertexCount { get { return 1; } }
181 | }
182 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Collision/Shapes/EdgeShape.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using System; using System.Numerics;
23 | using System.Collections.Generic;
24 | using System.Text;
25 | using Box2DNet.Common;
26 |
27 |
28 | using Transform = Box2DNet.Common.Transform;
29 |
30 | namespace Box2DNet.Collision
31 | {
32 | public class EdgeShape : Shape
33 | {
34 | public Vector2 _v1;
35 | public Vector2 _v2;
36 |
37 | public float _length;
38 |
39 | public Vector2 _normal;
40 |
41 | public Vector2 _direction;
42 |
43 | // Unit vector halfway between m_direction and m_prevEdge.m_direction:
44 | public Vector2 _cornerDir1;
45 |
46 | // Unit vector halfway between m_direction and m_nextEdge.m_direction:
47 | public Vector2 _cornerDir2;
48 |
49 | public bool _cornerConvex1;
50 | public bool _cornerConvex2;
51 |
52 | public EdgeShape _nextEdge;
53 | public EdgeShape _prevEdge;
54 |
55 | public EdgeShape()
56 | {
57 | _type = ShapeType.EdgeShape;
58 | _radius = Settings.PolygonRadius;
59 | }
60 |
61 | public override void Dispose()
62 | {
63 | if (_prevEdge != null)
64 | {
65 | _prevEdge._nextEdge = null;
66 | }
67 |
68 | if (_nextEdge != null)
69 | {
70 | _nextEdge._prevEdge = null;
71 | }
72 | }
73 |
74 | public void Set(Vector2 v1, Vector2 v2)
75 | {
76 | _v1 = v1;
77 | _v2 = v2;
78 |
79 | _direction = _v2 - _v1;
80 | _length = _direction.Length();
81 | _direction.Normalize();
82 | _normal = _direction.CrossScalarPostMultiply(1.0f);
83 |
84 | _cornerDir1 = _normal;
85 | _cornerDir2 = -1.0f * _normal;
86 | }
87 |
88 | public override bool TestPoint(Transform xf, Vector2 p)
89 | {
90 | return false;
91 | }
92 |
93 | public override SegmentCollide TestSegment(Transform xf, out float lambda, out Vector2 normal, Segment segment, float maxLambda)
94 | {
95 | Vector2 r = segment.P2 - segment.P1;
96 | Vector2 v1 = xf.TransformPoint(_v1);
97 | Vector2 d = ((Vector2)xf.TransformPoint(_v2)) - v1;
98 | Vector2 n = d.CrossScalarPostMultiply(1.0f);
99 |
100 | float k_slop = 100.0f * Common.Settings.FLT_EPSILON;
101 | float denom = -Vector2.Dot(r, n);
102 |
103 | // Cull back facing collision and ignore parallel segments.
104 | if (denom > k_slop)
105 | {
106 | // Does the segment intersect the infinite line associated with this segment?
107 | Vector2 b = segment.P1 - v1;
108 | float a = Vector2.Dot(b, n);
109 |
110 | if (0.0f <= a && a <= maxLambda * denom)
111 | {
112 | float mu2 = -r.X * b.Y + r.Y * b.X;
113 |
114 | // Does the segment intersect this segment?
115 | if (-k_slop * denom <= mu2 && mu2 <= denom * (1.0f + k_slop))
116 | {
117 | a /= denom;
118 | n.Normalize();
119 | lambda = a;
120 | normal = n;
121 | return SegmentCollide.HitCollide;
122 | }
123 | }
124 | }
125 |
126 | lambda = 0;
127 | normal = new Vector2();
128 | return SegmentCollide.MissCollide;
129 | }
130 |
131 | public override void ComputeAABB(out AABB aabb, Transform xf)
132 | {
133 | Vector2 v1 = xf.TransformPoint(_v1);
134 | Vector2 v2 = xf.TransformPoint(_v2);
135 |
136 | Vector2 r = new Vector2(_radius, _radius);
137 | aabb.LowerBound = Vector2.Min(v1, v2) - r;
138 | aabb.UpperBound = Vector2.Max(v1, v2) + r;
139 | }
140 |
141 | public override void ComputeMass(out MassData massData, float density)
142 | {
143 | massData.Mass = 0.0f;
144 | massData.Center = _v1;
145 | massData.I = 0.0f;
146 | }
147 |
148 | public void SetPrevEdge(EdgeShape edge, Vector2 cornerDir, bool convex)
149 | {
150 | _prevEdge = edge;
151 | _cornerDir1 = cornerDir;
152 | _cornerConvex1 = convex;
153 | }
154 |
155 | public void SetNextEdge(EdgeShape edge, Vector2 cornerDir, bool convex)
156 | {
157 | _nextEdge = edge;
158 | _cornerDir2 = cornerDir;
159 | _cornerConvex2 = convex;
160 | }
161 |
162 | public override float ComputeSubmergedArea(Vector2 normal, float offset, Transform xf, out Vector2 c)
163 | {
164 | //Note that v0 is independent of any details of the specific edge
165 | //We are relying on v0 being consistent between multiple edges of the same body
166 | Vector2 v0 = offset * normal;
167 | //b2Vec2 v0 = xf.position + (offset - b2Dot(normal, xf.position)) * normal;
168 |
169 | Vector2 v1 = xf.TransformPoint(_v1);
170 | Vector2 v2 = xf.TransformPoint(_v2);
171 |
172 | float d1 = Vector2.Dot(normal, v1) - offset;
173 | float d2 = Vector2.Dot(normal, v2) - offset;
174 |
175 | if (d1 > 0.0f)
176 | {
177 | if (d2 > 0.0f)
178 | {
179 | c = new Vector2();
180 | return 0.0f;
181 | }
182 | else
183 | {
184 | v1 = -d2 / (d1 - d2) * v1 + d1 / (d1 - d2) * v2;
185 | }
186 | }
187 | else
188 | {
189 | if (d2 > 0.0f)
190 | {
191 | v2 = -d2 / (d1 - d2) * v1 + d1 / (d1 - d2) * v2;
192 | }
193 | else
194 | {
195 | //Nothing
196 | }
197 | }
198 |
199 | // v0,v1,v2 represents a fully submerged triangle
200 | float k_inv3 = 1.0f / 3.0f;
201 |
202 | // Area weighted centroid
203 | c = k_inv3 * (v0 + v1 + v2);
204 |
205 | Vector2 e1 = v1 - v0;
206 | Vector2 e2 = v2 - v0;
207 |
208 | return 0.5f * e1.Cross(e2);
209 | }
210 |
211 | public float Length
212 | {
213 | get { return _length; }
214 | }
215 |
216 | public Vector2 Vertex1
217 | {
218 | get { return _v1; }
219 | }
220 |
221 | public Vector2 Vertex2
222 | {
223 | get { return _v2; }
224 | }
225 |
226 | public Vector2 NormalVector
227 | {
228 | get { return _normal; }
229 | }
230 |
231 | public Vector2 DirectionVector
232 | {
233 | get { return _direction; }
234 | }
235 |
236 | public Vector2 Corner1Vector
237 | {
238 | get { return _cornerDir1; }
239 | }
240 |
241 | public Vector2 Corner2Vector
242 | {
243 | get { return _cornerDir2; }
244 | }
245 |
246 | public override int GetSupport(Vector2 d)
247 | {
248 | return Vector2.Dot(_v1, d) > Vector2.Dot(_v2, d) ? 0 : 1;
249 | }
250 |
251 | public override Vector2 GetSupportVertex(Vector2 d)
252 | {
253 | return Vector2.Dot(_v1, d) > Vector2.Dot(_v2, d) ? _v1 : _v2;
254 | }
255 |
256 | public override Vector2 GetVertex(int index)
257 | {
258 | Box2DNetDebug.Assert(0 <= index && index < 2);
259 | if (index == 0) return _v1;
260 | else return _v2;
261 | }
262 |
263 | public bool Corner1IsConvex
264 | {
265 | get { return _cornerConvex1; }
266 | }
267 |
268 | public bool Corner2IsConvex
269 | {
270 | get { return _cornerConvex2; }
271 | }
272 |
273 | public override float ComputeSweepRadius(Vector2 pivot)
274 | {
275 | float ds1 = (_v1 - pivot).LengthSquared();
276 | float ds2 = (_v2 - pivot).LengthSquared();
277 | return (float)System.Math.Sqrt((float)System.Math.Max(ds1, ds2));
278 | }
279 | }
280 | }
281 |
--------------------------------------------------------------------------------
/src/Box2DNet/Collision/Shapes/Shape.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using System; using System.Numerics;
23 | using Box2DNet.Common;
24 |
25 |
26 | using Transform = Box2DNet.Common.Transform;
27 |
28 | namespace Box2DNet.Collision
29 | {
30 | ///
31 | /// This holds the mass data computed for a shape.
32 | ///
33 | public struct MassData
34 | {
35 | ///
36 | /// The mass of the shape, usually in kilograms.
37 | ///
38 | public float Mass;
39 |
40 | ///
41 | /// The position of the shape's centroid relative to the shape's origin.
42 | ///
43 | public Vector2 Center;
44 |
45 | ///
46 | /// The rotational inertia of the shape.
47 | ///
48 | public float I;
49 | }
50 |
51 | ///
52 | /// The various collision shape types supported by Box2D.
53 | ///
54 | public enum ShapeType
55 | {
56 | UnknownShape = -1,
57 | CircleShape,
58 | PolygonShape,
59 | EdgeShape,
60 | ShapeTypeCount,
61 | }
62 |
63 | ///
64 | /// Returns code from TestSegment
65 | ///
66 | public enum SegmentCollide
67 | {
68 | StartInsideCollide = -1,
69 | MissCollide = 0,
70 | HitCollide = 1
71 | }
72 |
73 | ///
74 | /// A shape is used for collision detection. You can create a shape however you like.
75 | /// Shapes used for simulation in World are created automatically when a Fixture is created.
76 | ///
77 | public abstract class Shape : IDisposable
78 | {
79 | #region Fields
80 |
81 | protected ShapeType _type = ShapeType.UnknownShape;
82 | internal float _radius;
83 |
84 | #endregion Fields
85 |
86 | protected Shape() { }
87 |
88 | ///
89 | /// Test a point for containment in this shape. This only works for convex shapes.
90 | ///
91 | /// The shape world Transform.
92 | /// A point in world coordinates.
93 | ///
94 | public abstract bool TestPoint(Transform xf, Vector2 p);
95 |
96 | ///
97 | /// Perform a ray cast against this shape.
98 | ///
99 | /// The shape world Transform.
100 | /// Returns the hit fraction. You can use this to compute the contact point
101 | /// p = (1 - lambda) * segment.P1 + lambda * segment.P2.
102 | /// Returns the normal at the contact point. If there is no intersection,
103 | /// the normal is not set.
104 | /// Defines the begin and end point of the ray cast.
105 | /// A number typically in the range [0,1].
106 | public abstract SegmentCollide TestSegment(Transform xf, out float lambda, out Vector2 normal, Segment segment, float maxLambda);
107 |
108 | ///
109 | /// Given a Transform, compute the associated axis aligned bounding box for this shape.
110 | ///
111 | /// Returns the axis aligned box.
112 | /// The world Transform of the shape.
113 | public abstract void ComputeAABB(out AABB aabb, Transform xf);
114 |
115 | ///
116 | /// Compute the mass properties of this shape using its dimensions and density.
117 | /// The inertia tensor is computed about the local origin, not the centroid.
118 | ///
119 | /// Returns the mass data for this shape
120 | public abstract void ComputeMass(out MassData massData, float density);
121 |
122 | ///
123 | /// Compute the volume and centroid of this shape intersected with a half plane.
124 | ///
125 | /// Normal the surface normal.
126 | /// Offset the surface offset along normal.
127 | /// The shape Transform.
128 | /// Returns the centroid.
129 | /// The total volume less than offset along normal.
130 | public abstract float ComputeSubmergedArea(Vector2 normal, float offset, Transform xf, out Vector2 c);
131 |
132 | ///
133 | /// Compute the sweep radius. This is used for conservative advancement (continuous collision detection).
134 | ///
135 | /// Pivot is the pivot point for rotation.
136 | /// The distance of the furthest point from the pivot.
137 | public abstract float ComputeSweepRadius(Vector2 pivot);
138 |
139 | public abstract Vector2 GetVertex(int index);
140 |
141 | public abstract int GetSupport(Vector2 d);
142 |
143 | public abstract Vector2 GetSupportVertex(Vector2 d);
144 |
145 | public virtual void Dispose(){}
146 | }
147 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Mar33.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | //r175
20 |
21 | using System; using System.Numerics;
22 | using System.Collections.Generic;
23 | using System.Text;
24 |
25 |
26 | namespace Box2DNet.Common
27 | {
28 | ///
29 | /// A 3-by-3 matrix. Stored in column-major order.
30 | ///
31 | public struct Mat33
32 | {
33 | ///
34 | /// Construct this matrix using columns.
35 | ///
36 | public Mat33(Vector3 c1, Vector3 c2, Vector3 c3)
37 | {
38 | Col1 = c1;
39 | Col2 = c2;
40 | Col3 = c3;
41 | }
42 |
43 | ///
44 | /// Set this matrix to all zeros.
45 | ///
46 | public void SetZero()
47 | {
48 | Col1 = Vector3.Zero;
49 | Col2 = Vector3.Zero;
50 | Col3 = Vector3.Zero;
51 | }
52 |
53 | ///
54 | /// Solve A * x = b, where b is a column vector. This is more efficient
55 | /// than computing the inverse in one-shot cases.
56 | ///
57 | public Vector3 Solve33(Vector3 b)
58 | {
59 | float det = Vector3.Dot(Col1, Vector3.Cross(Col2, Col3));
60 | Box2DNetDebug.Assert(det != 0.0f);
61 | det = 1.0f / det;
62 | Vector3 x = new Vector3();
63 | x.X = det * Vector3.Dot(b, Vector3.Cross(Col2, Col3));
64 | x.Y = det * Vector3.Dot(Col1, Vector3.Cross(b, Col3));
65 | x.Z = det * Vector3.Dot(Col1, Vector3.Cross(Col2, b));
66 | return x;
67 | }
68 |
69 | ///
70 | /// Solve A * x = b, where b is a column vector. This is more efficient
71 | /// than computing the inverse in one-shot cases. Solve only the upper
72 | /// 2-by-2 matrix equation.
73 | ///
74 | public Vector2 Solve22(Vector2 b)
75 | {
76 | float a11 = Col1.X, a12 = Col2.X, a21 = Col1.Y, a22 = Col2.Y;
77 | float det = a11 * a22 - a12 * a21;
78 | Box2DNetDebug.Assert(det != 0.0f);
79 | det = 1.0f / det;
80 | Vector2 x = new Vector2();
81 | x.X = det * (a22 * b.X - a12 * b.Y);
82 | x.Y = det * (a11 * b.Y - a21 * b.X);
83 | return x;
84 | }
85 |
86 | public Vector3 Col1;
87 | public Vector3 Col2;
88 | public Vector3 Col3;
89 | }
90 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Mat22.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System; using System.Numerics;
20 | using System.Collections.Generic;
21 | using System.Text;
22 |
23 |
24 | namespace Box2DNet.Common
25 | {
26 | ///
27 | /// A 2-by-2 matrix. Stored in column-major order.
28 | ///
29 | public struct Mat22
30 | {
31 | public Vector2 Col1;
32 | public Vector2 Col2;
33 |
34 | ///
35 | /// Construct this matrix using columns.
36 | ///
37 | public Mat22(Vector2 c1, Vector2 c2)
38 | {
39 | Col1 = c1;
40 | Col2 = c2;
41 | }
42 |
43 | ///
44 | /// Construct this matrix using scalars.
45 | ///
46 | public Mat22(float a11, float a12, float a21, float a22)
47 | {
48 | Col1.X = a11; Col1.Y = a21;
49 | Col2.X = a12; Col2.Y = a22;
50 | }
51 |
52 | ///
53 | /// Construct this matrix using an angle.
54 | /// This matrix becomes an orthonormal rotation matrix.
55 | ///
56 | public Mat22(float angle)
57 | {
58 | float c = (float)System.Math.Cos(angle);
59 | float s = (float)System.Math.Sin(angle);
60 | Col1.X = c; Col2.X = -s;
61 | Col1.Y = s; Col2.Y = c;
62 | }
63 |
64 | ///
65 | /// Initialize this matrix using columns.
66 | ///
67 | public void Set(Vector2 c1, Vector2 c2)
68 | {
69 | Col1 = c1;
70 | Col2 = c2;
71 | }
72 |
73 | ///
74 | /// Initialize this matrix using an angle.
75 | /// This matrix becomes an orthonormal rotation matrix.
76 | ///
77 | public void Set(float angle)
78 | {
79 | float c = (float)System.Math.Cos(angle);
80 | float s = (float)System.Math.Sin(angle);
81 | Col1.X = c; Col2.X = -s;
82 | Col1.Y = s; Col2.Y = c;
83 | }
84 |
85 | ///
86 | /// Extract the angle from this matrix (assumed to be a rotation matrix).
87 | ///
88 | public float GetAngle()
89 | {
90 | return Math.Atan2(Col1.Y, Col1.X);
91 | }
92 |
93 | public Vector2 Multiply(Vector2 vector) {
94 | return new Vector2(Col1.X * vector.Y + Col2.X * vector.Y, Col1.Y * vector.X + Col2.Y * vector.Y);
95 | }
96 |
97 | ///
98 | /// Compute the inverse of this matrix, such that inv(A) * A = identity.
99 | ///
100 | public Mat22 GetInverse()
101 | {
102 | float a = Col1.X, b = Col2.X, c = Col1.Y, d = Col2.Y;
103 | Mat22 B = new Mat22();
104 | float det = a * d - b * c;
105 | Box2DNetDebug.Assert(det != 0.0f);
106 | det = 1.0f / det;
107 | B.Col1.X = det * d; B.Col2.X = -det * b;
108 | B.Col1.Y = -det * c; B.Col2.Y = det * a;
109 | return B;
110 | }
111 |
112 | ///
113 | /// Solve A * x = b, where b is a column vector. This is more efficient
114 | /// than computing the inverse in one-shot cases.
115 | ///
116 | public Vector2 Solve(Vector2 b)
117 | {
118 | float a11 = Col1.X, a12 = Col2.X, a21 = Col1.Y, a22 = Col2.Y;
119 | float det = a11 * a22 - a12 * a21;
120 | Box2DNetDebug.Assert(det != 0.0f);
121 | det = 1.0f / det;
122 | Vector2 x = new Vector2();
123 | x.X = det * (a22 * b.X - a12 * b.Y);
124 | x.Y = det * (a11 * b.Y - a21 * b.X);
125 | return x;
126 | }
127 |
128 | public static Mat22 Identity { get { return new Mat22(1, 0, 0, 1); } }
129 |
130 | public static Mat22 operator +(Mat22 A, Mat22 B)
131 | {
132 | Mat22 C = new Mat22();
133 | C.Set(A.Col1 + B.Col1, A.Col2 + B.Col2);
134 | return C;
135 | }
136 | }
137 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Math.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System; using System.Numerics;
20 | using System.Collections.Generic;
21 | using System.Text;
22 |
23 |
24 | using Random = System.Random;
25 |
26 | namespace Box2DNet.Common
27 | {
28 | public static class Vector2Extension
29 | {
30 | public static float Rad2Deg = (float)360.0f / (float)(System.Math.PI * 2);
31 | public static Vector3 ToVector3(this Vector2 vector)
32 | {
33 | return new Vector3(vector.X, vector.Y, 0.0f);
34 | }
35 |
36 | public static bool IsValid(this Vector2 vector)
37 | {
38 | return Math.IsValid(vector.X) && Math.IsValid(vector.Y);
39 | }
40 |
41 | public static float Cross(this Vector2 vector, Vector2 other)
42 | {
43 | return vector.X * other.Y - vector.Y * other.X;
44 | }
45 |
46 | public static Vector2 CrossScalarPostMultiply(this Vector2 vector, float s)
47 | {
48 | return new Vector2(s * vector.Y, -s * vector.X);
49 | }
50 |
51 | public static Vector2 CrossScalarPreMultiply(this Vector2 vector, float s)
52 | {
53 | return new Vector2(-s * vector.Y, s * vector.X);
54 | }
55 |
56 | public static Vector2 Abs(this Vector2 vector) {
57 | return new Vector2(Math.Abs(vector.X), Math.Abs(vector.Y));
58 | }
59 | }
60 |
61 | public static class Vector3Extension
62 | {
63 | public static Vector2 ToVector2(this Vector3 vector)
64 | {
65 | return new Vector2(vector.X, vector.Y);
66 | }
67 | }
68 |
69 | public static class QuaternionExtension
70 | {
71 | public static Quaternion FromAngle2D(float radians)
72 | {
73 | return Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), radians * ((float)360.0f / (float)(System.Math.PI * 2)));
74 | }
75 | }
76 |
77 | public class Math
78 | {
79 | public static readonly ushort USHRT_MAX = 0xffff;
80 | public static readonly byte UCHAR_MAX = 0xff;
81 | public static readonly int RAND_LIMIT = 32767;
82 |
83 | ///
84 | /// This function is used to ensure that a floating point number is
85 | /// not a NaN or infinity.
86 | ///
87 | public static bool IsValid(float x)
88 | {
89 | return !(float.IsNaN(x) || float.IsNegativeInfinity(x) || float.IsPositiveInfinity(x));
90 | }
91 |
92 | [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
93 | public struct Convert
94 | {
95 | [System.Runtime.InteropServices.FieldOffset(0)]
96 | public float x;
97 |
98 | [System.Runtime.InteropServices.FieldOffset(0)]
99 | public int i;
100 | }
101 |
102 |
103 | #if USE_MATRIX_FOR_ROTATION
104 | public static Mat22 AngleToRotation(float angle)
105 | {
106 | return new Mat22(angle);
107 | }
108 | #else
109 | public static Quaternion AngleToRotation(float angle)
110 | {
111 | return QuaternionExtension.FromAngle2D(angle);
112 | }
113 | #endif
114 |
115 | ///
116 | /// This is a approximate yet fast inverse square-root.
117 | ///
118 | public static float InvSqrt(float x)
119 | {
120 | Convert convert = new Convert();
121 | convert.x = x;
122 | float xhalf = 0.5f * x;
123 | convert.i = 0x5f3759df - (convert.i >> 1);
124 | x = convert.x;
125 | x = x * (1.5f - xhalf * x * x);
126 | return x;
127 | }
128 |
129 | public static float Clamp(float f, float min, float max) {
130 | if (f < min)
131 | return min;
132 | else if (f > max)
133 | return max;
134 | else return f;
135 | }
136 | public static float Rad2Deg = 57.29578f;
137 | public static float Epsilon = 1.401298E-45f;
138 | public static float Sqrt(float x)
139 | {
140 | return Math.Sqrt(x);
141 | }
142 | public static float Distance(Vector2 v1, Vector2 v2) {
143 | return (float)System.Math.Sqrt(System.Math.Pow(v2.X - v1.X, 2) + System.Math.Pow(v2.Y - v1.Y, 2));
144 | }
145 |
146 | ///
147 | /// Random floating point number in range [lo, hi]
148 | ///
149 |
150 | ///
151 | /// "Next Largest Power of 2
152 | /// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm
153 | /// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with
154 | /// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next
155 | /// largest power of 2. For a 32-bit value:"
156 | ///
157 | public static uint NextPowerOfTwo(uint x)
158 | {
159 | x |= (x >> 1);
160 | x |= (x >> 2);
161 | x |= (x >> 4);
162 | x |= (x >> 8);
163 | x |= (x >> 16);
164 | return x + 1;
165 | }
166 |
167 | public static bool IsPowerOfTwo(uint x)
168 | {
169 | bool result = x > 0 && (x & (x - 1)) == 0;
170 | return result;
171 | }
172 |
173 | public static float Abs(float a)
174 | {
175 | return a > 0.0f ? a : -a;
176 | }
177 |
178 | public static Vector2 Abs(Vector2 a)
179 | {
180 | return new Vector2(Math.Abs(a.X), Math.Abs(a.Y));
181 | }
182 |
183 | public static Mat22 Abs(Mat22 A)
184 | {
185 | Mat22 B = new Mat22();
186 | B.Set(Math.Abs(A.Col1), Math.Abs(A.Col2));
187 | return B;
188 | }
189 |
190 | public static float Min(float a, float b)
191 | {
192 | return a < b ? a : b;
193 | }
194 |
195 | public static int Min(int a, int b)
196 | {
197 | return a < b ? a : b;
198 | }
199 |
200 | public static float Max(float a, float b)
201 | {
202 | return a > b ? a : b;
203 | }
204 |
205 | public static int Max(int a, int b)
206 | {
207 | return a > b ? a : b;
208 | }
209 |
210 | public static Vector2 Clamp(Vector2 a, Vector2 low, Vector2 high)
211 | {
212 | return Vector2.Max(low, Vector2.Min(a, high));
213 | }
214 |
215 | public static void Swap(ref T a, ref T b)
216 | {
217 | T tmp = a;
218 | a = b;
219 | b = tmp;
220 | }
221 |
222 | ///
223 | /// Multiply a matrix times a vector. If a rotation matrix is provided,
224 | /// then this Transforms the vector from one frame to another.
225 | ///
226 | public static Vector2 Mul(Mat22 A, Vector2 v)
227 | {
228 | return new Vector2(A.Col1.X * v.X + A.Col2.X * v.Y, A.Col1.Y * v.X + A.Col2.Y * v.Y);
229 | }
230 |
231 | ///
232 | /// Multiply a matrix transpose times a vector. If a rotation matrix is provided,
233 | /// then this Transforms the vector from one frame to another (inverse Transform).
234 | ///
235 | public static Vector2 MulT(Mat22 A, Vector2 v)
236 | {
237 | return new Vector2(Vector2.Dot(v, A.Col1), Vector2.Dot(v, A.Col2));
238 | }
239 |
240 | ///
241 | /// A * B
242 | ///
243 | public static Mat22 Mul(Mat22 A, Mat22 B)
244 | {
245 | Mat22 C = new Mat22();
246 | C.Set(Math.Mul(A, B.Col1), Math.Mul(A, B.Col2));
247 | return C;
248 | }
249 |
250 | ///
251 | /// A^T * B
252 | ///
253 | public static Mat22 MulT(Mat22 A, Mat22 B)
254 | {
255 | Vector2 c1 = new Vector2(Vector2.Dot(A.Col1, B.Col1), Vector2.Dot(A.Col2, B.Col1));
256 | Vector2 c2 = new Vector2(Vector2.Dot(A.Col1, B.Col2), Vector2.Dot(A.Col2, B.Col2));
257 | return new Mat22(c1, c2);
258 | }
259 |
260 | public static Vector2 Mul(Transform T, Vector2 v)
261 | {
262 | #if USE_MATRIX_FOR_ROTATION
263 | return T.position + Math.Mul(T.R, v);
264 | #else
265 | return T.position + T.TransformDirection(v);
266 | #endif
267 | }
268 |
269 | public static Vector2 MulT(Transform T, Vector2 v)
270 | {
271 | #if USE_MATRIX_FOR_ROTATION
272 | return Math.MulT(T.R, v - T.position);
273 | #else
274 | return T.InverseTransformDirection(v - T.position);
275 | #endif
276 | }
277 |
278 | ///
279 | /// Multiply a matrix times a vector.
280 | ///
281 | public static Vector3 Mul(Mat33 A, Vector3 v)
282 | {
283 | return v.X * A.Col1 + v.Y * A.Col2 + v.Z * A.Col3;
284 | }
285 |
286 | public static float Atan2(float y, float x)
287 | {
288 | return (float)System.Math.Atan2(y, x);
289 | }
290 | }
291 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Settings.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System; using System.Numerics;
20 | using System.Collections.Generic;
21 | using System.Text;
22 |
23 | namespace Box2DNet.Common
24 | {
25 | public class Settings
26 | {
27 | #if TARGET_FLOAT32_IS_FIXED
28 | public static readonly float FLT_EPSILON = FIXED_EPSILON;
29 | public static readonly float FLT_MAX = FIXED_MAX;
30 | public static float FORCE_SCALE2(x){ return x<<7;}
31 | public static float FORCE_INV_SCALE2(x) {return x>>7;}
32 | #else
33 | public static readonly float FLT_EPSILON = 1.192092896e-07F;//smallest such that 1.0f+FLT_EPSILON != 1.0f
34 | public static readonly float FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;//smallest such that 1.0f+FLT_EPSILON != 1.0f
35 | public static readonly float FLT_MAX = 3.402823466e+38F;
36 | public static float FORCE_SCALE(float x) { return x; }
37 | public static float FORCE_INV_SCALE(float x) { return x; }
38 | #endif
39 |
40 | public static readonly float Pi = 3.14159265359f;
41 |
42 | // Global tuning constants based on meters-kilograms-seconds (MKS) units.
43 |
44 | // Collision
45 | public static readonly int MaxManifoldPoints = 2;
46 | public static readonly int MaxPolygonVertices = 8;
47 | public static readonly int MaxProxies = 512; // this must be a power of two
48 | public static readonly int MaxPairs = 8 * MaxProxies; // this must be a power of two
49 |
50 | // Dynamics
51 |
52 | ///
53 | /// A small length used as a collision and constraint tolerance. Usually it is
54 | /// chosen to be numerically significant, but visually insignificant.
55 | ///
56 | public static readonly float LinearSlop = 0.005f; // 0.5 cm
57 |
58 | ///
59 | /// A small angle used as a collision and constraint tolerance. Usually it is
60 | /// chosen to be numerically significant, but visually insignificant.
61 | ///
62 | public static readonly float AngularSlop = 2.0f / 180.0f * Pi; // 2 degrees
63 |
64 | ///
65 | /// The radius of the polygon/edge shape skin. This should not be modified. Making
66 | /// this smaller means polygons will have and insufficient for continuous collision.
67 | /// Making it larger may create artifacts for vertex collision.
68 | ///
69 | public static readonly float PolygonRadius = 2.0f * LinearSlop;
70 |
71 | ///
72 | /// Continuous collision detection (CCD) works with core, shrunken shapes. This is amount
73 | /// by which shapes are automatically shrunk to work with CCD.
74 | /// This must be larger than LinearSlop.
75 | ///
76 | public static readonly float ToiSlop = 8.0f * LinearSlop;
77 |
78 | ///
79 | /// Maximum number of contacts to be handled to solve a TOI island.
80 | ///
81 | public static readonly int MaxTOIContactsPerIsland = 32;
82 |
83 | ///
84 | /// Maximum number of joints to be handled to solve a TOI island.
85 | ///
86 | public static readonly int MaxTOIJointsPerIsland = 32;
87 |
88 | ///
89 | /// A velocity threshold for elastic collisions. Any collision with a relative linear
90 | /// velocity below this threshold will be treated as inelastic.
91 | ///
92 | public static readonly float VelocityThreshold = 1.0f; // 1 m/s
93 |
94 | ///
95 | /// The maximum linear position correction used when solving constraints.
96 | /// This helps to prevent overshoot.
97 | ///
98 | public static readonly float MaxLinearCorrection = 0.2f; // 20 cm
99 |
100 | ///
101 | /// The maximum angular position correction used when solving constraints.
102 | /// This helps to prevent overshoot.
103 | ///
104 | public static readonly float MaxAngularCorrection = 8.0f / 180.0f * Pi; // 8 degrees
105 |
106 | ///
107 | /// The maximum linear velocity of a body. This limit is very large and is used
108 | /// to prevent numerical problems. You shouldn't need to adjust this.
109 | ///
110 | #if TARGET_FLOAT32_IS_FIXED
111 | public static readonly float MaxLinearVelocity = 100.0f;
112 | #else
113 | public static readonly float MaxLinearVelocity = 200.0f;
114 | public static readonly float MaxLinearVelocitySquared = MaxLinearVelocity * MaxLinearVelocity;
115 | #endif
116 | ///
117 | /// The maximum angular velocity of a body. This limit is very large and is used
118 | /// to prevent numerical problems. You shouldn't need to adjust this.
119 | ///
120 | public static readonly float MaxAngularVelocity = 250.0f;
121 | #if !TARGET_FLOAT32_IS_FIXED
122 | public static readonly float MaxAngularVelocitySquared = MaxAngularVelocity * MaxAngularVelocity;
123 | #endif
124 |
125 | ///
126 | /// The maximum linear velocity of a body. This limit is very large and is used
127 | /// to prevent numerical problems. You shouldn't need to adjust this.
128 | ///
129 | public static readonly float MaxTranslation = 2.0f;
130 | public static readonly float MaxTranslationSquared = (MaxTranslation * MaxTranslation);
131 |
132 | ///
133 | /// The maximum angular velocity of a body. This limit is very large and is used
134 | /// to prevent numerical problems. You shouldn't need to adjust this.
135 | ///
136 | public static readonly float MaxRotation = (0.5f * Pi);
137 | public static readonly float MaxRotationSquared = (MaxRotation * MaxRotation);
138 |
139 | ///
140 | /// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so
141 | /// that overlap is removed in one time step. However using values close to 1 often lead to overshoot.
142 | ///
143 | public static readonly float ContactBaumgarte = 0.2f;
144 |
145 | // Sleep
146 |
147 | ///
148 | /// The time that a body must be still before it will go to sleep.
149 | ///
150 | public static readonly float TimeToSleep = 0.5f; // half a second
151 |
152 | ///
153 | /// A body cannot sleep if its linear velocity is above this tolerance.
154 | ///
155 | public static readonly float LinearSleepTolerance = 0.01f; // 1 cm/s
156 |
157 | ///
158 | /// A body cannot sleep if its angular velocity is above this tolerance.
159 | ///
160 | public static readonly float AngularSleepTolerance = 2.0f / 180.0f; // 2 degrees/s
161 |
162 | ///
163 | /// Friction mixing law. Feel free to customize this.
164 | ///
165 | public static float MixFriction(float friction1, float friction2)
166 | {
167 | return (float)System.Math.Sqrt(friction1 * friction2);
168 | }
169 |
170 | ///
171 | /// Restitution mixing law. Feel free to customize this.
172 | ///
173 | public static float MixRestitution(float restitution1, float restitution2)
174 | {
175 | return restitution1 > restitution2 ? restitution1 : restitution2;
176 | }
177 | }
178 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Sweep.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | //r175
20 |
21 | using System; using System.Numerics;
22 | using System.Collections.Generic;
23 | using System.Text;
24 |
25 |
26 | namespace Box2DNet.Common
27 | {
28 | public struct Sweep
29 | {
30 | public Vector2 LocalCenter; //local center of mass position
31 | public Vector2 C0, C; //local center of mass position
32 | public float A0, A; //world angles
33 | public float T0; //time interval = [T0,1], where T0 is in [0,1]
34 |
35 | ///
36 | /// Get the interpolated Transform at a specific time.
37 | ///
38 | /// Alpha is a factor in [0,1], where 0 indicates t0.
39 | public void GetTransform(out Transform xf, float alpha)
40 | {
41 | xf = new Transform();
42 | xf.position = (1.0f - alpha) * C0 + alpha * C;
43 | float angle = (1.0f - alpha) * A0 + alpha * A;
44 |
45 | xf.rotation = Box2DNet.Common.Math.AngleToRotation(angle);
46 | //xf.R = new Mat22(angle);
47 |
48 | // Shift to origin
49 | xf.position -= xf.TransformDirection(LocalCenter);
50 | }
51 |
52 | ///
53 | /// Advance the sweep forward, yielding a new initial state.
54 | ///
55 | /// The new initial time.
56 | public void Advance(float t)
57 | {
58 | if (T0 < t && 1.0f - T0 > Settings.FLT_EPSILON)
59 | {
60 | float alpha = (t - T0) / (1.0f - T0);
61 | C0 = (1.0f - alpha) * C0 + alpha * C;
62 | A0 = (1.0f - alpha) * A0 + alpha * A;
63 | T0 = t;
64 | }
65 | }
66 | }
67 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Transform.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System;
20 | using System.Numerics;
21 | using System.Collections.Generic;
22 | using System.Text;
23 |
24 |
25 |
26 | namespace Box2DNet.Common
27 | {
28 | ///
29 | /// A Transform contains translation and rotation.
30 | /// It is used to represent the position and orientation of rigid frames.
31 | ///
32 | public struct Transform
33 | {
34 | public Vector2 position;
35 | #if USE_MATRIX_FOR_ROTATION
36 | public Mat22 rotation;
37 | #else
38 | public Quaternion rotation;
39 | #endif
40 |
41 | #if USE_MATRIX_FOR_ROTATION
42 | ///
43 | /// Initialize using a position vector and a rotation matrix.
44 | ///
45 | ///
46 | ///
47 | public Transform(Vector2 position, Mat22 rotation)
48 | {
49 | this.position = position;
50 | this.rotation = rotation;
51 | }
52 | #else
53 | ///
54 | /// Initialize using a position vector and a rotation matrix.
55 | ///
56 | ///
57 | ///
58 | public Transform(Vector2 position, Quaternion rotation)
59 | {
60 | this.position = position;
61 | this.rotation = rotation;
62 | }
63 | #endif
64 |
65 | public Vector2 InverseTransformPoint(Vector2 vector)
66 | {
67 | #if USE_MATRIX_FOR_ROTATION
68 | return Math.MulT(rotation, vector - position);
69 | #else
70 | return Quaternion.Inverse(rotation).Xyz().ToVector2() * (vector - position);
71 | #endif
72 | }
73 |
74 | public Vector2 InverseTransformDirection(Vector2 vector)
75 | {
76 | #if USE_MATRIX_FOR_ROTATION
77 | return Math.MulT(rotation, vector);
78 | #else
79 | return Quaternion.Inverse(rotation).Xyz().ToVector2() * vector;
80 | #endif
81 | }
82 |
83 | public Vector2 TransformPoint(Vector2 vector)
84 | {
85 | #if USE_MATRIX_FOR_ROTATION
86 | return position + Math.Mul(rotation, vector);
87 | #else
88 | return position + (rotation.Xyz() * vector.ToVector3()).ToVector2();
89 | #endif
90 |
91 | }
92 |
93 | //
94 | // Transforms direction from local space to world space.
95 | //
96 | public Vector2 TransformDirection(Vector2 vector)
97 | {
98 | #if USE_MATRIX_FOR_ROTATION
99 | return Math.Mul(rotation, vector);
100 | #else
101 | return (rotation.Xyz() * vector.ToVector3()).ToVector2();
102 | #endif
103 | }
104 |
105 | #if USE_MATRIX_FOR_ROTATION
106 | public static readonly Transform identify = new Transform(Vector2.zero, Mat22.Identity);
107 | #else
108 | public static readonly Transform identity = new Transform(Vector2.Zero, Quaternion.Identity);
109 | #endif
110 | }
111 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Utils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Numerics;
3 |
4 | namespace Box2DNet.Common
5 | {
6 | public static class Utils
7 | {
8 | public static Vector3 Xyz(this Quaternion q)
9 | {
10 | return new Vector3(q.X,q.Y,q.Z);
11 | }
12 |
13 | public static void Normalize(this Vector2 v2)
14 | {
15 | var scale = 1.0f / v2.Length();
16 | v2.X *= scale;
17 | v2.Y *= scale;
18 | }
19 |
20 | public static Vector2 Normalized(this Vector2 v2)
21 | {
22 |
23 | var scale = 1.0f / v2.Length();
24 | v2.X *= scale;
25 | v2.Y *= scale;
26 | return v2;
27 | }
28 | ///
29 | /// Gets or sets the value at the index of the Vector.
30 | ///
31 | public static float GetByIndex(this Vector2 v2, int index)
32 | {
33 |
34 | if (index == 0)
35 | {
36 | return v2.X;
37 | }
38 | else if (index == 1)
39 | {
40 | return v2.Y;
41 | }
42 | throw new IndexOutOfRangeException("You tried to access this vector at index: " + index);
43 |
44 | }
45 |
46 | public static void SetByIndex(this Vector2 v2, int index, float value)
47 | {
48 | switch (index)
49 | {
50 | case 0:
51 | v2.X = value;
52 | break;
53 | case 1:
54 | v2.Y = value;
55 | break;
56 | default:
57 | throw new IndexOutOfRangeException("You tried to set this vector at index: " + index);
58 | }
59 | }
60 |
61 | }
62 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Vec2.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System; using System.Numerics;
20 | using System.Collections.Generic;
21 | using System.Text;
22 |
23 | namespace Box2DNet.Common
24 | {
25 | ///
26 | /// A 2D column vector.
27 | ///
28 | public struct Vec2
29 | {
30 | public float X, Y;
31 |
32 | public float this[int i]
33 | {
34 | get
35 | {
36 | if (i == 0) return X;
37 | else if (i == 1) return Y;
38 | else
39 | {
40 | Box2DNetDebug.Assert(false, "Incorrect Vec2 element!");
41 | return 0;
42 | }
43 | }
44 | set
45 | {
46 | if (i == 0) X = value;
47 | else if (i == 1) Y = value;
48 | else
49 | {
50 | Box2DNetDebug.Assert(false, "Incorrect Vec2 element!");
51 | }
52 | }
53 | }
54 |
55 | ///
56 | /// Construct using coordinates.
57 | ///
58 | public Vec2(float x)
59 | {
60 | X = x;
61 | Y = x;
62 | }
63 |
64 | ///
65 | /// Construct using coordinates.
66 | ///
67 | public Vec2(float x, float y)
68 | {
69 | X = x;
70 | Y = y;
71 | }
72 |
73 | ///
74 | /// Set this vector to all zeros.
75 | ///
76 | public void SetZero() { X = 0.0f; Y = 0.0f; }
77 |
78 | ///
79 | /// Set this vector to some specified coordinates.
80 | ///
81 | public void Set(float x, float y) { X = x; Y = y; }
82 |
83 | public void Set(float xy) { X = xy; Y = xy; }
84 |
85 | ///
86 | /// Get the length of this vector (the norm).
87 | ///
88 | public float Length()
89 | {
90 | return (float)System.Math.Sqrt(X * X + Y * Y);
91 | }
92 |
93 | ///
94 | /// Get the length squared. For performance, use this instead of
95 | /// Length (if possible).
96 | ///
97 | public float LengthSquared()
98 | {
99 | return X * X + Y * Y;
100 | }
101 |
102 | ///
103 | /// Convert this vector into a unit vector. Returns the length.
104 | ///
105 | public float Normalize()
106 | {
107 | float length = Length();
108 | if (length < Settings.FLT_EPSILON)
109 | {
110 | return 0.0f;
111 | }
112 | float invLength = 1.0f / length;
113 | X *= invLength;
114 | Y *= invLength;
115 |
116 | return length;
117 | }
118 |
119 | ///
120 | /// Does this vector contain finite coordinates?
121 | ///
122 | public bool IsValid
123 | {
124 | get { return Math.IsValid(X) && Math.IsValid(Y); }
125 | }
126 |
127 | ///
128 | /// Negate this vector.
129 | ///
130 | public static Vec2 operator -(Vec2 v1)
131 | {
132 | Vec2 v = new Vec2();
133 | v.Set(-v1.X, -v1.Y);
134 | return v;
135 | }
136 |
137 | public static Vec2 operator +(Vec2 v1, Vec2 v2)
138 | {
139 | Vec2 v = new Vec2();
140 | v.Set(v1.X + v2.X, v1.Y + v2.Y);
141 | return v;
142 | }
143 |
144 | public static Vec2 operator -(Vec2 v1, Vec2 v2)
145 | {
146 | Vec2 v = new Vec2();
147 | v.Set(v1.X - v2.X, v1.Y - v2.Y);
148 | return v;
149 | }
150 |
151 | public static Vec2 operator *(Vec2 v1, float a)
152 | {
153 | Vec2 v = new Vec2();
154 | v.Set(v1.X * a, v1.Y * a);
155 | return v;
156 | }
157 |
158 | public static Vec2 operator *(float a, Vec2 v1)
159 | {
160 | Vec2 v = new Vec2();
161 | v.Set(v1.X * a, v1.Y * a);
162 | return v;
163 | }
164 |
165 | public static bool operator ==(Vec2 a, Vec2 b)
166 | {
167 | return a.X == b.X && a.Y == b.Y;
168 | }
169 |
170 | public static bool operator !=(Vec2 a, Vec2 b)
171 | {
172 | return a.X != b.X || a.Y != b.Y;
173 | }
174 |
175 | public static Vec2 Zero { get { return new Vec2(0, 0); } }
176 |
177 | ///
178 | /// Peform the dot product on two vectors.
179 | ///
180 | public static float Dot(Vec2 a, Vec2 b)
181 | {
182 | return a.X * b.X + a.Y * b.Y;
183 | }
184 |
185 | ///
186 | /// Perform the cross product on two vectors. In 2D this produces a scalar.
187 | ///
188 | public static float Cross(Vec2 a, Vec2 b)
189 | {
190 | return a.X * b.Y - a.Y * b.X;
191 | }
192 |
193 | ///
194 | /// Perform the cross product on a vector and a scalar.
195 | /// In 2D this produces a vector.
196 | ///
197 | public static Vec2 Cross(Vec2 a, float s)
198 | {
199 | Vec2 v = new Vec2();
200 | v.Set(s * a.Y, -s * a.X);
201 | return v;
202 | }
203 |
204 | ///
205 | /// Perform the cross product on a scalar and a vector.
206 | /// In 2D this produces a vector.
207 | ///
208 | public static Vec2 Cross(float s, Vec2 a)
209 | {
210 | Vec2 v = new Vec2();
211 | v.Set(-s * a.Y, s * a.X);
212 | return v;
213 | }
214 |
215 | public static float Distance(Vec2 a, Vec2 b)
216 | {
217 | Vec2 c = a - b;
218 | return c.Length();
219 | }
220 |
221 | public static float DistanceSquared(Vec2 a, Vec2 b)
222 | {
223 | Vec2 c = a - b;
224 | return Vec2.Dot(c, c);
225 | }
226 | }
227 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/Vec3.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | //r175
20 |
21 | using System; using System.Numerics;
22 | using System.Collections.Generic;
23 | using System.Text;
24 |
25 | namespace Box2DNet.Common
26 | {
27 | ///
28 | /// A 2D column vector with 3 elements.
29 | ///
30 | public struct Vec3
31 | {
32 | ///
33 | /// Construct using coordinates.
34 | ///
35 | public Vec3(float x, float y, float z) { X = x; Y = y; Z = z; }
36 |
37 | ///
38 | /// Set this vector to all zeros.
39 | ///
40 | public void SetZero() { X = 0.0f; Y = 0.0f; Z = 0.0f; }
41 |
42 | ///
43 | /// Set this vector to some specified coordinates.
44 | ///
45 | public void Set(float x, float y, float z) { X = x; Y = y; Z = z; }
46 |
47 | ///
48 | /// Perform the dot product on two vectors.
49 | ///
50 | public static float Dot(Vec3 a, Vec3 b)
51 | {
52 | return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
53 | }
54 |
55 | ///
56 | /// Perform the cross product on two vectors.
57 | ///
58 | public static Vec3 Cross(Vec3 a, Vec3 b)
59 | {
60 | return new Vec3(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X);
61 | }
62 |
63 | ///
64 | /// Negate this vector.
65 | ///
66 | public static Vec3 operator -(Vec3 v)
67 | {
68 | return new Vec3(-v.X, -v.Y, -v.Z);
69 | }
70 |
71 | ///
72 | /// Add two vectors component-wise.
73 | ///
74 | public static Vec3 operator +(Vec3 v1, Vec3 v2)
75 | {
76 | return new Vec3(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
77 | }
78 |
79 | ///
80 | /// Subtract two vectors component-wise.
81 | ///
82 | public static Vec3 operator -(Vec3 v1, Vec3 v2)
83 | {
84 | return new Vec3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
85 | }
86 |
87 | ///
88 | /// Multiply this vector by a scalar.
89 | ///
90 | public static Vec3 operator *(Vec3 v, float s)
91 | {
92 | return new Vec3(v.X * s, v.Y * s, v.Z * s);
93 | }
94 |
95 | ///
96 | /// Multiply this vector by a scalar.
97 | ///
98 | public static Vec3 operator *(float s, Vec3 v)
99 | {
100 | return new Vec3(v.X * s, v.Y * s, v.Z * s);
101 | }
102 |
103 | public float X, Y, Z;
104 | }
105 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Common/XForm.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 | This software is provided 'as-is', without any express or implied
5 | warranty. In no event will the authors be held liable for any damages
6 | arising from the use of this software.
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 | 1. The origin of this software must not be misrepresented; you must not
11 | claim that you wrote the original software. If you use this software
12 | in a product, an acknowledgment in the product documentation would be
13 | appreciated but is not required.
14 | 2. Altered source versions must be plainly marked as such, and must not be
15 | misrepresented as being the original software.
16 | 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System; using System.Numerics;
20 | using System.Collections.Generic;
21 | using System.Text;
22 |
23 |
24 | namespace Box2DNet.Common
25 | {
26 | ///
27 | /// A transform contains translation and rotation.
28 | /// It is used to represent the position and orientation of rigid frames.
29 | ///
30 | public struct XForm
31 | {
32 | public Vector2 position;
33 | public Mat22 R;
34 |
35 | ///
36 | /// Initialize using a position vector and a rotation matrix.
37 | ///
38 | ///
39 | ///
40 | public XForm(Vector2 p, Mat22 rotation)
41 | {
42 | position = p;
43 | R = rotation;
44 | }
45 |
46 | ///
47 | /// Set this to the identity transform.
48 | ///
49 | public void SetIdentity()
50 | {
51 | position = Vector2.Zero;
52 | R = Mat22.Identity;
53 | }
54 |
55 | /// Set this based on the position and angle.
56 | public void Set(Vector2 p, float angle)
57 | {
58 | position = p;
59 | R = new Mat22(angle);
60 | }
61 |
62 | /// Calculate the angle that the rotation matrix represents.
63 | public float GetAngle()
64 | {
65 | return Math.Atan2(R.Col1.Y, R.Col1.X);
66 | }
67 |
68 | public Vector2 TransformDirection(Vector2 vector)
69 | {
70 | return Math.Mul(R, vector);
71 | }
72 |
73 | public Vector2 InverseTransformDirection(Vector2 vector)
74 | {
75 | return Math.MulT(R, vector);
76 | }
77 |
78 | public Vector2 TransformPoint(Vector2 vector)
79 | {
80 | return position + Math.Mul(R, vector);
81 | }
82 |
83 | public Vector2 InverseTransformPoint(Vector2 vector)
84 | {
85 | return Math.MulT(R, vector - position);
86 | }
87 |
88 | public static XForm Identity { get { return new XForm(Vector2.Zero, Mat22.Identity); } }
89 | }
90 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/ContactManager.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Collision;
23 |
24 | namespace Box2DNet.Dynamics
25 | {
26 | ///
27 | // Delegate of World.
28 | ///
29 | public class ContactManager : PairCallback
30 | {
31 | public World _world;
32 |
33 | // This lets us provide broadphase proxy pair user data for
34 | // contacts that shouldn't exist.
35 | public NullContact _nullContact;
36 |
37 | public bool _destroyImmediate;
38 |
39 | public ContactManager() { }
40 |
41 | // This is a callback from the broadphase when two AABB proxies begin
42 | // to overlap. We create a Contact to manage the narrow phase.
43 | public override object PairAdded(object proxyUserDataA, object proxyUserDataB)
44 | {
45 | Fixture fixtureA = proxyUserDataA as Fixture;
46 | Fixture fixtureB = proxyUserDataB as Fixture;
47 |
48 | Body bodyA = fixtureA.Body;
49 | Body bodyB = fixtureB.Body;
50 |
51 | if (bodyA.IsStatic() && bodyB.IsStatic())
52 | {
53 | return _nullContact;
54 | }
55 |
56 | if (fixtureA.Body == fixtureB.Body)
57 | {
58 | return _nullContact;
59 | }
60 |
61 | if (bodyB.IsConnected(bodyA))
62 | {
63 | return _nullContact;
64 | }
65 |
66 | if (_world._contactFilter != null && _world._contactFilter.ShouldCollide(fixtureA, fixtureB) == false)
67 | {
68 | return _nullContact;
69 | }
70 |
71 | // Call the factory.
72 | Contact c = Contact.Create(fixtureA, fixtureB);
73 |
74 | if (c == null)
75 | {
76 | return _nullContact;
77 | }
78 |
79 | // Contact creation may swap shapes.
80 | fixtureA = c.FixtureA;
81 | fixtureB = c.FixtureB;
82 | bodyA = fixtureA.Body;
83 | bodyB = fixtureB.Body;
84 |
85 | // Insert into the world.
86 | c._prev = null;
87 | c._next = _world._contactList;
88 | if (_world._contactList != null)
89 | {
90 | _world._contactList._prev = c;
91 | }
92 | _world._contactList = c;
93 |
94 | // Connect to island graph.
95 |
96 | // Connect to body 1
97 | c._nodeA.Contact = c;
98 | c._nodeA.Other = bodyB;
99 |
100 | c._nodeA.Prev = null;
101 | c._nodeA.Next = bodyA._contactList;
102 | if (bodyA._contactList != null)
103 | {
104 | bodyA._contactList.Prev = c._nodeA;
105 | }
106 | bodyA._contactList = c._nodeA;
107 |
108 | // Connect to body 2
109 | c._nodeB.Contact = c;
110 | c._nodeB.Other = bodyA;
111 |
112 | c._nodeB.Prev = null;
113 | c._nodeB.Next = bodyB._contactList;
114 | if (bodyB._contactList != null)
115 | {
116 | bodyB._contactList.Prev = c._nodeB;
117 | }
118 | bodyB._contactList = c._nodeB;
119 |
120 | ++_world._contactCount;
121 | return c;
122 | }
123 |
124 | // This is a callback from the broadphase when two AABB proxies cease
125 | // to overlap. We retire the Contact.
126 | public override void PairRemoved(object proxyUserData1, object proxyUserData2, object pairUserData)
127 | {
128 | //B2_NOT_USED(proxyUserData1);
129 | //B2_NOT_USED(proxyUserData2);
130 |
131 | if (pairUserData == null)
132 | {
133 | return;
134 | }
135 |
136 | Contact c = pairUserData as Contact;
137 | if (c == _nullContact)
138 | {
139 | return;
140 | }
141 |
142 | // An attached body is being destroyed, we must destroy this contact
143 | // immediately to avoid orphaned shape pointers.
144 | Destroy(c);
145 | }
146 |
147 | public void Destroy(Contact c)
148 | {
149 | Fixture fixtureA = c.FixtureA;
150 | Fixture fixtureB = c.FixtureB;
151 | Body bodyA = fixtureA.Body;
152 | Body bodyB = fixtureB.Body;
153 |
154 | if (c.Manifold.PointCount > 0)
155 | {
156 | if(_world._contactListener!=null)
157 | _world._contactListener.EndContact(c);
158 | }
159 |
160 | // Remove from the world.
161 | if (c._prev != null)
162 | {
163 | c._prev._next = c._next;
164 | }
165 |
166 | if (c._next != null)
167 | {
168 | c._next._prev = c._prev;
169 | }
170 |
171 | if (c == _world._contactList)
172 | {
173 | _world._contactList = c._next;
174 | }
175 |
176 | // Remove from body 1
177 | if (c._nodeA.Prev != null)
178 | {
179 | c._nodeA.Prev.Next = c._nodeA.Next;
180 | }
181 |
182 | if (c._nodeA.Next != null)
183 | {
184 | c._nodeA.Next.Prev = c._nodeA.Prev;
185 | }
186 |
187 | if (c._nodeA == bodyA._contactList)
188 | {
189 | bodyA._contactList = c._nodeA.Next;
190 | }
191 |
192 | // Remove from body 2
193 | if (c._nodeB.Prev != null)
194 | {
195 | c._nodeB.Prev.Next = c._nodeB.Next;
196 | }
197 |
198 | if (c._nodeB.Next != null)
199 | {
200 | c._nodeB.Next.Prev = c._nodeB.Prev;
201 | }
202 |
203 | if (c._nodeB == bodyB._contactList)
204 | {
205 | bodyB._contactList = c._nodeB.Next;
206 | }
207 |
208 | // Call the factory.
209 | Contact.Destroy(ref c);
210 | --_world._contactCount;
211 | }
212 |
213 | // This is the top level collision call for the time step. Here
214 | // all the narrow phase collision is processed for the world
215 | // contact list.
216 | public void Collide()
217 | {
218 | // Update awake contacts.
219 | for (Contact c = _world._contactList; c != null; c = c.GetNext())
220 | {
221 | Body bodyA = c._fixtureA.Body;
222 | Body bodyB = c._fixtureB.Body;
223 | if (bodyA.IsSleeping() && bodyB.IsSleeping())
224 | {
225 | continue;
226 | }
227 |
228 | c.Update(_world._contactListener);
229 | }
230 | }
231 | }
232 | }
233 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Contacts/CircleContact.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Collision;
23 | using Box2DNet.Common;
24 |
25 | namespace Box2DNet.Dynamics
26 | {
27 | public class CircleContact : Contact
28 | {
29 | public CircleContact(Fixture fixtureA, Fixture fixtureB)
30 | : base(fixtureA, fixtureB)
31 | {
32 | Box2DNetDebug.Assert(fixtureA.ShapeType == ShapeType.CircleShape);
33 | Box2DNetDebug.Assert(fixtureB.ShapeType == ShapeType.CircleShape);
34 | CollideShapeFunction = CollideCircles;
35 | }
36 |
37 | private static void CollideCircles(ref Manifold manifold, Shape shape1, Transform xf1, Shape shape2, Transform xf2)
38 | {
39 | Collision.Collision.CollideCircles(ref manifold, (CircleShape)shape1, xf1, (CircleShape)shape2, xf2);
40 | }
41 |
42 | new public static Contact Create(Fixture fixtureA, Fixture fixtureB)
43 | {
44 | return new CircleContact(fixtureA, fixtureB);
45 | }
46 |
47 | new public static void Destroy(ref Contact contact)
48 | {
49 | contact = null;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Contacts/EdgeAndCircleContact.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Collision;
23 | using Box2DNet.Common;
24 |
25 | namespace Box2DNet.Dynamics
26 | {
27 | public class EdgeAndCircleContact : Contact
28 | {
29 | public EdgeAndCircleContact(Fixture fixtureA, Fixture fixtureB)
30 | : base(fixtureA, fixtureB)
31 | {
32 | Box2DNetDebug.Assert(fixtureA.ShapeType == ShapeType.EdgeShape);
33 | Box2DNetDebug.Assert(fixtureB.ShapeType == ShapeType.CircleShape);
34 | _manifold.PointCount = 0;
35 | _manifold.Points[0].NormalImpulse = 0.0f;
36 | _manifold.Points[0].TangentImpulse = 0.0f;
37 | CollideShapeFunction = CollideEdgeAndCircle;
38 | }
39 |
40 | private static void CollideEdgeAndCircle(ref Manifold manifold, Shape shape1, Transform xf1, Shape shape2, Transform xf2)
41 | {
42 | Collision.Collision.CollideEdgeAndCircle(ref manifold, (EdgeShape)shape1, xf1, (CircleShape)shape2, xf2);
43 | }
44 |
45 | new public static Contact Create(Fixture fixtureA, Fixture fixtureB)
46 | {
47 | return new EdgeAndCircleContact(fixtureA, fixtureB);
48 | }
49 |
50 | new public static void Destroy(ref Contact contact)
51 | {
52 | contact = null;
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Contacts/NullContact.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Collision;
23 | using Box2DNet.Common;
24 |
25 | namespace Box2DNet.Dynamics
26 | {
27 | public class NullContact : Contact
28 | {
29 | public NullContact()
30 | {
31 | CollideShapeFunction = Collide;
32 | }
33 | private static void Collide(ref Manifold manifold, Shape shape1, Transform xf1, Shape shape2, Transform xf2) { }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Contacts/PolyAndCircleContact.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Collision;
23 | using Box2DNet.Common;
24 |
25 | using Transform = Box2DNet.Common.Transform;
26 |
27 | namespace Box2DNet.Dynamics
28 | {
29 | public class PolyAndCircleContact : Contact
30 | {
31 | public PolyAndCircleContact(Fixture fixtureA, Fixture fixtureB)
32 | : base(fixtureA, fixtureB)
33 | {
34 | Box2DNetDebug.Assert(fixtureA.ShapeType == ShapeType.PolygonShape);
35 | Box2DNetDebug.Assert(fixtureB.ShapeType == ShapeType.CircleShape);
36 | CollideShapeFunction = CollidePolygonCircle;
37 | }
38 |
39 | private static void CollidePolygonCircle(ref Manifold manifold, Shape shape1, Transform xf1, Shape shape2, Transform xf2)
40 | {
41 | Collision.Collision.CollidePolygonAndCircle(ref manifold, (PolygonShape)shape1, xf1, (CircleShape)shape2, xf2);
42 | }
43 |
44 | new public static Contact Create(Fixture fixtureA, Fixture fixtureB)
45 | {
46 | return new PolyAndCircleContact(fixtureA, fixtureB);
47 | }
48 |
49 | new public static void Destroy(ref Contact contact)
50 | {
51 | contact = null;
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Contacts/PolyAndEdgeContact.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Collision;
23 | using Box2DNet.Common;
24 |
25 | using Transform = Box2DNet.Common.Transform;
26 |
27 | namespace Box2DNet.Dynamics
28 | {
29 | public class PolyAndEdgeContact : Contact
30 | {
31 | public PolyAndEdgeContact(Fixture fixtureA, Fixture fixtureB)
32 | : base(fixtureA, fixtureB)
33 | {
34 | Box2DNetDebug.Assert(fixtureA.ShapeType == ShapeType.PolygonShape);
35 | Box2DNetDebug.Assert(fixtureB.ShapeType == ShapeType.EdgeShape);
36 | CollideShapeFunction = CollidePolyAndEdgeContact;
37 | }
38 |
39 | private static void CollidePolyAndEdgeContact(ref Manifold manifold, Shape shape1, Transform xf1, Shape shape2, Transform xf2)
40 | {
41 | Collision.Collision.CollidePolyAndEdge(ref manifold, (PolygonShape)shape1, xf1, (EdgeShape)shape2, xf2);
42 | }
43 |
44 | new public static Contact Create(Fixture fixtureA, Fixture fixtureB)
45 | {
46 | return new PolyAndEdgeContact(fixtureA, fixtureB);
47 | }
48 |
49 | new public static void Destroy(ref Contact contact)
50 | {
51 | contact = null;
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Contacts/PolyContact.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using Box2DNet.Collision;
23 | using Box2DNet.Common;
24 |
25 | namespace Box2DNet.Dynamics
26 | {
27 | public class PolygonContact : Contact
28 | {
29 | public PolygonContact(Fixture fixtureA, Fixture fixtureB)
30 | : base(fixtureA, fixtureB)
31 | {
32 | Box2DNetDebug.Assert(fixtureA.ShapeType == ShapeType.PolygonShape);
33 | Box2DNetDebug.Assert(fixtureB.ShapeType == ShapeType.PolygonShape);
34 | CollideShapeFunction = CollidePolygons;
35 | }
36 |
37 | private static void CollidePolygons(ref Manifold manifold, Shape shape1, Transform xf1, Shape shape2, Transform xf2)
38 | {
39 | Collision.Collision.CollidePolygons(ref manifold, (PolygonShape)shape1, xf1, (PolygonShape)shape2, xf2);
40 | }
41 |
42 | new public static Contact Create(Fixture fixtureA, Fixture fixtureB)
43 | {
44 | return new PolygonContact(fixtureA, fixtureB);
45 | }
46 |
47 | new public static void Destroy(ref Contact contact)
48 | {
49 | contact = null;
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Controllers/BuoyancyController.cs:
--------------------------------------------------------------------------------
1 | using System.Numerics;
2 | using Box2DNet.Common;
3 |
4 |
5 | namespace Box2DNet.Dynamics.Controllers
6 | {
7 | ///
8 | /// This class is used to build buoyancy controllers
9 | ///
10 | public class BuoyancyControllerDef
11 | {
12 | /// The outer surface normal
13 | public Vector2 Normal;
14 | /// The height of the fluid surface along the normal
15 | public float Offset;
16 | /// The fluid density
17 | public float Density;
18 | /// Fluid velocity, for drag calculations
19 | public Vector2 Velocity;
20 | /// Linear drag co-efficient
21 | public float LinearDrag;
22 | /// Linear drag co-efficient
23 | public float AngularDrag;
24 | /// If false, bodies are assumed to be uniformly dense, otherwise use the shapes densities
25 | public bool UseDensity; //False by default to prevent a gotcha
26 | /// If true, gravity is taken from the world instead of the gravity parameter.
27 | public bool UseWorldGravity;
28 | /// Gravity vector, if the world's gravity is not used
29 | public Vector2 Gravity;
30 |
31 | public BuoyancyControllerDef()
32 | {
33 | Normal = new Vector2(0, 1);
34 | Offset = 0;
35 | Density = 0;
36 | Velocity = Vector2.Zero;
37 | LinearDrag = 0;
38 | AngularDrag = 0;
39 | UseDensity = false;
40 | UseWorldGravity = true;
41 | Gravity = Vector2.Zero;
42 | }
43 | }
44 |
45 | ///
46 | /// Calculates buoyancy forces for fluids in the form of a half plane.
47 | ///
48 | public class BuoyancyController : Controller
49 | {
50 | /// The outer surface normal
51 | public Vector2 Normal;
52 | /// The height of the fluid surface along the normal
53 | public float Offset;
54 | /// The fluid density
55 | public float Density;
56 | /// Fluid velocity, for drag calculations
57 | public Vector2 Velocity;
58 | /// Linear drag co-efficient
59 | public float LinearDrag;
60 | /// Linear drag co-efficient
61 | public float AngularDrag;
62 | /// If false, bodies are assumed to be uniformly dense, otherwise use the shapes densities
63 | public bool UseDensity; //False by default to prevent a gotcha
64 | /// If true, gravity is taken from the world instead of the gravity parameter.
65 | public bool UseWorldGravity;
66 | /// Gravity vector, if the world's gravity is not used
67 | public Vector2 Gravity;
68 |
69 | public BuoyancyController(BuoyancyControllerDef buoyancyControllerDef)
70 | {
71 | Normal = buoyancyControllerDef.Normal;
72 | Offset = buoyancyControllerDef.Offset;
73 | Density = buoyancyControllerDef.Density;
74 | Velocity = buoyancyControllerDef.Velocity;
75 | LinearDrag = buoyancyControllerDef.LinearDrag;
76 | AngularDrag = buoyancyControllerDef.AngularDrag;
77 | UseDensity = buoyancyControllerDef.UseDensity;
78 | UseWorldGravity = buoyancyControllerDef.UseWorldGravity;
79 | Gravity = buoyancyControllerDef.Gravity;
80 | }
81 |
82 | public override void Step(TimeStep step)
83 | {
84 | //B2_NOT_USED(step);
85 | if (_bodyList == null)
86 | return;
87 |
88 | if (UseWorldGravity)
89 | {
90 | Gravity = _world.Gravity;
91 | }
92 | for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
93 | {
94 | Body body = i.body;
95 | if (body.IsSleeping())
96 | {
97 | //Buoyancy force is just a function of position,
98 | //so unlike most forces, it is safe to ignore sleeping bodes
99 | continue;
100 | }
101 | Vector2 areac = Vector2.Zero;
102 | Vector2 massc = Vector2.Zero;
103 | float area = 0;
104 | float mass = 0;
105 | for (Fixture shape = body.GetFixtureList(); shape != null; shape = shape.Next)
106 | {
107 | Vector2 sc;
108 | float sarea = shape.ComputeSubmergedArea(Normal, Offset, out sc);
109 | area += sarea;
110 | areac.X += sarea * sc.X;
111 | areac.Y += sarea * sc.Y;
112 | float shapeDensity = 0;
113 | if (UseDensity)
114 | {
115 | //TODO: Expose density publicly
116 | shapeDensity = shape.Density;
117 | }
118 | else
119 | {
120 | shapeDensity = 1;
121 | }
122 | mass += sarea * shapeDensity;
123 | massc.X += sarea * sc.X * shapeDensity;
124 | massc.Y += sarea * sc.Y * shapeDensity;
125 | }
126 | areac.X /= area;
127 | areac.Y /= area;
128 | //Vec2 localCentroid = Math.MulT(body.GetTransform(), areac);
129 | massc.X /= mass;
130 | massc.Y /= mass;
131 | if (area < Settings.FLT_EPSILON)
132 | continue;
133 | //Buoyancy
134 | Vector2 buoyancyForce = -Density * area * Gravity;
135 | body.ApplyForce(buoyancyForce, massc);
136 | //Linear drag
137 | Vector2 dragForce = body.GetLinearVelocityFromWorldPoint(areac) - Velocity;
138 | dragForce *= -LinearDrag * area;
139 | body.ApplyForce(dragForce, areac);
140 | //Angular drag
141 | //TODO: Something that makes more physical sense?
142 | body.ApplyTorque(-body.GetInertia() / body.GetMass() * area * body.GetAngularVelocity() * AngularDrag);
143 |
144 | }
145 | }
146 |
147 | public override void Draw(DebugDraw debugDraw)
148 | {
149 | float r = 1000;
150 | Vector2 p1 = Offset * Normal + Normal.CrossScalarPostMultiply(r);
151 | Vector2 p2 = Offset * Normal - Normal.CrossScalarPostMultiply(r);
152 |
153 | Color color = new Color(0, 0, 0.8f);
154 |
155 | debugDraw.DrawSegment(p1, p2, color);
156 | }
157 | }
158 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Controllers/ConstantAccelController.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
3 | *
4 | * This software is provided 'as-is', without any express or implied
5 | * warranty. In no event will the authors be held liable for any damages
6 | * arising from the use of this software.
7 | * Permission is granted to anyone to use this software for any purpose,
8 | * including commercial applications, and to alter it and redistribute it
9 | * freely, subject to the following restrictions:
10 | * 1. The origin of this software must not be misrepresented; you must not
11 | * claim that you wrote the original software. If you use this software
12 | * in a product, an acknowledgment in the product documentation would be
13 | * appreciated but is not required.
14 | * 2. Altered source versions must be plainly marked as such, and must not be
15 | * misrepresented as being the original software.
16 | * 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using Box2DNet.Common;
20 | using System.Numerics;
21 |
22 | namespace Box2DNet.Dynamics.Controllers
23 | {
24 |
25 | /// This class is used to build constant acceleration controllers
26 | public class ConstantAccelControllerDef
27 | {
28 | ///
29 | /// The force to apply
30 | ///
31 | public Vector2 A;
32 | }
33 |
34 | public class ConstantAccelController : Controller
35 | {
36 | ///
37 | /// The force to apply
38 | ///
39 | public Vector2 A;
40 |
41 | public ConstantAccelController(ConstantAccelControllerDef def)
42 | {
43 | A = def.A;
44 | }
45 |
46 | public override void Step(TimeStep step)
47 | {
48 | for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
49 | {
50 | Body body = i.body;
51 | if (body.IsSleeping())
52 | continue;
53 | body.SetLinearVelocity(body.GetLinearVelocity() + step.Dt * A);
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Controllers/ConstantForceController.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
3 | *
4 | * This software is provided 'as-is', without any express or implied
5 | * warranty. In no event will the authors be held liable for any damages
6 | * arising from the use of this software.
7 | * Permission is granted to anyone to use this software for any purpose,
8 | * including commercial applications, and to alter it and redistribute it
9 | * freely, subject to the following restrictions:
10 | * 1. The origin of this software must not be misrepresented; you must not
11 | * claim that you wrote the original software. If you use this software
12 | * in a product, an acknowledgment in the product documentation would be
13 | * appreciated but is not required.
14 | * 2. Altered source versions must be plainly marked as such, and must not be
15 | * misrepresented as being the original software.
16 | * 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using Box2DNet.Common;
20 |
21 | using System.Numerics;
22 | namespace Box2DNet.Dynamics.Controllers
23 | {
24 |
25 | ///
26 | /// This class is used to build constant force controllers
27 | ///
28 | public class ConstantForceControllerDef
29 | {
30 | /// The force to apply
31 | public Vector2 F;
32 | }
33 |
34 | public class ConstantForceController : Controller
35 | {
36 | ///
37 | /// The force to apply
38 | ///
39 | Vector2 F;
40 |
41 | public ConstantForceController(ConstantForceControllerDef def)
42 | {
43 | F = def.F;
44 | }
45 |
46 | public override void Step(TimeStep step)
47 | {
48 | //B2_NOT_USED(step);
49 | for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
50 | {
51 | Body body = i.body;
52 | if (body.IsSleeping())
53 | continue;
54 | body.ApplyForce(F, body.GetWorldCenter());
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Controllers/Controller.cs:
--------------------------------------------------------------------------------
1 | using System; using System.Numerics;
2 |
3 | namespace Box2DNet.Dynamics.Controllers
4 | {
5 | ///
6 | /// A controller edge is used to connect bodies and controllers together
7 | /// in a bipartite graph.
8 | ///
9 | public class ControllerEdge
10 | {
11 | public Controller controller; // provides quick access to other end of this edge.
12 | public Body body; // the body
13 | public ControllerEdge prevBody; // the previous controller edge in the controllers's joint list
14 | public ControllerEdge nextBody; // the next controller edge in the controllers's joint list
15 | public ControllerEdge prevController; // the previous controller edge in the body's joint list
16 | public ControllerEdge nextController; // the next controller edge in the body's joint list
17 | }
18 |
19 | ///
20 | /// Base class for controllers. Controllers are a convience for encapsulating common
21 | /// per-step functionality.
22 | ///
23 | public abstract class Controller : IDisposable
24 | {
25 | internal Controller _prev;
26 | internal Controller _next;
27 |
28 | internal World _world;
29 | protected ControllerEdge _bodyList;
30 | protected int _bodyCount;
31 |
32 | public Controller()
33 | {
34 | _bodyList = null;
35 | _bodyCount = 0;
36 | }
37 |
38 | public Controller(World world)
39 | {
40 | _bodyList = null;
41 | _bodyCount = 0;
42 |
43 | _world = world;
44 | }
45 |
46 | public void Dispose()
47 | {
48 | //Remove attached bodies
49 |
50 | //Previus implementation:
51 | //while (_bodyCount > 0)
52 | // RemoveBody(_bodyList.body);
53 |
54 | Clear();
55 | }
56 |
57 | ///
58 | /// Controllers override this to implement per-step functionality.
59 | ///
60 | public abstract void Step(TimeStep step);
61 |
62 | ///
63 | /// Controllers override this to provide debug drawing.
64 | ///
65 | public virtual void Draw(DebugDraw debugDraw) { }
66 |
67 | ///
68 | /// Adds a body to the controller list.
69 | ///
70 | public void AddBody(Body body)
71 | {
72 | ControllerEdge edge = new ControllerEdge();
73 |
74 | edge.body = body;
75 | edge.controller = this;
76 |
77 | //Add edge to controller list
78 | edge.nextBody = _bodyList;
79 | edge.prevBody = null;
80 | if (_bodyList != null)
81 | _bodyList.prevBody = edge;
82 | _bodyList = edge;
83 | ++_bodyCount;
84 |
85 | //Add edge to body list
86 | edge.nextController = body._controllerList;
87 | edge.prevController = null;
88 | if (body._controllerList != null)
89 | body._controllerList.prevController = edge;
90 | body._controllerList = edge;
91 | }
92 |
93 | ///
94 | /// Removes a body from the controller list.
95 | ///
96 | public void RemoveBody(Body body)
97 | {
98 | //Assert that the controller is not empty
99 | Box2DNetDebug.Assert(_bodyCount > 0);
100 |
101 | //Find the corresponding edge
102 | ControllerEdge edge = _bodyList;
103 | while (edge != null && edge.body != body)
104 | edge = edge.nextBody;
105 |
106 | //Assert that we are removing a body that is currently attached to the controller
107 | Box2DNetDebug.Assert(edge != null);
108 |
109 | //Remove edge from controller list
110 | if (edge.prevBody != null)
111 | edge.prevBody.nextBody = edge.nextBody;
112 | if (edge.nextBody != null)
113 | edge.nextBody.prevBody = edge.prevBody;
114 | if (edge == _bodyList)
115 | _bodyList = edge.nextBody;
116 | --_bodyCount;
117 |
118 | //Remove edge from body list
119 | if (edge.prevController != null)
120 | edge.prevController.nextController = edge.nextController;
121 | if (edge.nextController != null)
122 | edge.nextController.prevController = edge.prevController;
123 | if (edge == body._controllerList)
124 | body._controllerList = edge.nextController;
125 |
126 | //Free the edge
127 | edge = null;
128 | }
129 |
130 | ///
131 | /// Removes all bodies from the controller list.
132 | ///
133 | public void Clear()
134 | {
135 | #warning "Check this"
136 | ControllerEdge current = _bodyList;
137 | while (current != null)
138 | {
139 | ControllerEdge edge = current;
140 |
141 | //Remove edge from controller list
142 | _bodyList = edge.nextBody;
143 |
144 | //Remove edge from body list
145 | if (edge.prevController != null)
146 | edge.prevController.nextController = edge.nextController;
147 | if (edge.nextController != null)
148 | edge.nextController.prevController = edge.prevController;
149 | if (edge == edge.body._controllerList)
150 | edge.body._controllerList = edge.nextController;
151 |
152 | //Free the edge
153 | //m_world->m_blockAllocator.Free(edge, sizeof(b2ControllerEdge));
154 | }
155 |
156 | _bodyCount = 0;
157 | }
158 |
159 | ///
160 | /// Get the next body in the world's body list.
161 | ///
162 | internal Controller GetNext() { return _next; }
163 |
164 | ///
165 | /// Get the parent world of this body.
166 | ///
167 | internal World GetWorld() { return _world; }
168 |
169 | ///
170 | /// Get the attached body list
171 | ///
172 | internal ControllerEdge GetBodyList() { return _bodyList; }
173 | }
174 | }
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Controllers/GravityController.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
3 | *
4 | * This software is provided 'as-is', without any express or implied
5 | * warranty. In no event will the authors be held liable for any damages
6 | * arising from the use of this software.
7 | * Permission is granted to anyone to use this software for any purpose,
8 | * including commercial applications, and to alter it and redistribute it
9 | * freely, subject to the following restrictions:
10 | * 1. The origin of this software must not be misrepresented; you must not
11 | * claim that you wrote the original software. If you use this software
12 | * in a product, an acknowledgment in the product documentation would be
13 | * appreciated but is not required.
14 | * 2. Altered source versions must be plainly marked as such, and must not be
15 | * misrepresented as being the original software.
16 | * 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using System.Numerics;
20 | using Box2DNet.Common;
21 | using Math = Box2DNet.Common.Math;
22 |
23 |
24 |
25 | namespace Box2DNet.Dynamics.Controllers
26 | {
27 | /// This class is used to build gravity controllers
28 | public class GravityControllerDef
29 | {
30 | ///
31 | /// Specifies the strength of the gravitiation force
32 | ///
33 | public float G;
34 |
35 | ///
36 | /// If true, gravity is proportional to r^-2, otherwise r^-1
37 | ///
38 | public bool InvSqr;
39 | }
40 |
41 | public class GravityController : Controller
42 | {
43 | ///
44 | /// Specifies the strength of the gravitiation force
45 | ///
46 | public float G;
47 |
48 | /// If true, gravity is proportional to r^-2, otherwise r^-1
49 | public bool InvSqr;
50 |
51 | public GravityController(GravityControllerDef def)
52 | {
53 | G = def.G;
54 | InvSqr = def.InvSqr;
55 | }
56 |
57 | public override void Step(TimeStep step)
58 | {
59 | //B2_NOT_USED(step);
60 | if (InvSqr)
61 | {
62 | for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
63 | {
64 | Body body1 = i.body;
65 | for (ControllerEdge j = _bodyList; j != i; j = j.nextBody)
66 | {
67 | Body body2 = j.body;
68 | Vector2 d = body2.GetWorldCenter() - body1.GetWorldCenter();
69 | float r2 = d.LengthSquared();
70 | if (r2 < Settings.FLT_EPSILON)
71 | continue;
72 |
73 | Vector2 f = G / r2 / Math.Sqrt(r2) * body1.GetMass() * body2.GetMass() * d;
74 | body1.ApplyForce(f, body1.GetWorldCenter());
75 | body2.ApplyForce(-1.0f * f, body2.GetWorldCenter());
76 | }
77 | }
78 | }
79 | else
80 | {
81 | for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
82 | {
83 | Body body1 = i.body;
84 | for (ControllerEdge j = _bodyList; j != i; j = j.nextBody)
85 | {
86 | Body body2 = j.body;
87 | Vector2 d = body2.GetWorldCenter() - body1.GetWorldCenter();
88 | float r2 = d.LengthSquared();
89 | if (r2 < Settings.FLT_EPSILON)
90 | continue;
91 | Vector2 f = G / r2 * body1.GetMass() * body2.GetMass() * d;
92 | body1.ApplyForce(f, body1.GetWorldCenter());
93 | body2.ApplyForce(-1.0f * f, body2.GetWorldCenter());
94 | }
95 | }
96 | }
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Controllers/TensorDampingController.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
3 | *
4 | * This software is provided 'as-is', without any express or implied
5 | * warranty. In no event will the authors be held liable for any damages
6 | * arising from the use of this software.
7 | * Permission is granted to anyone to use this software for any purpose,
8 | * including commercial applications, and to alter it and redistribute it
9 | * freely, subject to the following restrictions:
10 | * 1. The origin of this software must not be misrepresented; you must not
11 | * claim that you wrote the original software. If you use this software
12 | * in a product, an acknowledgment in the product documentation would be
13 | * appreciated but is not required.
14 | * 2. Altered source versions must be plainly marked as such, and must not be
15 | * misrepresented as being the original software.
16 | * 3. This notice may not be removed or altered from any source distribution.
17 | */
18 |
19 | using Box2DNet.Common;
20 |
21 | using System.Numerics;
22 |
23 | namespace Box2DNet.Dynamics.Controllers
24 | {
25 |
26 | ///
27 | /// This class is used to build tensor damping controllers
28 | ///
29 | public class b2TensorDampingControllerDef
30 | {
31 | /// Tensor to use in damping model
32 | Mat22 T;
33 | /// Set this to a positive number to clamp the maximum amount of damping done.
34 | float maxTimestep;
35 | };
36 |
37 | public class TensorDampingController : Controller
38 | {
39 |
40 | ///
41 | /// Tensor to use in damping model
42 | /// Some examples (matrixes in format (row1; row2) )
43 | ///(-a 0;0 -a) Standard isotropic damping with strength a
44 | ///(0 a;-a 0) Electron in fixed field - a force at right angles to velocity with proportional magnitude
45 | ///(-a 0;0 -b) Differing x and y damping. Useful e.g. for top-down wheels.
46 | ///By the way, tensor in this case just means matrix, don't let the terminology get you down.
47 | ///
48 | Mat22 T;
49 |
50 | ///
51 | /// Set this to a positive number to clamp the maximum amount of damping done.
52 | /// Typically one wants maxTimestep to be 1/(max eigenvalue of T), so that damping will never cause something to reverse direction
53 | ///
54 | float MaxTimestep;
55 |
56 | /// Sets damping independantly along the x and y axes
57 | public void SetAxisAligned(float xDamping, float yDamping)
58 | {
59 | T.Col1.X = -xDamping;
60 | T.Col1.Y = 0;
61 | T.Col2.X = 0;
62 | T.Col2.Y = -yDamping;
63 | if (xDamping > 0 || yDamping > 0)
64 | {
65 | MaxTimestep = 1 / Math.Max(xDamping, yDamping);
66 | }
67 | else
68 | {
69 | MaxTimestep = 0;
70 | }
71 | }
72 |
73 | public override void Step(TimeStep step)
74 | {
75 | float timestep = step.Dt;
76 | if (timestep <= Settings.FLT_EPSILON)
77 | return;
78 | if (timestep > MaxTimestep && MaxTimestep > 0)
79 | timestep = MaxTimestep;
80 | for (ControllerEdge i = _bodyList; i != null; i = i.nextBody)
81 | {
82 | Body body = i.body;
83 | if (body.IsSleeping())
84 | continue;
85 |
86 | Vector2 damping = body.GetWorldVector(T.Multiply(body.GetLocalVector(body.GetLinearVelocity())));
87 | body.SetLinearVelocity(body.GetLinearVelocity() + timestep*damping);
88 | }
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Joints/DistanceJoint.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | // 1-D constrained system
23 | // m (v2 - v1) = lambda
24 | // v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass.
25 | // x2 = x1 + h * v2
26 |
27 | // 1-D mass-damper-spring system
28 | // m (v2 - v1) + h * d * v2 + h * k *
29 |
30 | // C = norm(p2 - p1) - L
31 | // u = (p2 - p1) / norm(p2 - p1)
32 | // Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1))
33 | // J = [-u -cross(r1, u) u cross(r2, u)]
34 | // K = J * invM * JT
35 | // = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2
36 |
37 | using System; using System.Numerics;
38 | using System.Collections.Generic;
39 | using System.Text;
40 |
41 | using Box2DNet.Common;
42 |
43 |
44 | namespace Box2DNet.Dynamics
45 | {
46 | ///
47 | /// Distance joint definition. This requires defining an
48 | /// anchor point on both bodies and the non-zero length of the
49 | /// distance joint. The definition uses local anchor points
50 | /// so that the initial configuration can violate the constraint
51 | /// slightly. This helps when saving and loading a game.
52 | /// @warning Do not use a zero or short length.
53 | ///
54 | public class DistanceJointDef : JointDef
55 | {
56 | public DistanceJointDef()
57 | {
58 | Type = JointType.DistanceJoint;
59 | LocalAnchor1 = Vector2.Zero;
60 | LocalAnchor2 = Vector2.Zero;
61 | Length = 1.0f;
62 | FrequencyHz = 0.0f;
63 | DampingRatio = 0.0f;
64 | }
65 |
66 | ///
67 | /// Initialize the bodies, anchors, and length using the world anchors.
68 | ///
69 | public void Initialize(Body body1, Body body2, Vector2 anchor1, Vector2 anchor2)
70 | {
71 | Body1 = body1;
72 | Body2 = body2;
73 | LocalAnchor1 = body1.GetLocalPoint(anchor1);
74 | LocalAnchor2 = body2.GetLocalPoint(anchor2);
75 | var d = anchor2 - anchor1;
76 | Length = d.Length();
77 | }
78 |
79 | ///
80 | /// The local anchor point relative to body1's origin.
81 | ///
82 | public Vector2 LocalAnchor1;
83 |
84 | ///
85 | /// The local anchor point relative to body2's origin.
86 | ///
87 | public Vector2 LocalAnchor2;
88 |
89 | ///
90 | /// The equilibrium length between the anchor points.
91 | ///
92 | public float Length;
93 |
94 | ///
95 | /// The response speed.
96 | ///
97 | public float FrequencyHz;
98 |
99 | ///
100 | /// The damping ratio. 0 = no damping, 1 = critical damping.
101 | ///
102 | public float DampingRatio;
103 | }
104 |
105 | ///
106 | /// A distance joint constrains two points on two bodies
107 | /// to remain at a fixed distance from each other. You can view
108 | /// this as a massless, rigid rod.
109 | ///
110 | public class DistanceJoint : Joint
111 | {
112 | public Vector2 _localAnchor1;
113 | public Vector2 _localAnchor2;
114 | public Vector2 _u;
115 | public float _frequencyHz;
116 | public float _dampingRatio;
117 | public float _gamma;
118 | public float _bias;
119 | public float _impulse;
120 | public float _mass; // effective mass for the constraint.
121 | public float _length;
122 |
123 | public override Vector2 Anchor1
124 | {
125 | get { return _body1.GetWorldPoint(_localAnchor1);}
126 | }
127 |
128 | public override Vector2 Anchor2
129 | {
130 | get { return _body2.GetWorldPoint(_localAnchor2);}
131 | }
132 |
133 | public override Vector2 GetReactionForce(float inv_dt)
134 | {
135 | return (inv_dt * _impulse) * _u;
136 | }
137 |
138 | public override float GetReactionTorque(float inv_dt)
139 | {
140 | return 0.0f;
141 | }
142 |
143 | public DistanceJoint(DistanceJointDef def)
144 | : base(def)
145 | {
146 | _localAnchor1 = def.LocalAnchor1;
147 | _localAnchor2 = def.LocalAnchor2;
148 | _length = def.Length;
149 | _frequencyHz = def.FrequencyHz;
150 | _dampingRatio = def.DampingRatio;
151 | _impulse = 0.0f;
152 | _gamma = 0.0f;
153 | _bias = 0.0f;
154 | }
155 |
156 | internal override void InitVelocityConstraints(TimeStep step)
157 | {
158 | Body b1 = _body1;
159 | Body b2 = _body2;
160 |
161 | // Compute the effective mass matrix.
162 | Vector2 r1 = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
163 | Vector2 r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());
164 | _u = b2._sweep.C + r2 - b1._sweep.C - r1;
165 |
166 | // Handle singularity.
167 | float length = _u.Length();
168 | if (length > Settings.LinearSlop)
169 | {
170 | _u *= 1.0f / length;
171 | }
172 | else
173 | {
174 | _u = Vector2.Zero;
175 | }
176 |
177 | float cr1u = r1.Cross(_u);
178 | float cr2u = r2.Cross(_u);
179 | float invMass = b1._invMass + b1._invI * cr1u * cr1u + b2._invMass + b2._invI * cr2u * cr2u;
180 | Box2DNetDebug.Assert(invMass > Settings.FLT_EPSILON);
181 | _mass = 1.0f / invMass;
182 |
183 | if (_frequencyHz > 0.0f)
184 | {
185 | float C = length - _length;
186 |
187 | // Frequency
188 | float omega = 2.0f * Settings.Pi * _frequencyHz;
189 |
190 | // Damping coefficient
191 | float d = 2.0f * _mass * _dampingRatio * omega;
192 |
193 | // Spring stiffness
194 | float k = _mass * omega * omega;
195 |
196 | // magic formulas
197 | _gamma = 1.0f / (step.Dt * (d + step.Dt * k));
198 | _bias = C * step.Dt * k * _gamma;
199 |
200 | _mass = 1.0f / (invMass + _gamma);
201 | }
202 |
203 | if (step.WarmStarting)
204 | {
205 | //Scale the inpulse to support a variable timestep.
206 | _impulse *= step.DtRatio;
207 | Vector2 P = _impulse * _u;
208 | b1._linearVelocity -= b1._invMass * P;
209 | b1._angularVelocity -= b1._invI * r1.Cross(P);
210 | b2._linearVelocity += b2._invMass * P;
211 | b2._angularVelocity += b2._invI * r2.Cross(P);
212 | }
213 | else
214 | {
215 | _impulse = 0.0f;
216 | }
217 | }
218 |
219 | internal override bool SolvePositionConstraints(float baumgarte)
220 | {
221 | if (_frequencyHz > 0.0f)
222 | {
223 | //There is no possition correction for soft distace constraint.
224 | return true;
225 | }
226 |
227 | Body b1 = _body1;
228 | Body b2 = _body2;
229 |
230 | Vector2 r1 = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
231 | Vector2 r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());
232 |
233 | Vector2 d = b2._sweep.C + r2 - b1._sweep.C - r1;
234 |
235 | var length = d.Length();
236 | d.Normalize();
237 | var C = length - _length;
238 | C = Box2DNet.Common.Math.Clamp(C, -Settings.MaxLinearCorrection, Settings.MaxLinearCorrection);
239 |
240 | var impulse = -_mass * C;
241 | _u = d;
242 | var P = impulse * _u;
243 |
244 | b1._sweep.C -= b1._invMass * P;
245 | b1._sweep.A -= b1._invI * r1.Cross(P);
246 | b2._sweep.C += b2._invMass * P;
247 | b2._sweep.A += b2._invI * r2.Cross(P);
248 |
249 | b1.SynchronizeTransform();
250 | b2.SynchronizeTransform();
251 |
252 | return System.Math.Abs(C) < Settings.LinearSlop;
253 | }
254 |
255 | internal override void SolveVelocityConstraints(TimeStep step)
256 | {
257 | //B2_NOT_USED(step);
258 |
259 | var b1 = _body1;
260 | var b2 = _body2;
261 |
262 | var r1 = b1.GetTransform().TransformDirection( _localAnchor1 - b1.GetLocalCenter());
263 | var r2 = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());
264 |
265 | // Cdot = dot(u, v + cross(w, r))
266 | var v1 = b1._linearVelocity + r1.CrossScalarPreMultiply(b1._angularVelocity);
267 | var v2 = b2._linearVelocity + r2.CrossScalarPreMultiply(b2._angularVelocity);
268 | var cdot = Vector2.Dot(_u, v2 - v1);
269 | var impulse = -_mass * (cdot + _bias + _gamma * _impulse);
270 | _impulse += impulse;
271 |
272 | var p = impulse * _u;
273 | b1._linearVelocity -= b1._invMass * p;
274 | b1._angularVelocity -= b1._invI * r1.Cross(p);
275 | b2._linearVelocity += b2._invMass * p;
276 | b2._angularVelocity += b2._invI * r2.Cross(p);
277 | }
278 | }
279 | }
280 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Joints/GearJoint.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | // Gear Joint:
23 | // C0 = (coordinate1 + ratio * coordinate2)_initial
24 | // C = C0 - (cordinate1 + ratio * coordinate2) = 0
25 | // Cdot = -(Cdot1 + ratio * Cdot2)
26 | // J = -[J1 ratio * J2]
27 | // K = J * invM * JT
28 | // = J1 * invM1 * J1T + ratio * ratio * J2 * invM2 * J2T
29 | //
30 | // Revolute:
31 | // coordinate = rotation
32 | // Cdot = angularVelocity
33 | // J = [0 0 1]
34 | // K = J * invM * JT = invI
35 | //
36 | // Prismatic:
37 | // coordinate = dot(p - pg, ug)
38 | // Cdot = dot(v + cross(w, r), ug)
39 | // J = [ug cross(r, ug)]
40 | // K = J * invM * JT = invMass + invI * cross(r, ug)^2
41 |
42 | using System; using System.Numerics;
43 | using System.Collections.Generic;
44 | using System.Text;
45 |
46 | using Box2DNet.Common;
47 |
48 |
49 | namespace Box2DNet.Dynamics
50 | {
51 | ///
52 | /// Gear joint definition. This definition requires two existing
53 | /// revolute or prismatic joints (any combination will work).
54 | /// The provided joints must attach a dynamic body to a static body.
55 | ///
56 | public class GearJointDef : JointDef
57 | {
58 | public GearJointDef()
59 | {
60 | Type = JointType.GearJoint;
61 | Joint1 = null;
62 | Joint2 = null;
63 | Ratio = 1.0f;
64 | }
65 |
66 | ///
67 | /// The first revolute/prismatic joint attached to the gear joint.
68 | ///
69 | public Joint Joint1;
70 |
71 | ///
72 | /// The second revolute/prismatic joint attached to the gear joint.
73 | ///
74 | public Joint Joint2;
75 |
76 | ///
77 | /// The gear ratio.
78 | /// @see GearJoint for explanation.
79 | ///
80 | public float Ratio;
81 | }
82 |
83 | ///
84 | /// A gear joint is used to connect two joints together. Either joint
85 | /// can be a revolute or prismatic joint. You specify a gear ratio
86 | /// to bind the motions together:
87 | /// coordinate1 + ratio * coordinate2 = constant
88 | /// The ratio can be negative or positive. If one joint is a revolute joint
89 | /// and the other joint is a prismatic joint, then the ratio will have units
90 | /// of length or units of 1/length.
91 | /// @warning The revolute and prismatic joints must be attached to
92 | /// fixed bodies (which must be body1 on those joints).
93 | ///
94 | public class GearJoint : Joint
95 | {
96 | public Body _ground1;
97 | public Body _ground2;
98 |
99 | // One of these is NULL.
100 | public RevoluteJoint _revolute1;
101 | public PrismaticJoint _prismatic1;
102 |
103 | // One of these is NULL.
104 | public RevoluteJoint _revolute2;
105 | public PrismaticJoint _prismatic2;
106 |
107 | public Vector2 _groundAnchor1;
108 | public Vector2 _groundAnchor2;
109 |
110 | public Vector2 _localAnchor1;
111 | public Vector2 _localAnchor2;
112 |
113 | public Jacobian _J;
114 |
115 | public float _constant;
116 | public float _ratio;
117 |
118 | // Effective mass
119 | public float _mass;
120 |
121 | // Impulse for accumulation/warm starting.
122 | public float _impulse;
123 |
124 | public override Vector2 Anchor1 { get { return _body1.GetWorldPoint(_localAnchor1); } }
125 | public override Vector2 Anchor2 { get { return _body2.GetWorldPoint(_localAnchor2); } }
126 |
127 | public override Vector2 GetReactionForce(float inv_dt)
128 | {
129 | // TODO_ERIN not tested
130 | Vector2 P = _impulse * _J.Linear2;
131 | return inv_dt * P;
132 | }
133 |
134 | public override float GetReactionTorque(float inv_dt)
135 | {
136 | // TODO_ERIN not tested
137 | Vector2 r = _body2.GetTransform().TransformDirection(_localAnchor2 - _body2.GetLocalCenter());
138 | Vector2 P = _impulse * _J.Linear2;
139 | float L = _impulse * _J.Angular2 - r.Cross(P);
140 | return inv_dt * L;
141 | }
142 |
143 | ///
144 | /// Get the gear ratio.
145 | ///
146 | public float Ratio { get { return _ratio; } }
147 |
148 | public GearJoint(GearJointDef def)
149 | : base(def)
150 | {
151 | JointType type1 = def.Joint1.GetType();
152 | JointType type2 = def.Joint2.GetType();
153 |
154 | Box2DNetDebug.Assert(type1 == JointType.RevoluteJoint || type1 == JointType.PrismaticJoint);
155 | Box2DNetDebug.Assert(type2 == JointType.RevoluteJoint || type2 == JointType.PrismaticJoint);
156 | Box2DNetDebug.Assert(def.Joint1.GetBody1().IsStatic());
157 | Box2DNetDebug.Assert(def.Joint2.GetBody1().IsStatic());
158 |
159 | _revolute1 = null;
160 | _prismatic1 = null;
161 | _revolute2 = null;
162 | _prismatic2 = null;
163 |
164 | float coordinate1, coordinate2;
165 |
166 | _ground1 = def.Joint1.GetBody1();
167 | _body1 = def.Joint1.GetBody2();
168 | if (type1 == JointType.RevoluteJoint)
169 | {
170 | _revolute1 = (RevoluteJoint)def.Joint1;
171 | _groundAnchor1 = _revolute1._localAnchor1;
172 | _localAnchor1 = _revolute1._localAnchor2;
173 | coordinate1 = _revolute1.JointAngle;
174 | }
175 | else
176 | {
177 | _prismatic1 = (PrismaticJoint)def.Joint1;
178 | _groundAnchor1 = _prismatic1._localAnchor1;
179 | _localAnchor1 = _prismatic1._localAnchor2;
180 | coordinate1 = _prismatic1.JointTranslation;
181 | }
182 |
183 | _ground2 = def.Joint2.GetBody1();
184 | _body2 = def.Joint2.GetBody2();
185 | if (type2 == JointType.RevoluteJoint)
186 | {
187 | _revolute2 = (RevoluteJoint)def.Joint2;
188 | _groundAnchor2 = _revolute2._localAnchor1;
189 | _localAnchor2 = _revolute2._localAnchor2;
190 | coordinate2 = _revolute2.JointAngle;
191 | }
192 | else
193 | {
194 | _prismatic2 = (PrismaticJoint)def.Joint2;
195 | _groundAnchor2 = _prismatic2._localAnchor1;
196 | _localAnchor2 = _prismatic2._localAnchor2;
197 | coordinate2 = _prismatic2.JointTranslation;
198 | }
199 |
200 | _ratio = def.Ratio;
201 |
202 | _constant = coordinate1 + _ratio * coordinate2;
203 |
204 | _impulse = 0.0f;
205 | }
206 |
207 | internal override void InitVelocityConstraints(TimeStep step)
208 | {
209 | Body g1 = _ground1;
210 | Body g2 = _ground2;
211 | Body b1 = _body1;
212 | Body b2 = _body2;
213 |
214 | float K = 0.0f;
215 | _J.SetZero();
216 |
217 | if (_revolute1!=null)
218 | {
219 | _J.Angular1 = -1.0f;
220 | K += b1._invI;
221 | }
222 | else
223 | {
224 | Vector2 ug = g1.GetTransform().TransformDirection(_prismatic1._localXAxis1);
225 | Vector2 r = b1.GetTransform().TransformDirection(_localAnchor1 - b1.GetLocalCenter());
226 | float crug = r.Cross(ug);
227 | _J.Linear1 = -ug;
228 | _J.Angular1 = -crug;
229 | K += b1._invMass + b1._invI * crug * crug;
230 | }
231 |
232 | if (_revolute2!=null)
233 | {
234 | _J.Angular2 = -_ratio;
235 | K += _ratio * _ratio * b2._invI;
236 | }
237 | else
238 | {
239 | Vector2 ug = g2.GetTransform().TransformDirection(_prismatic2._localXAxis1);
240 | Vector2 r = b2.GetTransform().TransformDirection(_localAnchor2 - b2.GetLocalCenter());
241 | float crug = r.Cross(ug);
242 | _J.Linear2 = -_ratio * ug;
243 | _J.Angular2 = -_ratio * crug;
244 | K += _ratio * _ratio * (b2._invMass + b2._invI * crug * crug);
245 | }
246 |
247 | // Compute effective mass.
248 | Box2DNetDebug.Assert(K > 0.0f);
249 | _mass = 1.0f / K;
250 |
251 | if (step.WarmStarting)
252 | {
253 | // Warm starting.
254 | b1._linearVelocity += b1._invMass * _impulse * _J.Linear1;
255 | b1._angularVelocity += b1._invI * _impulse * _J.Angular1;
256 | b2._linearVelocity += b2._invMass * _impulse * _J.Linear2;
257 | b2._angularVelocity += b2._invI * _impulse * _J.Angular2;
258 | }
259 | else
260 | {
261 | _impulse = 0.0f;
262 | }
263 | }
264 |
265 | internal override void SolveVelocityConstraints(TimeStep step)
266 | {
267 | Body b1 = _body1;
268 | Body b2 = _body2;
269 |
270 | float Cdot = _J.Compute(b1._linearVelocity, b1._angularVelocity, b2._linearVelocity, b2._angularVelocity);
271 |
272 | float impulse = _mass * (-Cdot);
273 | _impulse += impulse;
274 |
275 | b1._linearVelocity += b1._invMass * impulse * _J.Linear1;
276 | b1._angularVelocity += b1._invI * impulse * _J.Angular1;
277 | b2._linearVelocity += b2._invMass * impulse * _J.Linear2;
278 | b2._angularVelocity += b2._invI * impulse * _J.Angular2;
279 | }
280 |
281 | internal override bool SolvePositionConstraints(float baumgarte)
282 | {
283 | float linearError = 0.0f;
284 |
285 | Body b1 = _body1;
286 | Body b2 = _body2;
287 |
288 | float coordinate1, coordinate2;
289 | if (_revolute1 != null)
290 | {
291 | coordinate1 = _revolute1.JointAngle;
292 | }
293 | else
294 | {
295 | coordinate1 = _prismatic1.JointTranslation;
296 | }
297 |
298 | if (_revolute2 != null)
299 | {
300 | coordinate2 = _revolute2.JointAngle;
301 | }
302 | else
303 | {
304 | coordinate2 = _prismatic2.JointTranslation;
305 | }
306 |
307 | float C = _constant - (coordinate1 + _ratio * coordinate2);
308 |
309 | float impulse = _mass * (-C);
310 |
311 | b1._sweep.C += b1._invMass * impulse * _J.Linear1;
312 | b1._sweep.A += b1._invI * impulse * _J.Angular1;
313 | b2._sweep.C += b2._invMass * impulse * _J.Linear2;
314 | b2._sweep.A += b2._invI * impulse * _J.Angular2;
315 |
316 | b1.SynchronizeTransform();
317 | b2.SynchronizeTransform();
318 |
319 | //TODO_ERIN not implemented
320 | return linearError < Settings.LinearSlop;
321 | }
322 | }
323 | }
324 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Joints/Joint.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using System; using System.Numerics;
23 | using System.Collections.Generic;
24 | using System.Text;
25 |
26 | using Box2DNet.Common;
27 |
28 | using Transform = Box2DNet.Common.Transform;
29 |
30 | namespace Box2DNet.Dynamics
31 | {
32 | public enum JointType
33 | {
34 | UnknownJoint,
35 | RevoluteJoint,
36 | PrismaticJoint,
37 | DistanceJoint,
38 | PulleyJoint,
39 | MouseJoint,
40 | GearJoint,
41 | LineJoint
42 | }
43 |
44 | public enum LimitState
45 | {
46 | InactiveLimit,
47 | AtLowerLimit,
48 | AtUpperLimit,
49 | EqualLimits
50 | }
51 |
52 | public struct Jacobian
53 | {
54 | public Vector2 Linear1;
55 | public float Angular1;
56 | public Vector2 Linear2;
57 | public float Angular2;
58 |
59 | public void SetZero()
60 | {
61 | Linear1 = Vector2.Zero;
62 | Angular1 = 0.0f;
63 | Linear2 = Vector2.Zero;
64 | Angular2 = 0.0f;
65 | }
66 |
67 | public void Set(Vector2 x1, float a1, Vector2 x2, float a2)
68 | {
69 | Linear1 = x1; Angular1 = a1;
70 | Linear2 = x2; Angular2 = a2;
71 | }
72 |
73 | public float Compute(Vector2 x1, float a1, Vector2 x2, float a2)
74 | {
75 | return Vector2.Dot(Linear1, x1) + Angular1 * a1 + Vector2.Dot(Linear2, x2) + Angular2 * a2;
76 | }
77 | }
78 |
79 | #warning "CAS"
80 | ///
81 | /// A joint edge is used to connect bodies and joints together
82 | /// in a joint graph where each body is a node and each joint
83 | /// is an edge. A joint edge belongs to a doubly linked list
84 | /// maintained in each attached body. Each joint has two joint
85 | /// nodes, one for each attached body.
86 | ///
87 | public class JointEdge
88 | {
89 | ///
90 | /// Provides quick access to the other body attached.
91 | ///
92 | public Body Other;
93 |
94 | ///
95 | /// The joint.
96 | ///
97 | public Joint Joint;
98 |
99 | ///
100 | /// The previous joint edge in the body's joint list.
101 | ///
102 | public JointEdge Prev;
103 |
104 | ///
105 | /// The next joint edge in the body's joint list.
106 | ///
107 | public JointEdge Next;
108 | }
109 |
110 | #warning "CAS"
111 | ///
112 | /// Joint definitions are used to construct joints.
113 | ///
114 | public class JointDef
115 | {
116 | public JointDef()
117 | {
118 | Type = JointType.UnknownJoint;
119 | UserData = null;
120 | Body1 = null;
121 | Body2 = null;
122 | CollideConnected = false;
123 | }
124 |
125 | ///
126 | /// The joint type is set automatically for concrete joint types.
127 | ///
128 | public JointType Type;
129 |
130 | ///
131 | /// Use this to attach application specific data to your joints.
132 | ///
133 | public object UserData;
134 |
135 | ///
136 | /// The first attached body.
137 | ///
138 | public Body Body1;
139 |
140 | ///
141 | /// The second attached body.
142 | ///
143 | public Body Body2;
144 |
145 | ///
146 | /// Set this flag to true if the attached bodies should collide.
147 | ///
148 | public bool CollideConnected;
149 | }
150 |
151 | ///
152 | /// The base joint class. Joints are used to constraint two bodies together in
153 | /// various fashions. Some joints also feature limits and motors.
154 | ///
155 | public abstract class Joint
156 | {
157 | protected JointType _type;
158 | internal Joint _prev;
159 | internal Joint _next;
160 | internal JointEdge _node1 = new JointEdge();
161 | internal JointEdge _node2 = new JointEdge();
162 | internal Body _body1;
163 | internal Body _body2;
164 |
165 | internal bool _islandFlag;
166 | internal bool _collideConnected;
167 |
168 | protected object _userData;
169 |
170 | // Cache here per time step to reduce cache misses.
171 | protected Vector2 _localCenter1, _localCenter2;
172 | protected float _invMass1, _invI1;
173 | protected float _invMass2, _invI2;
174 |
175 | ///
176 | /// Get the type of the concrete joint.
177 | ///
178 | public new JointType GetType()
179 | {
180 | return _type;
181 | }
182 |
183 | ///
184 | /// Get the first body attached to this joint.
185 | ///
186 | ///
187 | public Body GetBody1()
188 | {
189 | return _body1;
190 | }
191 |
192 | ///
193 | /// Get the second body attached to this joint.
194 | ///
195 | ///
196 | public Body GetBody2()
197 | {
198 | return _body2;
199 | }
200 |
201 | ///
202 | /// Get the anchor point on body1 in world coordinates.
203 | ///
204 | ///
205 | public abstract Vector2 Anchor1 { get; }
206 |
207 | ///
208 | /// Get the anchor point on body2 in world coordinates.
209 | ///
210 | ///
211 | public abstract Vector2 Anchor2 { get; }
212 |
213 | ///
214 | /// Get the reaction force on body2 at the joint anchor.
215 | ///
216 | public abstract Vector2 GetReactionForce(float inv_dt);
217 |
218 | ///
219 | /// Get the reaction torque on body2.
220 | ///
221 | public abstract float GetReactionTorque(float inv_dt);
222 |
223 | ///
224 | /// Get the next joint the world joint list.
225 | ///
226 | ///
227 | public Joint GetNext()
228 | {
229 | return _next;
230 | }
231 |
232 | ///
233 | /// Get/Set the user data pointer.
234 | ///
235 | ///
236 | public object UserData
237 | {
238 | get { return _userData; }
239 | set { _userData = value; }
240 | }
241 |
242 | protected Joint(JointDef def)
243 | {
244 | _type = def.Type;
245 | _prev = null;
246 | _next = null;
247 | _body1 = def.Body1;
248 | _body2 = def.Body2;
249 | _collideConnected = def.CollideConnected;
250 | _islandFlag = false;
251 | _userData = def.UserData;
252 | }
253 |
254 | internal static Joint Create(JointDef def)
255 | {
256 | Joint joint = null;
257 |
258 | switch (def.Type)
259 | {
260 | case JointType.DistanceJoint:
261 | {
262 | joint = new DistanceJoint((DistanceJointDef)def);
263 | }
264 | break;
265 | case JointType.MouseJoint:
266 | {
267 | joint = new MouseJoint((MouseJointDef)def);
268 | }
269 | break;
270 | case JointType.PrismaticJoint:
271 | {
272 | joint = new PrismaticJoint((PrismaticJointDef)def);
273 | }
274 | break;
275 | case JointType.RevoluteJoint:
276 | {
277 | joint = new RevoluteJoint((RevoluteJointDef)def);
278 | }
279 | break;
280 | case JointType.PulleyJoint:
281 | {
282 | joint = new PulleyJoint((PulleyJointDef)def);
283 | }
284 | break;
285 | case JointType.GearJoint:
286 | {
287 | joint = new GearJoint((GearJointDef)def);
288 | }
289 | break;
290 | case JointType.LineJoint:
291 | {
292 | joint = new LineJoint((LineJointDef)def);
293 | }
294 | break;
295 | default:
296 | Box2DNetDebug.Assert(false);
297 | break;
298 | }
299 |
300 | return joint;
301 | }
302 |
303 | internal static void Destroy(Joint joint)
304 | {
305 | joint = null;
306 | }
307 |
308 | internal abstract void InitVelocityConstraints(TimeStep step);
309 | internal abstract void SolveVelocityConstraints(TimeStep step);
310 |
311 | // This returns true if the position errors are within tolerance.
312 | internal abstract bool SolvePositionConstraints(float baumgarte);
313 |
314 | internal void ComputeTransform(ref Transform xf, Vector2 center, Vector2 localCenter, float angle)
315 | {
316 | xf.rotation = Box2DNet.Common.Math.AngleToRotation(angle);
317 | //xf.R = new Mat22(angle);
318 | xf.position = center - xf.TransformDirection(localCenter);
319 | }
320 | }
321 | }
322 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/Joints/MouseJoint.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2018 codeyu https://github.com/codeyu/Box2DNet
3 | Box2D original C++ version Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | // p = attached point, m = mouse point
23 | // C = p - m
24 | // Cdot = v
25 | // = v + cross(w, r)
26 | // J = [I r_skew]
27 | // Identity used:
28 | // w k % (rx i + ry j) = w * (-ry i + rx j)
29 |
30 | using System; using System.Numerics;
31 | using System.Collections.Generic;
32 | using System.Text;
33 |
34 | using Box2DNet.Common;
35 |
36 |
37 | namespace Box2DNet.Dynamics
38 | {
39 | ///
40 | /// Mouse joint definition. This requires a world target point,
41 | /// tuning parameters, and the time step.
42 | ///
43 | public class MouseJointDef : JointDef
44 | {
45 | public MouseJointDef()
46 | {
47 | Type = JointType.MouseJoint;
48 | Target = Vector2.Zero;
49 | MaxForce = 0.0f;
50 | FrequencyHz = 5.0f;
51 | DampingRatio = 0.7f;
52 | }
53 |
54 | ///
55 | /// The initial world target point. This is assumed
56 | /// to coincide with the body anchor initially.
57 | ///
58 | public Vector2 Target;
59 |
60 | ///
61 | /// The maximum constraint force that can be exerted
62 | /// to move the candidate body. Usually you will express
63 | /// as some multiple of the weight (multiplier * mass * gravity).
64 | ///
65 | public float MaxForce;
66 |
67 | ///
68 | /// The response speed.
69 | ///
70 | public float FrequencyHz;
71 |
72 | ///
73 | /// The damping ratio. 0 = no damping, 1 = critical damping.
74 | ///
75 | public float DampingRatio;
76 | }
77 |
78 | ///
79 | /// A mouse joint is used to make a point on a body track a
80 | /// specified world point. This a soft constraint with a maximum
81 | /// force. This allows the constraint to stretch and without
82 | /// applying huge forces.
83 | ///
84 | public class MouseJoint : Joint
85 | {
86 | public Vector2 _localAnchor;
87 | public Vector2 _target;
88 | public Vector2 _impulse;
89 |
90 | public Mat22 _mass; // effective mass for point-to-point constraint.
91 | public Vector2 _C; // position error
92 | public float _maxForce;
93 | public float _frequencyHz;
94 | public float _dampingRatio;
95 | public float _beta;
96 | public float _gamma;
97 |
98 | public override Vector2 Anchor1
99 | {
100 | get { return _target; }
101 | }
102 |
103 | public override Vector2 Anchor2
104 | {
105 | get { return _body2.GetWorldPoint(_localAnchor); }
106 | }
107 |
108 | public override Vector2 GetReactionForce(float inv_dt)
109 | {
110 | return inv_dt * _impulse;
111 | }
112 |
113 | public override float GetReactionTorque(float inv_dt)
114 | {
115 | return inv_dt * 0.0f;
116 | }
117 |
118 | ///
119 | /// Use this to update the target point.
120 | ///
121 | public void SetTarget(Vector2 target)
122 | {
123 | if (_body2.IsSleeping())
124 | {
125 | _body2.WakeUp();
126 | }
127 | _target = target;
128 | }
129 |
130 | public MouseJoint(MouseJointDef def)
131 | : base(def)
132 | {
133 | _target = def.Target;
134 | _localAnchor = _body2.GetTransform().InverseTransformPoint(_target);
135 |
136 | _maxForce = def.MaxForce;
137 | _impulse = Vector2.Zero;
138 |
139 | _frequencyHz = def.FrequencyHz;
140 | _dampingRatio = def.DampingRatio;
141 |
142 | _beta = 0.0f;
143 | _gamma = 0.0f;
144 | }
145 |
146 | internal override void InitVelocityConstraints(TimeStep step)
147 | {
148 | Body b = _body2;
149 |
150 | float mass = b.GetMass();
151 |
152 | // Frequency
153 | float omega = 2.0f * Settings.Pi * _frequencyHz;
154 |
155 | // Damping coefficient
156 | float d = 2.0f * mass * _dampingRatio * omega;
157 |
158 | // Spring stiffness
159 | float k = mass * (omega * omega);
160 |
161 | // magic formulas
162 | // gamma has units of inverse mass.
163 | // beta has units of inverse time.
164 | Box2DNetDebug.Assert(d + step.Dt * k > Settings.FLT_EPSILON);
165 | _gamma = 1.0f / (step.Dt * (d + step.Dt * k));
166 | _beta = step.Dt * k * _gamma;
167 |
168 | // Compute the effective mass matrix.
169 | Vector2 r = b.GetTransform().TransformDirection(_localAnchor - b.GetLocalCenter());
170 |
171 | // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)]
172 | // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y]
173 | // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x]
174 | float invMass = b._invMass;
175 | float invI = b._invI;
176 |
177 | Mat22 K1 = new Mat22();
178 | K1.Col1.X = invMass; K1.Col2.X = 0.0f;
179 | K1.Col1.Y = 0.0f; K1.Col2.Y = invMass;
180 |
181 | Mat22 K2 = new Mat22();
182 | K2.Col1.X = invI * r.Y * r.Y; K2.Col2.X = -invI * r.X * r.Y;
183 | K2.Col1.Y = -invI * r.X * r.Y; K2.Col2.Y = invI * r.X * r.X;
184 |
185 | Mat22 K = K1 + K2;
186 | K.Col1.X += _gamma;
187 | K.Col2.Y += _gamma;
188 |
189 | _mass = K.GetInverse();
190 |
191 | _C = b._sweep.C + r - _target;
192 |
193 | // Cheat with some damping
194 | b._angularVelocity *= 0.98f;
195 |
196 | // Warm starting.
197 | _impulse *= step.DtRatio;
198 | b._linearVelocity += invMass * _impulse;
199 | b._angularVelocity += invI * r.Cross(_impulse);
200 | }
201 |
202 | internal override void SolveVelocityConstraints(TimeStep step)
203 | {
204 | Body b = _body2;
205 |
206 | Vector2 r = b.GetTransform().TransformDirection(_localAnchor - b.GetLocalCenter());
207 |
208 | // Cdot = v + cross(w, r)
209 | Vector2 Cdot = b._linearVelocity + r.CrossScalarPreMultiply(b._angularVelocity);
210 | Vector2 impulse = _mass.Multiply(-(Cdot + _beta * _C + _gamma * _impulse));
211 |
212 | Vector2 oldImpulse = _impulse;
213 | _impulse += impulse;
214 | float maxImpulse = step.Dt * _maxForce;
215 | if (_impulse.LengthSquared() > maxImpulse * maxImpulse)
216 | {
217 | _impulse *= maxImpulse / _impulse.Length();
218 | }
219 | impulse = _impulse - oldImpulse;
220 |
221 | b._linearVelocity += b._invMass * impulse;
222 | b._angularVelocity += b._invI * r.Cross(impulse);
223 | }
224 |
225 | internal override bool SolvePositionConstraints(float baumgarte)
226 | {
227 | return true;
228 | }
229 | }
230 | }
231 |
--------------------------------------------------------------------------------
/src/Box2DNet/Dynamics/WorldCallbacks.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Box2DNet Copyright (c) 2009 Ihar Kalasouski http://code.google.com/p/box2dx
3 | Box2D original C++ version Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
4 |
5 | This software is provided 'as-is', without any express or implied
6 | warranty. In no event will the authors be held liable for any damages
7 | arising from the use of this software.
8 |
9 | Permission is granted to anyone to use this software for any purpose,
10 | including commercial applications, and to alter it and redistribute it
11 | freely, subject to the following restrictions:
12 |
13 | 1. The origin of this software must not be misrepresented; you must not
14 | claim that you wrote the original software. If you use this software
15 | in a product, an acknowledgment in the product documentation would be
16 | appreciated but is not required.
17 | 2. Altered source versions must be plainly marked as such, and must not be
18 | misrepresented as being the original software.
19 | 3. This notice may not be removed or altered from any source distribution.
20 | */
21 |
22 | using System;
23 | using System.Numerics;
24 | using Box2DNet.Common;
25 | using Box2DNet.Collision;
26 |
27 |
28 | using Transform = Box2DNet.Common.Transform;
29 |
30 | namespace Box2DNet.Dynamics
31 | {
32 | ///
33 | /// Joints and shapes are destroyed when their associated
34 | /// body is destroyed. Implement this listener so that you
35 | /// may nullify references to these joints and shapes.
36 | ///
37 | public abstract class DestructionListener
38 | {
39 | ///
40 | /// Called when any joint is about to be destroyed due
41 | /// to the destruction of one of its attached bodies.
42 | ///
43 | public abstract void SayGoodbye(Joint joint);
44 |
45 | ///
46 | /// Called when any shape is about to be destroyed due
47 | /// to the destruction of its parent body.
48 | ///
49 | public abstract void SayGoodbye(Fixture fixture);
50 | }
51 |
52 | ///
53 | /// This is called when a body's shape passes outside of the world boundary.
54 | ///
55 | public abstract class BoundaryListener
56 | {
57 | ///
58 | /// This is called for each body that leaves the world boundary.
59 | /// @warning you can't modify the world inside this callback.
60 | ///
61 | public abstract void Violation(Body body);
62 | }
63 |
64 | ///
65 | /// Implement this class to provide collision filtering. In other words, you can implement
66 | /// this class if you want finer control over contact creation.
67 | ///
68 | public class ContactFilter
69 | {
70 | ///
71 | /// Return true if contact calculations should be performed between these two shapes.
72 | /// If you implement your own collision filter you may want to build from this implementation.
73 | /// @warning for performance reasons this is only called when the AABBs begin to overlap.
74 | ///
75 | public virtual bool ShouldCollide(Fixture fixtureA, Fixture fixtureB)
76 | {
77 | FilterData filterA = fixtureA.Filter;
78 | FilterData filterB = fixtureB.Filter;
79 |
80 | if (filterA.GroupIndex == filterB.GroupIndex && filterA.GroupIndex != 0)
81 | {
82 | return filterA.GroupIndex > 0;
83 | }
84 |
85 | bool collide = (filterA.MaskBits & filterB.CategoryBits) != 0 && (filterA.CategoryBits & filterB.MaskBits) != 0;
86 | return collide;
87 | }
88 |
89 | ///
90 | /// Return true if the given shape should be considered for ray intersection.
91 | ///
92 | public bool RayCollide(object userData, Fixture fixture)
93 | {
94 | //By default, cast userData as a shape, and then collide if the shapes would collide
95 | if (userData == null)
96 | {
97 | return true;
98 | }
99 |
100 | return ShouldCollide((Fixture)userData, fixture);
101 | }
102 | }
103 |
104 | /// Contact impulses for reporting. Impulses are used instead of forces because
105 | /// sub-step forces may approach infinity for rigid body collisions. These
106 | /// match up one-to-one with the contact points in b2Manifold.
107 | public class ContactImpulse
108 | {
109 | public float[] normalImpulses = new float[Settings.MaxManifoldPoints];
110 | public float[] tangentImpulses = new float[Settings.MaxManifoldPoints];
111 | }
112 |
113 | /// Implement this class to get contact information. You can use these results for
114 | /// things like sounds and game logic. You can also get contact results by
115 | /// traversing the contact lists after the time step. However, you might miss
116 | /// some contacts because continuous physics leads to sub-stepping.
117 | /// Additionally you may receive multiple callbacks for the same contact in a
118 | /// single time step.
119 | /// You should strive to make your callbacks efficient because there may be
120 | /// many callbacks per time step.
121 | /// @warning You cannot create/destroy Box2DNet entities inside these callbacks.
122 | public interface ContactListener
123 | {
124 | /// Called when two fixtures begin to touch.
125 | void BeginContact(Contact contact);
126 |
127 | /// Called when two fixtures cease to touch.
128 | void EndContact(Contact contact);
129 |
130 | /// This is called after a contact is updated. This allows you to inspect a
131 | /// contact before it goes to the solver. If you are careful, you can modify the
132 | /// contact manifold (e.g. disable contact).
133 | /// A copy of the old manifold is provided so that you can detect changes.
134 | /// Note: this is called only for awake bodies.
135 | /// Note: this is called even when the number of contact points is zero.
136 | /// Note: this is not called for sensors.
137 | /// Note: if you set the number of contact points to zero, you will not
138 | /// get an EndContact callback. However, you may get a BeginContact callback
139 | /// the next step.
140 | void PreSolve(Contact contact, Manifold oldManifold);
141 |
142 | /// This lets you inspect a contact after the solver is finished. This is useful
143 | /// for inspecting impulses.
144 | /// Note: the contact manifold does not include time of impact impulses, which can be
145 | /// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly
146 | /// in a separate data structure.
147 | /// Note: this is only called for contacts that are touching, solid, and awake.
148 | void PostSolve(Contact contact, ContactImpulse impulse);
149 | }
150 |
151 | ///
152 | /// Color for debug drawing. Each value has the range [0,1].
153 | ///
154 | public struct Color
155 | {
156 | public float R, G, B;
157 |
158 | public Color(float r, float g, float b)
159 | {
160 | R = r; G = g; B = b;
161 | }
162 | public void Set(float r, float g, float b)
163 | {
164 | R = r; G = g; B = b;
165 | }
166 | }
167 |
168 | ///
169 | /// Implement and register this class with a b2World to provide debug drawing of physics
170 | /// entities in your game.
171 | ///
172 | public abstract class DebugDraw
173 | {
174 | [Flags]
175 | public enum DrawFlags
176 | {
177 | Shape = 0x0001, // draw shapes
178 | Joint = 0x0002, // draw joint connections
179 | CoreShape = 0x0004, // draw core (TOI) shapes // should be removed in this revision?
180 | Aabb = 0x0008, // draw axis aligned bounding boxes
181 | Obb = 0x0010, // draw oriented bounding boxes // should be removed in this revision?
182 | Pair = 0x0020, // draw broad-phase pairs
183 | CenterOfMass = 0x0040, // draw center of mass frame
184 | Controller = 0x0080 // draw center of mass frame
185 | };
186 |
187 | protected DrawFlags _drawFlags;
188 |
189 | public DebugDraw()
190 | {
191 | _drawFlags = 0;
192 | }
193 |
194 | public DrawFlags Flags { get { return _drawFlags; } set { _drawFlags = value; } }
195 |
196 | ///
197 | /// Append flags to the current flags.
198 | ///
199 | public void AppendFlags(DrawFlags flags)
200 | {
201 | _drawFlags |= flags;
202 | }
203 |
204 | ///
205 | /// Clear flags from the current flags.
206 | ///
207 | public void ClearFlags(DrawFlags flags)
208 | {
209 | _drawFlags &= ~flags;
210 | }
211 |
212 | ///
213 | /// Draw a closed polygon provided in CCW order.
214 | ///
215 | public abstract void DrawPolygon(Vector2[] vertices, int vertexCount, Color color);
216 |
217 | ///
218 | /// Draw a solid closed polygon provided in CCW order.
219 | ///
220 | public abstract void DrawSolidPolygon(Vector2[] vertices, int vertexCount, Color color);
221 |
222 | ///
223 | /// Draw a circle.
224 | ///
225 | public abstract void DrawCircle(Vector2 center, float radius, Color color);
226 |
227 | ///
228 | /// Draw a solid circle.
229 | ///
230 | public abstract void DrawSolidCircle(Vector2 center, float radius, Vector2 axis, Color color);
231 |
232 | ///
233 | /// Draw a line segment.
234 | ///
235 | public abstract void DrawSegment(Vector2 p1, Vector2 p2, Color color);
236 |
237 | ///
238 | /// Draw a Transform. Choose your own length scale.
239 | ///
240 | /// A Transform.
241 | public abstract void DrawTransform(Transform xf);
242 | }
243 | }
244 |
--------------------------------------------------------------------------------