1+ /**
2+ *
3+ * LiquidFunProcessing | Copyright 2017 Thomas Diewald - www.thomasdiewald.com
4+ *
5+ * https://github.com/diwi/LiquidFunProcessing.git
6+ *
7+ * Box2d / LiquidFun Library for Processing.
8+ * MIT License: https://opensource.org/licenses/MIT
9+ *
10+ */
11+
12+
13+
14+ package box2d_EdgeShapes ;
15+
16+
17+ import com .thomasdiewald .liquidfun .java .DwWorld ;
18+
19+ import org .jbox2d .callbacks .RayCastCallback ;
20+ import org .jbox2d .collision .shapes .CircleShape ;
21+ import org .jbox2d .collision .shapes .EdgeShape ;
22+ import org .jbox2d .collision .shapes .PolygonShape ;
23+ import org .jbox2d .common .Color3f ;
24+ import org .jbox2d .common .MathUtils ;
25+ import org .jbox2d .common .Vec2 ;
26+ import org .jbox2d .dynamics .Body ;
27+ import org .jbox2d .dynamics .BodyDef ;
28+ import org .jbox2d .dynamics .BodyType ;
29+ import org .jbox2d .dynamics .Fixture ;
30+ import org .jbox2d .dynamics .FixtureDef ;
31+ import processing .core .*;
32+ import processing .opengl .PGraphics2D ;
33+
34+
35+ public class box2d_EdgeShapes extends PApplet {
36+
37+ // Example to demonstrate how to use the RayCastCallback
38+
39+ int viewport_w = 1280 ;
40+ int viewport_h = 720 ;
41+ int viewport_x = 230 ;
42+ int viewport_y = 0 ;
43+
44+ boolean UPDATE_PHYSICS = true ;
45+ boolean USE_DEBUG_DRAW = false ;
46+
47+ DwWorld world ;
48+
49+ public void settings (){
50+ size (viewport_w , viewport_h , P2D );
51+ smooth (8 );
52+ }
53+
54+
55+ public void setup (){
56+ surface .setLocation (viewport_x , viewport_y );
57+ reset ();
58+ frameRate (120 );
59+ }
60+
61+
62+ public void release (){
63+ if (world != null ) world .release (); world = null ;
64+ }
65+
66+
67+ public void reset (){
68+ // release old resources
69+ release ();
70+
71+ world = new DwWorld (this , 25 );
72+ world .transform .setCamera (0 , 10 , 25 );
73+ // create scene: rigid bodies, particles, etc ...
74+ initScene ();
75+ }
76+
77+
78+ int id = 0 ;
79+ public void draw (){
80+
81+ // create a new body every second
82+ if ((frameCount %120 ) == 0 ){
83+ Create (id ++%5 );
84+ }
85+
86+ if (UPDATE_PHYSICS ){
87+ world .update ();
88+ }
89+
90+ PGraphics2D canvas = (PGraphics2D ) this .g ;
91+ canvas .background (32 );
92+ canvas .pushMatrix ();
93+ world .applyTransform (canvas );
94+ world .drawBulletSpawnTrack (canvas );
95+ if (USE_DEBUG_DRAW ){
96+ world .displayDebugDraw (canvas );
97+ // DwDebugDraw.display(canvas, world);
98+ } else {
99+ world .display (canvas );
100+ }
101+ step ();
102+ canvas .popMatrix ();
103+
104+ // info
105+ int num_bodies = world .getBodyCount ();
106+ int num_particles = world .getParticleCount ();
107+ String txt_fps = String .format (getClass ().getName ()+ " [bodies: %d] [particles: %d] [fps %6.2f]" , num_bodies , num_particles , frameRate );
108+ surface .setTitle (txt_fps );
109+ }
110+
111+
112+
113+ //////////////////////////////////////////////////////////////////////////////
114+ // User Interaction
115+ //////////////////////////////////////////////////////////////////////////////
116+ public void keyReleased (){
117+ if (key == 't' ) UPDATE_PHYSICS = !UPDATE_PHYSICS ;
118+ if (key == 'r' ) reset ();
119+ if (key == 'f' ) USE_DEBUG_DRAW = !USE_DEBUG_DRAW ;
120+ if (key >= '1' && key <= '5' ) Create (key -'1' );
121+ }
122+
123+
124+
125+ //////////////////////////////////////////////////////////////////////////////
126+ // Scene Setup
127+ //////////////////////////////////////////////////////////////////////////////
128+
129+
130+
131+ int e_maxBodies = 256 ;
132+ int m_bodyIndex ;
133+ Body m_bodies [] = new Body [e_maxBodies ];
134+ PolygonShape m_polygons [] = new PolygonShape [4 ];
135+ CircleShape m_circle ;
136+
137+ float m_angle ;
138+
139+ // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/EdgeShapes.java
140+ public void initScene () {
141+ for (int i = 0 ; i < m_bodies .length ; i ++) {
142+ m_bodies [i ] = null ;
143+ }
144+ // Ground body
145+ {
146+ BodyDef bd = new BodyDef ();
147+ Body ground = world .createBody (bd );
148+
149+ float x1 = -20.0f ;
150+ float y1 = 2.0f * MathUtils .cos (x1 / 10.0f * MathUtils .PI );
151+ for (int i = 0 ; i < 80 ; ++i ) {
152+ float x2 = x1 + 0.5f ;
153+ float y2 = 2.0f * MathUtils .cos (x2 / 10.0f * MathUtils .PI );
154+
155+ EdgeShape shape = new EdgeShape ();
156+ shape .set (new Vec2 (x1 , y1 ), new Vec2 (x2 , y2 ));
157+ ground .createFixture (shape , 0.0f );
158+
159+ x1 = x2 ;
160+ y1 = y2 ;
161+ }
162+ world .bodies .add (ground , false , color (0 ), true , color (255 ,255 ,0 ), 1f );
163+ }
164+
165+ {
166+ Vec2 vertices [] = new Vec2 [3 ];
167+ vertices [0 ] = new Vec2 (-0.5f , 0.0f );
168+ vertices [1 ] = new Vec2 (0.5f , 0.0f );
169+ vertices [2 ] = new Vec2 (0.0f , 1.5f );
170+ m_polygons [0 ] = new PolygonShape ();
171+ m_polygons [0 ].set (vertices , 3 );
172+ }
173+
174+ {
175+ Vec2 vertices [] = new Vec2 [3 ];
176+ vertices [0 ] = new Vec2 (-0.1f , 0.0f );
177+ vertices [1 ] = new Vec2 (0.1f , 0.0f );
178+ vertices [2 ] = new Vec2 (0.0f , 1.5f );
179+ m_polygons [1 ] = new PolygonShape ();
180+ m_polygons [1 ].set (vertices , 3 );
181+ }
182+
183+ {
184+ float w = 1.0f ;
185+ float b = w / (2.0f + MathUtils .sqrt (2.0f ));
186+ float s = MathUtils .sqrt (2.0f ) * b ;
187+
188+ Vec2 vertices [] = new Vec2 [8 ];
189+ vertices [0 ] = new Vec2 (0.5f * s , 0.0f );
190+ vertices [1 ] = new Vec2 (0.5f * w , b );
191+ vertices [2 ] = new Vec2 (0.5f * w , b + s );
192+ vertices [3 ] = new Vec2 (0.5f * s , w );
193+ vertices [4 ] = new Vec2 (-0.5f * s , w );
194+ vertices [5 ] = new Vec2 (-0.5f * w , b + s );
195+ vertices [6 ] = new Vec2 (-0.5f * w , b );
196+ vertices [7 ] = new Vec2 (-0.5f * s , 0.0f );
197+
198+ m_polygons [2 ] = new PolygonShape ();
199+ m_polygons [2 ].set (vertices , 8 );
200+ }
201+
202+ {
203+ m_polygons [3 ] = new PolygonShape ();
204+ m_polygons [3 ].setAsBox (0.5f , 0.5f );
205+ }
206+
207+ {
208+ m_circle = new CircleShape ();
209+ m_circle .m_radius = 0.5f ;
210+ }
211+
212+ m_bodyIndex = 0 ;
213+ m_angle = 0.0f ;
214+ }
215+
216+
217+
218+
219+
220+ void Create (int index ) {
221+ if (m_bodies [m_bodyIndex ] != null ) {
222+ world .destroyBody (m_bodies [m_bodyIndex ]);
223+ m_bodies [m_bodyIndex ] = null ;
224+ }
225+
226+ BodyDef bd = new BodyDef ();
227+
228+ float x = MathUtils .randomFloat (-10.0f , 10.0f );
229+ float y = MathUtils .randomFloat (10.0f , 20.0f );
230+ bd .position .set (x , y );
231+ bd .angle = MathUtils .randomFloat (-MathUtils .PI , MathUtils .PI );
232+ bd .type = BodyType .DYNAMIC ;
233+
234+ if (index == 4 ) {
235+ bd .angularDamping = 0.02f ;
236+ }
237+
238+ m_bodies [m_bodyIndex ] = world .createBody (bd );
239+
240+ if (index < 4 ) {
241+ FixtureDef fd = new FixtureDef ();
242+ fd .shape = m_polygons [index ];
243+ fd .friction = 0.3f ;
244+ fd .density = 20.0f ;
245+ m_bodies [m_bodyIndex ].createFixture (fd );
246+ } else {
247+ FixtureDef fd = new FixtureDef ();
248+ fd .shape = m_circle ;
249+ fd .friction = 0.3f ;
250+ fd .density = 20.0f ;
251+ m_bodies [m_bodyIndex ].createFixture (fd );
252+ }
253+
254+ world .bodies .add (m_bodies [m_bodyIndex ], true , color (255 ,0 ,0 ), true , color (0 ), 1f );
255+
256+ m_bodyIndex = (m_bodyIndex + 1 ) % e_maxBodies ;
257+ }
258+
259+
260+
261+
262+ EdgeShapesCallback callback = new EdgeShapesCallback ();
263+
264+
265+ public void step (){
266+
267+ m_angle += 0.25f * PI / 180.0f ;
268+
269+ float radius = 25.0f ;
270+ Vec2 point1 = new Vec2 (0.0f , 10.0f );
271+ Vec2 p1p2 = new Vec2 (radius * cos (m_angle ), -radius * abs (sin (m_angle )));
272+ Vec2 point2 = point1 .add (p1p2 );
273+
274+ callback .m_fixture = null ;
275+ world .raycast (callback , point1 , point2 );
276+
277+ if (callback .m_fixture != null ) {
278+ world .debug_draw .drawPoint (callback .m_point , 5.0f /world .transform .screen_scale , new Color3f (0.4f , 0.9f , 0.4f ));
279+ world .debug_draw .drawSegment (point1 , callback .m_point , new Color3f (0.8f , 0.8f , 0.8f ));
280+ Vec2 head = callback .m_normal .mul (.5f ).addLocal (callback .m_point );
281+ world .debug_draw .drawSegment (callback .m_point , head , new Color3f (0.9f , 0.9f , 0.4f ));
282+ } else {
283+ world .debug_draw .drawSegment (point1 , point2 , new Color3f (0.8f , 0.8f , 0.8f ));
284+ }
285+
286+ }
287+
288+
289+ static class EdgeShapesCallback implements RayCastCallback {
290+
291+ Fixture m_fixture = null ;
292+ Vec2 m_point ;
293+ Vec2 m_normal ;
294+
295+ public float reportFixture (Fixture fixture , final Vec2 point , final Vec2 normal , float fraction ) {
296+ m_fixture = fixture ;
297+ m_point = point ;
298+ m_normal = normal ;
299+ return fraction ;
300+ }
301+ }
302+
303+
304+ public static void main (String args []) {
305+ PApplet .main (new String [] { box2d_EdgeShapes .class .getName () });
306+ }
307+
308+ }
0 commit comments