Skip to content

Commit 7a6d151

Browse files
committed
[upstream] Simplified island merging, revised motor joint (box2d #966)
- simplified island merging. Islands are now immediately merged when a contact or joint are linked. - motor joint now has spring target and velocity target functionality - distance joint now has tension and compression force limits for the spring - samples now use the motor joint instead of the mouse joint #964 #960 #961 #959 #958
1 parent 3a39917 commit 7a6d151

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1232
-895
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using static Box2D.NET.B2Geometries;
2+
using static Box2D.NET.B2Types;
3+
using static Box2D.NET.B2MathFunction;
4+
using static Box2D.NET.B2Bodies;
5+
using static Box2D.NET.B2Shapes;
6+
7+
namespace Box2D.NET.Samples.Samples.Benchmarks;
8+
9+
// This is used to compare performance with Box2D v2.4
10+
public class BenchmarkBarrel24 : Sample
11+
{
12+
private static readonly int benchmarkBarrel24 = SampleFactory.Shared.RegisterSample("Benchmark", "Barrel 2.4", Create);
13+
14+
private static Sample Create(SampleContext context)
15+
{
16+
return new BenchmarkBarrel24(context);
17+
}
18+
19+
public BenchmarkBarrel24(SampleContext context) : base(context)
20+
{
21+
if (m_context.settings.restart == false)
22+
{
23+
m_context.camera.m_center = new B2Vec2(8.0f, 53.0f);
24+
m_context.camera.m_zoom = 25.0f * 2.35f;
25+
}
26+
27+
float groundSize = 25.0f;
28+
29+
{
30+
B2BodyDef bodyDef = b2DefaultBodyDef();
31+
B2BodyId groundId = b2CreateBody(m_worldId, ref bodyDef);
32+
33+
B2Polygon box = b2MakeBox(groundSize, 1.2f);
34+
B2ShapeDef shapeDef = b2DefaultShapeDef();
35+
b2CreatePolygonShape(groundId, ref shapeDef, ref box);
36+
37+
bodyDef.rotation = b2MakeRot(0.5f * B2_PI);
38+
bodyDef.position = new B2Vec2(groundSize, 2.0f * groundSize);
39+
groundId = b2CreateBody(m_worldId, ref bodyDef);
40+
41+
box = b2MakeBox(2.0f * groundSize, 1.2f);
42+
b2CreatePolygonShape(groundId, ref shapeDef, ref box);
43+
44+
bodyDef.position = new B2Vec2(-groundSize, 2.0f * groundSize);
45+
groundId = b2CreateBody(m_worldId, ref bodyDef);
46+
b2CreatePolygonShape(groundId, ref shapeDef, ref box);
47+
}
48+
49+
int num = 26;
50+
float rad = 0.5f;
51+
52+
float shift = rad * 2.0f;
53+
float centerx = shift * num / 2.0f;
54+
float centery = shift / 2.0f;
55+
56+
{
57+
B2BodyDef bodyDef = b2DefaultBodyDef();
58+
bodyDef.type = B2BodyType.b2_dynamicBody;
59+
60+
B2ShapeDef shapeDef = b2DefaultShapeDef();
61+
shapeDef.density = 1.0f;
62+
shapeDef.material.friction = 0.5f;
63+
64+
B2Polygon cuboid = b2MakeSquare(0.5f);
65+
66+
// b2Polygon top = b2MakeOffsetBox(0.8f, 0.2f, {0.0f, 0.8f}, 0.0f);
67+
// b2Polygon leftLeg = b2MakeOffsetBox(0.2f, 0.5f, {-0.6f, 0.5f}, 0.0f);
68+
// b2Polygon rightLeg = b2MakeOffsetBox(0.2f, 0.5f, {0.6f, 0.5f}, 0.0f);
69+
70+
#if DEBUG
71+
int numj = 5;
72+
#else
73+
int numj = 5 * num;
74+
#endif
75+
for (int i = 0; i < num; ++i)
76+
{
77+
float x = i * shift - centerx;
78+
79+
for (int j = 0; j < numj; ++j)
80+
{
81+
float y = j * shift + centery + 2.0f;
82+
83+
bodyDef.position = new B2Vec2(x, y);
84+
85+
B2BodyId bodyId = b2CreateBody(m_worldId, ref bodyDef);
86+
b2CreatePolygonShape(bodyId, ref shapeDef, ref cuboid);
87+
}
88+
}
89+
}
90+
}
91+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using static Box2D.NET.B2Geometries;
2+
using static Box2D.NET.B2Types;
3+
using static Box2D.NET.B2Bodies;
4+
using static Box2D.NET.B2Shapes;
5+
using static Box2D.NET.B2Worlds;
6+
7+
namespace Box2D.NET.Samples.Samples.Benchmarks;
8+
9+
public class BenchmarkCapacity : Sample
10+
{
11+
private static readonly int benchmarkCapacity = SampleFactory.Shared.RegisterSample("Benchmark", "Capacity", Create);
12+
13+
private B2Polygon m_square;
14+
private int m_reachCount;
15+
private bool m_done;
16+
17+
private static Sample Create(SampleContext context)
18+
{
19+
return new BenchmarkCapacity(context);
20+
}
21+
22+
public BenchmarkCapacity(SampleContext context) : base(context)
23+
{
24+
if (m_context.settings.restart == false)
25+
{
26+
m_context.camera.m_center = new B2Vec2(0.0f, 150.0f);
27+
m_context.camera.m_zoom = 200.0f;
28+
}
29+
30+
{
31+
B2BodyDef bodyDef = b2DefaultBodyDef();
32+
bodyDef.position.Y = -5.0f;
33+
B2BodyId groundId = b2CreateBody(m_worldId, ref bodyDef);
34+
35+
B2Polygon box = b2MakeBox(800.0f, 5.0f);
36+
B2ShapeDef shapeDef = b2DefaultShapeDef();
37+
b2CreatePolygonShape(groundId, ref shapeDef, ref box);
38+
}
39+
40+
m_square = b2MakeSquare(0.5f);
41+
m_done = false;
42+
m_reachCount = 0;
43+
}
44+
45+
public override void Step()
46+
{
47+
base.Step();
48+
49+
float millisecondLimit = 20.0f;
50+
51+
B2Profile profile = b2World_GetProfile(m_worldId);
52+
if (profile.step > millisecondLimit)
53+
{
54+
m_reachCount += 1;
55+
if (m_reachCount > 60)
56+
{
57+
// Hit the millisecond limit 60 times in a row
58+
m_done = true;
59+
}
60+
}
61+
else
62+
{
63+
m_reachCount = 0;
64+
}
65+
66+
if (m_done == true)
67+
{
68+
return;
69+
}
70+
71+
if ((m_stepCount & 0x1F) != 0x1F)
72+
{
73+
return;
74+
}
75+
76+
B2BodyDef bodyDef = b2DefaultBodyDef();
77+
bodyDef.type = B2BodyType.b2_dynamicBody;
78+
bodyDef.position.Y = 200.0f;
79+
80+
B2ShapeDef shapeDef = b2DefaultShapeDef();
81+
82+
int count = 200;
83+
float x = -1.0f * count;
84+
for (int i = 0; i < count; ++i)
85+
{
86+
bodyDef.position.X = x;
87+
bodyDef.position.Y += 0.5f;
88+
89+
B2BodyId bodyId = b2CreateBody(m_worldId, ref bodyDef);
90+
b2CreatePolygonShape(bodyId, ref shapeDef, ref m_square);
91+
92+
x += 2.0f;
93+
}
94+
}
95+
}

src/Box2D.NET.Samples/Samples/Benchmarks/BenchmarkSensor.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,25 @@ public BenchmarkSensor(SampleContext context) : base(context)
8383
shapeDef.enableSensorEvents = true;
8484

8585
float yStart = 10.0f;
86-
86+
m_filterRow = m_rowCount >> 1;
87+
8788
for (int j = 0; j < m_rowCount; ++j)
8889
{
8990
m_passiveSensors[j] = new ShapeUserData();
9091
m_passiveSensors[j].row = j;
9192
m_passiveSensors[j].active = false;
9293
shapeDef.userData = m_passiveSensors[j];
94+
95+
if ( j == m_filterRow )
96+
{
97+
shapeDef.enableCustomFiltering = true;
98+
shapeDef.material.customColor = (uint)B2HexColor.b2_colorFuchsia;
99+
}
100+
else
101+
{
102+
shapeDef.enableCustomFiltering = false;
103+
shapeDef.material.customColor = 0;
104+
}
93105

94106
float y = j * shift + yStart;
95107
for (int i = 0; i < m_columnCount; ++i)
@@ -104,7 +116,6 @@ public BenchmarkSensor(SampleContext context) : base(context)
104116
m_maxBeginCount = 0;
105117
m_maxEndCount = 0;
106118
m_lastStepCount = 0;
107-
m_filterRow = m_rowCount >> 1;
108119
}
109120

110121
void CreateRow(float y)

src/Box2D.NET.Samples/Samples/Continuous/ChainDrop.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void Launch()
7777
B2Circle circle = new B2Circle(new B2Vec2(0.0f, 0.0f), 0.5f);
7878
m_shapeId = b2CreateCircleShape(m_bodyId, ref shapeDef, ref circle);
7979

80-
//b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f };
80+
//b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, 0.25f };
8181
//m_shapeId = b2CreateCapsuleShape( m_bodyId, &shapeDef, &capsule );
8282

8383
//float h = 0.5f;

src/Box2D.NET.Samples/Samples/Events/JointEvent.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ public JointEvent(SampleContext context) : base(context)
9999
jointDef.@base.bodyIdA = groundId;
100100
jointDef.@base.bodyIdB = bodyId;
101101
jointDef.@base.localFrameA.p = position;
102-
jointDef.maxForce = 1000.0f;
103-
jointDef.maxTorque = 20.0f;
102+
jointDef.maxVelocityForce = 1000.0f;
103+
jointDef.maxVelocityTorque = 20.0f;
104104
jointDef.@base.forceThreshold = forceThreshold;
105105
jointDef.@base.torqueThreshold = torqueThreshold;
106106
jointDef.@base.collideConnected = true;

src/Box2D.NET.Samples/Samples/Joints/BreakableJoint.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ public BreakableJoint(SampleContext context) : base(context)
9595
jointDef.@base.bodyIdA = groundId;
9696
jointDef.@base.bodyIdB = bodyId;
9797
jointDef.@base.localFrameA.p = position;
98-
jointDef.maxForce = 1000.0f;
99-
jointDef.maxTorque = 20.0f;
98+
jointDef.maxVelocityForce = 1000.0f;
99+
jointDef.maxVelocityTorque = 20.0f;
100100
jointDef.@base.collideConnected = true;
101101
m_jointIds[index] = b2CreateMotorJoint(m_worldId, ref jointDef);
102102
}

src/Box2D.NET.Samples/Samples/Joints/DistanceJoint.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public class DistanceJoint : Sample
2727
private float m_hertz;
2828
private float m_dampingRatio;
2929
private float m_length;
30+
private float m_tensionForce;
31+
private float m_compressionForce;
3032
private float m_minLength;
3133
private float m_maxLength;
3234
private bool m_enableSpring;
@@ -51,11 +53,13 @@ public DistanceJoint(SampleContext context) : base(context)
5153
}
5254

5355
m_count = 0;
54-
m_hertz = 2.0f;
56+
m_hertz = 5.0f;
5557
m_dampingRatio = 0.5f;
5658
m_length = 1.0f;
5759
m_minLength = m_length;
5860
m_maxLength = m_length;
61+
m_tensionForce = 2000.0f;
62+
m_compressionForce = 100.0f;
5963
m_enableSpring = false;
6064
m_enableLimit = false;
6165

@@ -97,6 +101,8 @@ void CreateScene(int newCount)
97101
jointDef.hertz = m_hertz;
98102
jointDef.dampingRatio = m_dampingRatio;
99103
jointDef.length = m_length;
104+
jointDef.lowerSpringForce = -m_tensionForce;
105+
jointDef.upperSpringForce = m_compressionForce;
100106
jointDef.minLength = m_minLength;
101107
jointDef.maxLength = m_maxLength;
102108
jointDef.enableSpring = m_enableSpring;
@@ -107,7 +113,7 @@ void CreateScene(int newCount)
107113
{
108114
B2BodyDef bodyDef = b2DefaultBodyDef();
109115
bodyDef.type = B2BodyType.b2_dynamicBody;
110-
bodyDef.angularDamping = 0.1f;
116+
bodyDef.angularDamping = 1.0f;
111117
bodyDef.position = new B2Vec2(m_length * (i + 1.0f), yOffset);
112118
m_bodyIds[i] = b2CreateBody(m_worldId, ref bodyDef);
113119
b2CreateCircleShape(m_bodyIds[i], ref shapeDef, ref circle);
@@ -129,12 +135,12 @@ public override void UpdateGui()
129135
base.UpdateGui();
130136

131137
float fontSize = ImGui.GetFontSize();
132-
float height = 240.0f;
138+
float height = 20.0f * fontSize;
133139
ImGui.SetNextWindowPos(new Vector2(0.5f * fontSize, m_camera.m_height - height - 2.0f * fontSize), ImGuiCond.Once);
134-
ImGui.SetNextWindowSize(new Vector2(180.0f, height));
140+
ImGui.SetNextWindowSize(new Vector2(18.0f * fontSize, height));
135141

136142
ImGui.Begin("Distance Joint", ImGuiWindowFlags.NoResize);
137-
ImGui.PushItemWidth(100.0f);
143+
ImGui.PushItemWidth(10.0f * fontSize);
138144

139145
if (ImGui.SliderFloat("Length", ref m_length, 0.1f, 4.0f, "%3.1f"))
140146
{
@@ -156,6 +162,25 @@ public override void UpdateGui()
156162

157163
if (m_enableSpring)
158164
{
165+
166+
if ( ImGui.SliderFloat( "Tension", ref m_tensionForce, 0.0f, 4000.0f ) )
167+
{
168+
for ( int i = 0; i < m_count; ++i )
169+
{
170+
b2DistanceJoint_SetSpringForceRange( m_jointIds[i], -m_tensionForce, m_compressionForce );
171+
b2Joint_WakeBodies( m_jointIds[i] );
172+
}
173+
}
174+
175+
if ( ImGui.SliderFloat( "Compression", ref m_compressionForce, 0.0f, 200.0f ) )
176+
{
177+
for ( int i = 0; i < m_count; ++i )
178+
{
179+
b2DistanceJoint_SetSpringForceRange( m_jointIds[i], -m_tensionForce, m_compressionForce );
180+
b2Joint_WakeBodies( m_jointIds[i] );
181+
}
182+
}
183+
159184
if (ImGui.SliderFloat("Hertz", ref m_hertz, 0.0f, 15.0f, "%3.1f"))
160185
{
161186
for (int i = 0; i < m_count; ++i)

src/Box2D.NET.Samples/Samples/Joints/MotionLocks.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ public MotionLocks(SampleContext context) : base(context)
9393
jointDef.@base.bodyIdA = groundId;
9494
jointDef.@base.bodyIdB = m_bodyIds[index];
9595
jointDef.@base.localFrameA.p = position;
96-
jointDef.maxForce = 200.0f;
97-
jointDef.maxTorque = 200.0f;
96+
jointDef.maxVelocityForce = 200.0f;
97+
jointDef.maxVelocityTorque = 200.0f;
9898
b2CreateMotorJoint(m_worldId, ref jointDef);
9999
}
100100

0 commit comments

Comments
 (0)