1+ // SPDX-FileCopyrightText: 2022 Erin Catto
2+ // SPDX-FileCopyrightText: 2025 Ikpil Choi([email protected] ) 3+ // SPDX-License-Identifier: MIT
4+
5+ using System ;
6+ using System . Diagnostics ;
7+ using static Box2D . NET . B2Ids ;
8+ using static Box2D . NET . B2Geometries ;
9+ using static Box2D . NET . B2Types ;
10+ using static Box2D . NET . B2MathFunction ;
11+ using static Box2D . NET . B2Bodies ;
12+ using static Box2D . NET . B2Shapes ;
13+ using static Box2D . NET . B2Joints ;
14+ using static Box2D . NET . B2Constants ;
15+ using static Box2D . NET . B2Worlds ;
16+ using static Box2D . NET . B2Timers ;
17+
18+ namespace Box2D . NET . Shared
19+ {
20+ public static class Determinism
21+ {
22+ public static FallingHingeData CreateFallingHinges ( B2WorldId worldId )
23+ {
24+ {
25+ B2BodyDef bodyDef = b2DefaultBodyDef ( ) ;
26+ bodyDef . position = new B2Vec2 ( 0.0f , - 1.0f ) ;
27+ B2BodyId groundId = b2CreateBody ( worldId , ref bodyDef ) ;
28+
29+ B2Polygon box = b2MakeBox ( 20.0f , 1.0f ) ;
30+ B2ShapeDef shapeDef = b2DefaultShapeDef ( ) ;
31+ b2CreatePolygonShape ( groundId , ref shapeDef , ref box ) ;
32+ }
33+
34+ int columnCount = 4 ;
35+ int rowCount = 30 ;
36+ int bodyCount = rowCount * columnCount ;
37+
38+ B2BodyId [ ] bodyIds = new B2BodyId [ bodyCount ] ;
39+
40+ {
41+ float h = 0.25f ;
42+ float r = 0.1f * h ;
43+ B2Polygon box = b2MakeRoundedBox ( h - r , h - r , r ) ;
44+
45+ B2ShapeDef shapeDef = b2DefaultShapeDef ( ) ;
46+ shapeDef . material . friction = 0.3f ;
47+
48+ float offset = 0.4f * h ;
49+ float dx = 10.0f * h ;
50+ float xroot = - 0.5f * dx * ( columnCount - 1.0f ) ;
51+
52+ B2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef ( ) ;
53+ jointDef . enableLimit = true ;
54+ jointDef . lowerAngle = - 0.1f * B2_PI ;
55+ jointDef . upperAngle = 0.2f * B2_PI ;
56+ jointDef . enableSpring = true ;
57+ jointDef . hertz = 0.5f ;
58+ jointDef . dampingRatio = 0.5f ;
59+ jointDef . localAnchorA = new B2Vec2 ( h , h ) ;
60+ jointDef . localAnchorB = new B2Vec2 ( offset , - h ) ;
61+ jointDef . drawSize = 0.1f ;
62+
63+ int bodyIndex = 0 ;
64+
65+ for ( int j = 0 ; j < columnCount ; ++ j )
66+ {
67+ float x = xroot + j * dx ;
68+
69+ B2BodyId prevBodyId = b2_nullBodyId ;
70+
71+ for ( int i = 0 ; i < rowCount ; ++ i )
72+ {
73+ B2BodyDef bodyDef = b2DefaultBodyDef ( ) ;
74+ bodyDef . type = B2BodyType . b2_dynamicBody ;
75+
76+ bodyDef . position . X = x + offset * i ;
77+ bodyDef . position . Y = h + 2.0f * h * i ;
78+
79+ // this tests the deterministic cosine and sine functions
80+ bodyDef . rotation = b2MakeRot ( 0.1f * i - 1.0f ) ;
81+
82+ B2BodyId bodyId = b2CreateBody ( worldId , ref bodyDef ) ;
83+
84+ if ( ( i & 1 ) == 0 )
85+ {
86+ prevBodyId = bodyId ;
87+ }
88+ else
89+ {
90+ jointDef . bodyIdA = prevBodyId ;
91+ jointDef . bodyIdB = bodyId ;
92+ b2CreateRevoluteJoint ( worldId , ref jointDef ) ;
93+ prevBodyId = b2_nullBodyId ;
94+ }
95+
96+ b2CreatePolygonShape ( bodyId , ref shapeDef , ref box ) ;
97+
98+ Debug . Assert ( bodyIndex < bodyCount ) ;
99+ bodyIds [ bodyIndex ] = bodyId ;
100+
101+ bodyIndex += 1 ;
102+ }
103+ }
104+
105+ Debug . Assert ( bodyIndex == bodyCount ) ;
106+ }
107+
108+ FallingHingeData data = new FallingHingeData ( ) ;
109+ data . bodyIds = bodyIds ;
110+ data . bodyCount = bodyCount ;
111+ data . stepCount = 0 ;
112+ data . sleepStep = - 1 ;
113+ data . hash = 0 ;
114+ return data ;
115+ }
116+
117+ public static bool UpdateFallingHinges ( B2WorldId worldId , ref FallingHingeData data )
118+ {
119+ if ( data . hash == 0 )
120+ {
121+ B2BodyEvents bodyEvents = b2World_GetBodyEvents ( worldId ) ;
122+
123+ if ( bodyEvents . moveCount == 0 )
124+ {
125+ int awakeCount = b2World_GetAwakeBodyCount ( worldId ) ;
126+ Debug . Assert ( awakeCount == 0 ) ;
127+
128+ data . hash = B2_HASH_INIT ;
129+ Span < byte > bxf = stackalloc byte [ sizeof ( float ) * 4 ] ;
130+ for ( int i = 0 ; i < data . bodyCount ; ++ i )
131+ {
132+ B2Transform xf = b2Body_GetTransform ( data . bodyIds [ i ] ) ;
133+ xf . TryWriteBytes ( bxf ) ;
134+ data . hash = b2Hash ( data . hash , bxf , bxf . Length ) ;
135+ }
136+
137+ data . sleepStep = data . stepCount ;
138+ }
139+ }
140+
141+ data . stepCount += 1 ;
142+
143+ return data . hash != 0 ;
144+ }
145+
146+ public static void DestroyFallingHinges ( ref FallingHingeData data )
147+ {
148+ //free( data.bodyIds );
149+ data . bodyIds = null ;
150+ }
151+ }
152+ }
0 commit comments