Skip to content

Commit ec2a473

Browse files
committed
wip
1 parent c69b42d commit ec2a473

20 files changed

Lines changed: 385 additions & 221 deletions
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
// SPDX-FileCopyrightText: 2025 Erin Catto
2+
// SPDX-FileCopyrightText: 2025 Ikpil Choi(ikpil@naver.com)
3+
// SPDX-License-Identifier: MIT
4+
5+
using System.Collections.Generic;
6+
using System.Numerics;
7+
using System.Runtime.InteropServices;
8+
using ImGuiNET;
9+
using static Box2D.NET.B2Types;
10+
using static Box2D.NET.B2Bodies;
11+
using static Box2D.NET.B2Shapes;
12+
using static Box2D.NET.B2Ids;
13+
using static Box2D.NET.B2Worlds;
14+
using static Box2D.NET.B2Contacts;
15+
using static Box2D.NET.Samples.Graphics.Draws;
16+
17+
namespace Box2D.NET.Samples.Samples.Stackings;
18+
19+
public class CircleImpulse : Sample
20+
{
21+
private static readonly int SampleCircleImpulse = SampleFactory.Shared.RegisterSample("Stacking", "Circle Impulse", Create);
22+
23+
public struct Event
24+
{
25+
public float impulse;
26+
public float totalImpulse;
27+
public float speed;
28+
};
29+
30+
private float m_mass;
31+
private List<Event> m_events = new List<Event>();
32+
private B2BodyId m_bodyId;
33+
private float m_gravity;
34+
private float m_restitution;
35+
private bool m_useGravity;
36+
private bool m_useRestitution;
37+
38+
private static Sample Create(SampleContext context)
39+
{
40+
return new CircleImpulse(context);
41+
}
42+
43+
public CircleImpulse(SampleContext context) : base(context)
44+
{
45+
if (m_context.restart == false)
46+
{
47+
m_context.camera.center = new B2Vec2(0.0f, 2.7f);
48+
m_context.camera.zoom = 3.4f;
49+
}
50+
51+
{
52+
B2BodyDef bodyDef = b2DefaultBodyDef();
53+
B2BodyId groundId = b2CreateBody(m_worldId, bodyDef);
54+
55+
B2ShapeDef shapeDef = b2DefaultShapeDef();
56+
57+
B2Segment segment = new B2Segment(new B2Vec2(-10.0f, 0.0f), new B2Vec2(10.0f, 0.0f));
58+
b2CreateSegmentShape(groundId, shapeDef, segment);
59+
}
60+
61+
m_gravity = 10.0f;
62+
m_restitution = 0.25f;
63+
m_useGravity = false;
64+
m_useRestitution = false;
65+
m_mass = 1.0f;
66+
m_bodyId = b2_nullBodyId;
67+
68+
Spawn();
69+
}
70+
71+
void Spawn()
72+
{
73+
if (B2_IS_NON_NULL(m_bodyId))
74+
{
75+
b2DestroyBody(m_bodyId);
76+
m_bodyId = b2_nullBodyId;
77+
}
78+
79+
m_events.Clear();
80+
81+
B2BodyDef bodyDef = b2DefaultBodyDef();
82+
bodyDef.type = B2BodyType.b2_dynamicBody;
83+
bodyDef.gravityScale = m_useGravity ? 1.0f : 0.0f;
84+
bodyDef.linearVelocity.Y = -25.0f;
85+
bodyDef.position.Y = 5.5f;
86+
87+
B2Circle circle = new B2Circle();
88+
circle.radius = 0.25f;
89+
90+
B2ShapeDef shapeDef = b2DefaultShapeDef();
91+
shapeDef.enableHitEvents = true;
92+
shapeDef.material.friction = 0.0f;
93+
shapeDef.material.restitution = m_useRestitution ? m_restitution : 0.0f;
94+
95+
m_bodyId = b2CreateBody(m_worldId, bodyDef);
96+
97+
b2CreateCircleShape(m_bodyId, shapeDef, circle);
98+
99+
// Override mass
100+
B2MassData massData = b2Body_GetMassData(m_bodyId);
101+
float ratio = m_mass / massData.mass;
102+
massData.mass = m_mass;
103+
massData.rotationalInertia *= ratio;
104+
b2Body_SetMassData(m_bodyId, massData);
105+
}
106+
107+
public override void UpdateGui()
108+
{
109+
float fontSize = ImGui.GetFontSize();
110+
float height = 6.0f * fontSize;
111+
ImGui.SetNextWindowPos(new Vector2(0.5f * fontSize, m_camera.height - height - 2.0f * fontSize), ImGuiCond.Once);
112+
ImGui.SetNextWindowSize(new Vector2(10.0f * fontSize, height));
113+
114+
ImGui.Begin("Circle Impulse", ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoResize);
115+
116+
if (ImGui.Checkbox("gravity", ref m_useGravity))
117+
{
118+
Spawn();
119+
}
120+
121+
if (ImGui.Checkbox("restitution", ref m_useRestitution))
122+
{
123+
Spawn();
124+
}
125+
126+
ImGui.End();
127+
}
128+
129+
public override void Step()
130+
{
131+
base.Step();
132+
133+
B2ContactEvents events = b2World_GetContactEvents(m_worldId);
134+
for (int i = 0; i < events.hitCount; ++i)
135+
{
136+
ref readonly B2ContactHitEvent @event = ref events.hitEvents[i];
137+
138+
DrawPoint(m_draw, @event.point, 10.0f, B2HexColor.b2_colorWhite);
139+
140+
B2ContactData data = b2Contact_GetData(@event.contactId);
141+
142+
Event e = new Event();
143+
e.speed = @event.approachSpeed;
144+
145+
if (data.manifold.pointCount > 0)
146+
{
147+
e.impulse = data.manifold.points[0].normalImpulse;
148+
e.totalImpulse = data.manifold.points[0].totalNormalImpulse;
149+
}
150+
151+
m_events.Add(e);
152+
}
153+
154+
DrawTextLine($"mass = {m_mass}, gravity = {(m_useGravity ? 10.0f : 0.0f)}, restitution = {(m_useRestitution ? m_restitution : 0.0f)}");
155+
156+
int eventCount = m_events.Count;
157+
var eventsSpan = CollectionsMarshal.AsSpan(m_events);
158+
for (int i = 0; i < eventCount; ++i)
159+
{
160+
ref readonly Event e = ref eventsSpan[i];
161+
DrawTextLine($"hit speed = {e.speed}, hit momentum = {m_mass * e.speed}, final impulse = {e.impulse}, total impulse = {e.totalImpulse}");
162+
}
163+
}
164+
}

src/Box2D.NET.Shared/Benchmarks.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public static void CreateManyPyramids(B2WorldId worldId)
185185
for (int i = 0; i < rowCount; ++i)
186186
{
187187
B2Segment segment = new B2Segment(new B2Vec2(-0.5f * 2.0f * groundWidth, groundY), new B2Vec2(0.5f * 2.0f * groundWidth, groundY));
188-
b2CreateSegmentShape(groundId, ref shapeDef, ref segment);
188+
b2CreateSegmentShape(groundId, shapeDef, segment);
189189
groundY += groundDeltaY;
190190
}
191191

0 commit comments

Comments
 (0)