├── LICENSE ├── README.md ├── examples ├── Basic_Tutorial │ └── Basic_Tutorial.java ├── box2d_BlobJoint │ └── box2d_BlobJoint.java ├── box2d_BlobJoint_LiquidFx │ └── box2d_BlobJoint_LiquidFx.java ├── box2d_Breakable │ └── box2d_Breakable.java ├── box2d_BrickWall │ └── box2d_BrickWall.java ├── box2d_Bullet │ └── box2d_Bullet.java ├── box2d_Cantilever_WeldJoint │ └── box2d_Cantilever_WeldJoint.java ├── box2d_Car │ └── box2d_Car.java ├── box2d_Chain_RevoluteJoint │ └── box2d_Chain_RevoluteJoint.java ├── box2d_CircleStressTest │ └── box2d_CircleStressTest.java ├── box2d_Collisions │ └── box2d_Collisions.java ├── box2d_Collisions_SensorTest │ └── box2d_Collisions_SensorTest.java ├── box2d_Collisions_SensorTestCallback │ └── box2d_Collisions_SensorTestCallback.java ├── box2d_CompoundShapes │ └── box2d_CompoundShapes.java ├── box2d_DominoTower │ └── box2d_DominoTower.java ├── box2d_Dominos │ └── box2d_Dominos.java ├── box2d_MobileBalanced │ └── box2d_MobileBalanced.java ├── box2d_PistonStressTest │ └── box2d_PistonStressTest.java ├── box2d_PulleyJoint │ └── box2d_PulleyJoint.java ├── box2d_RainingBodies │ └── box2d_RainingBodies.java ├── box2d_RayCastEdgeShapes │ └── box2d_RayCastEdgeShapes.java ├── box2d_RopeJoint │ └── box2d_RopeJoint.java ├── box2d_TheoJansenWalker │ └── box2d_TheoJansenWalker.java ├── box2d_Tumbler │ └── box2d_Tumbler.java ├── box2d_TumblerMod │ └── box2d_TumblerMod.java ├── box2d_VaryingFriction │ └── box2d_VaryingFriction.java ├── box2d_VaryingRestitution │ └── box2d_VaryingRestitution.java ├── liquidfun_Chain_DistanceJoints_LiquidFx │ └── liquidfun_Chain_DistanceJoints_LiquidFx.java ├── liquidfun_DamBreak │ └── liquidfun_DamBreak.java ├── liquidfun_DamBreak_LiquidFx │ └── liquidfun_DamBreak_LiquidFx.java ├── liquidfun_DamBreak_PShapeParticles │ └── liquidfun_DamBreak_PShapeParticles.java ├── liquidfun_DrawingParticles │ └── liquidfun_DrawingParticles.java ├── liquidfun_DrawingParticles_LiquidFx │ └── liquidfun_DrawingParticles_LiquidFx.java ├── liquidfun_LiquidTimer │ └── liquidfun_LiquidTimer.java ├── liquidfun_ParticleColors_LiquidFx │ └── liquidfun_ParticleColors_LiquidFx.java ├── liquidfun_ParticleEmitter_LiquidFx │ └── liquidfun_ParticleEmitter_LiquidFx.java ├── liquidfun_ParticleRenderGroups_LiquidFx │ └── liquidfun_ParticleRenderGroups_LiquidFx.java ├── liquidfun_ParticleRenderGroups_LiquidFxDark │ └── liquidfun_ParticleRenderGroups_LiquidFxDark.java ├── liquidfun_ParticleTypes │ └── liquidfun_ParticleTypes.java ├── liquidfun_ParticleTypes_LiquidFx │ └── liquidfun_ParticleTypes_LiquidFx.java ├── liquidfun_WaveMachine │ └── liquidfun_WaveMachine.java └── liquidfun_WaveMachine_LiquidFx │ └── liquidfun_WaveMachine_LiquidFx.java ├── screenshots ├── LiquidFunProcessing_DebugDraw1.png ├── LiquidFunProcessing_Draw.png ├── LiquidFunProcessing_Orange.png ├── LiquidFunProcessing_Timer.png ├── LiquidFunProcessing_Wavemaschine.png ├── examples │ ├── diewald_LiquidFunProcessing_BalancedTree.jpg │ ├── diewald_LiquidFunProcessing_BlobJoints.jpg │ ├── diewald_LiquidFunProcessing_Chains.jpg │ ├── diewald_LiquidFunProcessing_CircleStress.jpg │ ├── diewald_LiquidFunProcessing_Collisions.jpg │ ├── diewald_LiquidFunProcessing_DamBreak.jpg │ ├── diewald_LiquidFunProcessing_DominoPyramid.jpg │ ├── diewald_LiquidFunProcessing_Dominos.jpg │ ├── diewald_LiquidFunProcessing_Examples1.jpg │ ├── diewald_LiquidFunProcessing_Examples2.jpg │ ├── diewald_LiquidFunProcessing_ParticleDrawing.jpg │ ├── diewald_LiquidFunProcessing_ParticleDrawing1.jpg │ ├── diewald_LiquidFunProcessing_ParticleEmitter.jpg │ ├── diewald_LiquidFunProcessing_ParticleRenderGroup.jpg │ ├── diewald_LiquidFunProcessing_ParticleTypes.jpg │ ├── diewald_LiquidFunProcessing_PistonStress.jpg │ ├── diewald_LiquidFunProcessing_Rain.jpg │ ├── diewald_LiquidFunProcessing_Tumbler.jpg │ └── diewald_LiquidFunProcessing_WaveMachine.jpg └── rendermodes │ ├── diewald_LiquidFunProcessing_RenderDebug.jpg │ ├── diewald_LiquidFunProcessing_RenderLiquidFx.jpg │ └── diewald_LiquidFunProcessing_RenderRaw.jpg └── src └── com └── thomasdiewald └── liquidfun ├── glsl ├── particle_render.frag ├── particle_render.vert ├── particle_render2.frag └── particle_render2.vert └── java ├── DwParticleEmitter.java ├── DwUtils.java ├── DwViewportTransform.java ├── DwWorld.java ├── interaction ├── DwInteractionEvent.java ├── DwMouseDragBodies.java ├── DwMouseDragParticles.java ├── DwMouseShootBullet.java ├── DwParticleDestroyer.java └── DwParticleSpawn.java └── render ├── DwBody.java ├── DwBodyGroup.java ├── DwDebugDraw.java ├── DwFixture.java ├── DwJoint.java ├── DwParticleRender.java ├── DwParticleRenderGL.java ├── DwParticleRenderGLQuads.java ├── DwParticleRenderGroupCallback.java ├── DwParticleRenderP5.java └── ShapeStyle.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Thomas Diewald 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 | ![LiquidFunProcessing](https://github.com/diwi/LiquidFunProcessing/blob/master/screenshots/examples/diewald_LiquidFunProcessing_Chains.jpg) 2 | 3 | 4 | # LiquidFunProcessing 5 | **Box2D/LiquidFun Library for Processing.** 6 | 7 | Particle based fluid simulation and rigid body simulation using [jBox2D/LiquidFun 2.3.0+](https://github.com/jbox2d/jbox2d). 8 | 9 | 10 | ### References 11 | 12 | - LiquidFunProcessing: http://thomasdiewald.com/processing/libraries/liquidfun/reference/index.html 13 | - jBox2d: http://thomasdiewald.com/processing/libraries/jbox2d-2.3.0/doc/index.html 14 | 15 | ### Tutorials, Readings 16 | - Box2D: http://www.iforce2d.net/b2dtut 17 | - LiquidFun: http://google.github.io/liquidfun/Programmers-Guide/html/index.html 18 | 19 |
20 | 21 | ## Download 22 | + [Releases](https://github.com/diwi/LiquidFunProcessing/releases) 23 | + [LiquidFunProcessing Website](http://thomasdiewald.com/processing/libraries/liquidfun) 24 | + Processing IDE -> Library Manager 25 | 26 |
27 | 28 | ![LiquidFunProcessing](https://github.com/diwi/LiquidFunProcessing/blob/master/screenshots/examples/diewald_LiquidFunProcessing_Examples2.jpg) 29 | 30 |
31 | 32 | ## Videos 33 | 34 | [](https://vimeo.com/223843930 "LiquidFunProcessing - Chains") 35 | [](https://vimeo.com/223843846 "LiquidFunProcessing - Bricks") 36 | [](https://vimeo.com/223843490 "LiquidFunProcessing - WaveMachine") 37 | [](https://vimeo.com/223843609 "LiquidFunProcessing - ParticleTypes") 38 | 39 |
40 | 41 | ## Examples 42 | The library includes a lot of examples from the original [jbox2d testbed](https://github.com/jbox2d/jbox2d/tree/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests).
43 | For a quick start, each sketch has a couple of default mouse-actions: 44 | 45 | - LMB: drag rigid bodies / particles 46 | - LMB + SHIFT: shoot a bullet 47 | - MMB: spawn particles 48 | - RMB: destroy particles 49 | 50 | ... as well as some key-mapping, e.g. to display the debug-draw, restart, pause/resume.
51 | Of course, each of those can be altered, overwritten or disabled/removed. 52 | 53 |
54 | 55 | 56 | ## Rendermodes 57 | 58 | #### Default renderer, no postprocessing 59 | 60 | particles are rendered as point-sprites and rigid bodies are rendered using the PShape tree structure. 61 | 62 | ![Default](https://github.com/diwi/LiquidFunProcessing/blob/master/screenshots/rendermodes/diewald_LiquidFunProcessing_RenderRaw.jpg) 63 | 64 |
65 | 66 | #### Default renderer + Postprocessing 67 | 68 | **LiquidFx** adds some liquid effect and fake shading. [PixelFlow](https://github.com/diwi/PixelFlow) needs to be installed to use it. 69 | 70 | ![LiquidFx](https://github.com/diwi/LiquidFunProcessing/blob/master/screenshots/rendermodes/diewald_LiquidFunProcessing_RenderLiquidFx.jpg) 71 | 72 |
73 | 74 | #### Debug Draw 75 | 76 | using the box2d world for rendering and basic processing draw calls. 77 | 78 | ![Debug](https://github.com/diwi/LiquidFunProcessing/blob/master/screenshots/rendermodes/diewald_LiquidFunProcessing_RenderDebug.jpg) 79 | 80 |
81 | 82 | ## Resources 83 | 84 | - jBox2d web: http://www.jbox2d.org/ 85 | - jBox2d Testbed: https://github.com/jbox2d/jbox2d/tree/master/jbox2d-testbed 86 | - Box2d Testbed: https://github.com/erincatto/Box2D/tree/master/Box2D/Testbed 87 | - LiquidFun: http://google.github.io/liquidfun/ 88 | - **LiquidFun Programmers Guide: http://google.github.io/liquidfun/Programmers-Guide/html/index.html** 89 | 90 |
91 | 92 | ## Installation, Processing IDE 93 | 94 | - Download [Processing 3](https://processing.org/download/?processing) 95 | - Install liquidFunProcessing via the Library Manager. 96 | - Or manually, unzip and put the extracted LiquidFunProcessing folder into the libraries folder of your Processing sketches. Reference and examples are included in the LiquidFunProcessing folder. 97 | 98 | - Also make sure you have the latest graphics card driver installed! 99 | 100 | #### Platforms 101 | Windows, Linux, MacOSX 102 | 103 | 104 |
105 | 106 | ## Dependencies, to run the examples 107 | 108 | - **PixelFlow: https://github.com/diwi/PixelFlow** 109 | 110 | -------------------------------------------------------------------------------- /examples/box2d_BrickWall/box2d_BrickWall.java: -------------------------------------------------------------------------------- 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_BrickWall; 15 | 16 | import com.thomasdiewald.liquidfun.java.DwWorld; 17 | 18 | import org.jbox2d.collision.shapes.CircleShape; 19 | import org.jbox2d.collision.shapes.PolygonShape; 20 | import org.jbox2d.common.Vec2; 21 | import org.jbox2d.dynamics.Body; 22 | import org.jbox2d.dynamics.BodyDef; 23 | import org.jbox2d.dynamics.BodyType; 24 | import org.jbox2d.dynamics.FixtureDef; 25 | 26 | import processing.core.*; 27 | import processing.opengl.PGraphics2D; 28 | 29 | 30 | public class box2d_BrickWall extends PApplet { 31 | 32 | 33 | // 34 | // Simple stacking demo. 35 | // 36 | // 37 | // Controls: 38 | // 39 | // LMB ... drag bodies 40 | // LMB + SHIFT ... shoot bullet 41 | // MMB ... add particles 42 | // RMB ... remove particles 43 | // 'r' ... reset 44 | // 't' ... update/pause physics 45 | // 'f' ... toggle debug draw 46 | // 47 | 48 | 49 | int viewport_w = 1280; 50 | int viewport_h = 720; 51 | int viewport_x = 230; 52 | int viewport_y = 0; 53 | 54 | boolean UPDATE_PHYSICS = true; 55 | boolean USE_DEBUG_DRAW = false; 56 | 57 | DwWorld world; 58 | 59 | public void settings(){ 60 | size(viewport_w, viewport_h, P2D); 61 | smooth(8); 62 | } 63 | 64 | public void setup(){ 65 | surface.setLocation(viewport_x, viewport_y); 66 | reset(); 67 | frameRate(120); 68 | } 69 | 70 | 71 | public void release(){ 72 | if(world != null) world.release(); world = null; 73 | } 74 | 75 | public void reset(){ 76 | // release old resources 77 | release(); 78 | 79 | world = new DwWorld(this, 20); 80 | 81 | // create scene: rigid bodies, particles, etc ... 82 | initScene(); 83 | } 84 | 85 | 86 | 87 | public void draw(){ 88 | 89 | if(UPDATE_PHYSICS){ 90 | world.update(); 91 | } 92 | 93 | 94 | PGraphics2D canvas = (PGraphics2D) this.g; 95 | 96 | canvas.background(32); 97 | canvas.pushMatrix(); 98 | world.applyTransform(canvas); 99 | world.drawBulletSpawnTrack(canvas); 100 | 101 | if(USE_DEBUG_DRAW){ 102 | world.displayDebugDraw(canvas); 103 | // DwDebugDraw.display(canvas, world); 104 | } else { 105 | world.bodies.display(canvas); 106 | world.particles.display(canvas); 107 | } 108 | canvas.popMatrix(); 109 | 110 | // info 111 | int num_bodies = world.getBodyCount(); 112 | int num_particles = world.getParticleCount(); 113 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 114 | surface.setTitle(txt_fps); 115 | } 116 | 117 | 118 | 119 | 120 | 121 | ////////////////////////////////////////////////////////////////////////////// 122 | // User Interaction 123 | ////////////////////////////////////////////////////////////////////////////// 124 | 125 | public void keyReleased(){ 126 | if(key == 'r') reset(); 127 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 128 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 129 | } 130 | 131 | 132 | 133 | ////////////////////////////////////////////////////////////////////////////// 134 | // Scene Setup 135 | ////////////////////////////////////////////////////////////////////////////// 136 | 137 | public void initScene() { 138 | 139 | float screen_scale = world.transform.screen_scale; 140 | float b2d_screen_w = world.transform.box2d_dimx; 141 | float b2d_screen_h = world.transform.box2d_dimy; 142 | float b2d_thickness = 20 / screen_scale; 143 | 144 | { 145 | 146 | float radius = 25 / screen_scale; 147 | CircleShape circle_shape = new CircleShape(); 148 | circle_shape.setRadius(radius); 149 | 150 | FixtureDef fixture_def = new FixtureDef(); 151 | fixture_def.shape = circle_shape; 152 | fixture_def.density = 10f; 153 | fixture_def.friction = 0.30f; 154 | fixture_def.restitution = 0.30f; 155 | 156 | BodyDef body_def = new BodyDef(); 157 | body_def.type = BodyType.DYNAMIC; 158 | body_def.angle = 0.0f; 159 | body_def.position.x = -1/screen_scale; 160 | body_def.position.y = b2d_screen_h - 10; 161 | body_def.bullet = true; 162 | 163 | Body circle_body = world.createBody(body_def); 164 | circle_body.createFixture(fixture_def); 165 | 166 | world.bodies.add(circle_body, true, color(64, 125, 255), true, color(0), 1f); 167 | } 168 | 169 | { // Walls 170 | BodyDef bd = new BodyDef(); 171 | bd.position.set(0, 0); 172 | 173 | Body ground = world.createBody(bd); 174 | PolygonShape sd = new PolygonShape(); 175 | 176 | float x, y, w, h; 177 | 178 | // BOTTOM 179 | x = 0; 180 | y = 0; 181 | w = b2d_screen_w; 182 | h = b2d_thickness; 183 | sd.setAsBox(w/2f, h/2f, new Vec2(x, y), 0.0f); 184 | ground.createFixture(sd, 0f); 185 | 186 | // TOP 187 | x = 0; 188 | y = b2d_screen_h; 189 | w = b2d_screen_w; 190 | h = b2d_thickness; 191 | sd.setAsBox(w/2f, h/2f, new Vec2(x, y), 0.0f); 192 | ground.createFixture(sd, 0f); 193 | 194 | // LEFT 195 | x = -b2d_screen_w/2; 196 | y = +b2d_screen_h/2; 197 | w = b2d_thickness; 198 | h = b2d_screen_h - b2d_thickness; 199 | sd.setAsBox(w/2f, h/2f, new Vec2(x, y), 0.0f); 200 | ground.createFixture(sd, 0f); 201 | 202 | // RIGHT 203 | x = +b2d_screen_w/2; 204 | y = +b2d_screen_h/2; 205 | w = b2d_thickness; 206 | h = b2d_screen_h - b2d_thickness; 207 | sd.setAsBox(w/2f, h/2f, new Vec2(x, y), 0.0f); 208 | ground.createFixture(sd, 0f); 209 | 210 | world.bodies.add(ground, true, color(0), !true, color(0), 1f); 211 | } 212 | 213 | createWall(10, 20, 40, 20, 0, 10); 214 | 215 | } 216 | 217 | 218 | public void createWall(int numx, int numy, float dimx, float dimy, float tx, float ty){ 219 | 220 | float scree_scale = world.transform.screen_scale; 221 | 222 | 223 | dimx /= scree_scale; 224 | dimy /= scree_scale; 225 | 226 | tx /= scree_scale; 227 | ty /= scree_scale; 228 | 229 | PolygonShape brick_shape = new PolygonShape(); 230 | brick_shape.setAsBox(dimx*0.5f, dimy*0.5f); 231 | 232 | PolygonShape brick_shape2 = new PolygonShape(); 233 | brick_shape2.setAsBox(dimx*0.25f, dimy*0.5f); 234 | 235 | FixtureDef fixture_def = new FixtureDef(); 236 | fixture_def.shape = brick_shape; 237 | fixture_def.density = 30; 238 | fixture_def.friction = 0.50f; 239 | fixture_def.restitution = 0.05f; 240 | 241 | BodyDef body_def = new BodyDef(); 242 | body_def.type = BodyType.DYNAMIC; 243 | body_def.angle = 0.0f; 244 | body_def.allowSleep = true; 245 | 246 | 247 | int scol = color(0); 248 | int fcol = color(224,128,64); 249 | 250 | colorMode(HSB, 360,100,100); 251 | 252 | randomSeed(1); 253 | 254 | float ox = 0; 255 | float oy = dimy/2; 256 | for(int y = 0; y < numy; y++){ 257 | 258 | float off = 0.5f; 259 | 260 | for(int x = 0; x < numx; x++){ 261 | boolean odd_row = (y & 1) == 1; 262 | 263 | ox = -numx * dimx * 0.5f; 264 | ox += odd_row ? dimx * off : 0; 265 | 266 | fixture_def.shape = brick_shape; 267 | if(!odd_row && x == 0){ 268 | fixture_def.shape = brick_shape2; 269 | ox += dimx * 0.25; 270 | } 271 | else if(odd_row && x == (numx-1)){ 272 | fixture_def.shape = brick_shape2; 273 | ox -= dimx * 0.25; 274 | } 275 | 276 | body_def.position.x = tx + ox + x * (dimx); 277 | body_def.position.y = ty + oy + y * (dimy); 278 | 279 | Body brick = world.createBody(body_def); 280 | brick.createFixture(fixture_def); 281 | 282 | float hsb_h = 20 + random(-3, 3); 283 | float hsb_s = random(70,60); 284 | float hsb_b = random(70,100); 285 | fcol = color(hsb_h, hsb_s, hsb_b); 286 | world.bodies.add(brick, true, fcol, true, scol, 0.5f); 287 | } 288 | } 289 | 290 | colorMode(RGB, 255); 291 | 292 | } 293 | 294 | 295 | 296 | 297 | 298 | public static void main(String args[]) { 299 | PApplet.main(new String[] { box2d_BrickWall.class.getName() }); 300 | } 301 | 302 | } -------------------------------------------------------------------------------- /examples/box2d_Bullet/box2d_Bullet.java: -------------------------------------------------------------------------------- 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_Bullet; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import com.thomasdiewald.liquidfun.java.interaction.DwMouseShootBullet; 19 | import com.thomasdiewald.liquidfun.java.render.DwBodyGroup; 20 | 21 | import org.jbox2d.collision.shapes.EdgeShape; 22 | import org.jbox2d.collision.shapes.PolygonShape; 23 | import org.jbox2d.common.MathUtils; 24 | import org.jbox2d.common.Vec2; 25 | import org.jbox2d.dynamics.Body; 26 | import org.jbox2d.dynamics.BodyDef; 27 | import org.jbox2d.dynamics.BodyType; 28 | import processing.core.*; 29 | import processing.opengl.PGraphics2D; 30 | 31 | 32 | public class box2d_Bullet extends PApplet { 33 | 34 | 35 | // 36 | // Bullet demo. 37 | // 38 | // Controls: 39 | // 40 | // LMB ... drag bodies 41 | // LMB + SHIFT ... shoot bullet 42 | // MMB ... add particles 43 | // RMB ... remove particles 44 | // 'r' ... reset 45 | // 't' ... update/pause physics 46 | // 'f' ... toggle debug draw 47 | // 48 | 49 | 50 | int viewport_w = 1280; 51 | int viewport_h = 720; 52 | int viewport_x = 230; 53 | int viewport_y = 0; 54 | 55 | boolean UPDATE_PHYSICS = true; 56 | boolean USE_DEBUG_DRAW = false; 57 | 58 | DwWorld world; 59 | DwBodyGroup bodies; 60 | DwMouseShootBullet bullet; 61 | 62 | public void settings(){ 63 | size(viewport_w, viewport_h, P2D); 64 | smooth(8); 65 | } 66 | 67 | public void setup(){ 68 | surface.setLocation(viewport_x, viewport_y); 69 | reset(); 70 | frameRate(120); 71 | } 72 | 73 | 74 | public void release(){ 75 | if(bodies != null) bodies .release(); bodies = null; 76 | // if(particles != null) particles.release(); particles = null; 77 | if(world != null) world .release(); world = null; } 78 | 79 | 80 | public void reset(){ 81 | // release old resources 82 | release(); 83 | 84 | world = new DwWorld(this, 22); 85 | world.transform.setScreen(width, height, 40, width/2, height-50); 86 | 87 | // Renderer 88 | bodies = new DwBodyGroup(this, world, world.transform); 89 | 90 | bullet = new DwMouseShootBullet(world, world.transform); 91 | 92 | // create scene: rigid bodies, particles, etc ... 93 | initScene(); 94 | } 95 | 96 | 97 | 98 | public void draw(){ 99 | if(UPDATE_PHYSICS){ 100 | if(frameCount % 120 == 0){ 101 | launch(); 102 | } 103 | bullet.updateSpawn(mouseX, mouseY); 104 | world.update(); 105 | } 106 | 107 | PGraphics2D canvas = (PGraphics2D) this.g; 108 | 109 | canvas.background(32); 110 | canvas.pushMatrix(); 111 | world.applyTransform(canvas); 112 | bullet.drawSpawnTrack(canvas); 113 | if(USE_DEBUG_DRAW){ 114 | world.displayDebugDraw(canvas); 115 | // DwDebugDraw.display(canvas, world); 116 | } else { 117 | bodies.display(canvas); 118 | } 119 | canvas.popMatrix(); 120 | 121 | 122 | // info 123 | int num_bodies = world.getBodyCount(); 124 | int num_particles = world.getParticleCount(); 125 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 126 | surface.setTitle(txt_fps); 127 | } 128 | 129 | 130 | 131 | 132 | 133 | 134 | ////////////////////////////////////////////////////////////////////////////// 135 | // User Interaction 136 | ////////////////////////////////////////////////////////////////////////////// 137 | public void keyReleased(){ 138 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 139 | if(key == 'r') reset(); 140 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 141 | } 142 | 143 | public void mousePressed(){ 144 | bullet.beginSpawn(mouseX, mouseY); 145 | } 146 | 147 | public void mouseReleased(){ 148 | bullet.endSpawn(mouseX, mouseY); 149 | bodies.add(bullet.popBullet(), true, color(255,32,0), true, color(0), 1f); 150 | } 151 | 152 | 153 | 154 | 155 | 156 | 157 | ////////////////////////////////////////////////////////////////////////////// 158 | // Scene Setup 159 | ////////////////////////////////////////////////////////////////////////////// 160 | 161 | Body m_body; 162 | Body m_bullet; 163 | float m_x; 164 | 165 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/BulletTest.java 166 | public void initScene() { 167 | { 168 | BodyDef bd = new BodyDef(); 169 | bd.position.set(0.0f, 0.0f); 170 | Body body = world.createBody(bd); 171 | 172 | EdgeShape edge = new EdgeShape(); 173 | 174 | edge.set(new Vec2(-10.0f, 0.0f), new Vec2(10.0f, 0.0f)); 175 | body.createFixture(edge, 0.0f); 176 | 177 | PolygonShape shape = new PolygonShape(); 178 | shape.setAsBox(0.2f, 1.0f, new Vec2(0.5f, 1.0f), 0.0f); 179 | body.createFixture(shape, 0.0f); 180 | } 181 | 182 | { 183 | BodyDef bd = new BodyDef(); 184 | bd.type = BodyType.DYNAMIC; 185 | bd.position.set(0.0f, 4.0f); 186 | 187 | PolygonShape box = new PolygonShape(); 188 | box.setAsBox(2.0f, 0.1f); 189 | 190 | m_body = world.createBody(bd); 191 | m_body.createFixture(box, 1.0f); 192 | 193 | box.setAsBox(0.25f, 0.25f); 194 | 195 | // m_x = RandomFloat(-1.0f, 1.0f); 196 | m_x = -0.06530577f; 197 | bd.position.set(m_x, 10.0f); 198 | bd.bullet = true; 199 | 200 | m_bullet = world.createBody(bd); 201 | m_bullet.createFixture(box, 100.0f); 202 | 203 | m_bullet.setLinearVelocity(new Vec2(0.0f, -50.0f)); 204 | } 205 | 206 | 207 | bodies.addAll(); 208 | } 209 | 210 | 211 | 212 | public void launch() { 213 | m_body.setTransform(new Vec2(0.0f, 4.0f), 0.0f); 214 | m_body.setLinearVelocity(new Vec2()); 215 | m_body.setAngularVelocity(0.0f); 216 | 217 | m_x = MathUtils.randomFloat(-1.0f, 1.0f); 218 | m_bullet.setTransform(new Vec2(m_x, 10.0f), 0.0f); 219 | m_bullet.setLinearVelocity(new Vec2(0.0f, -50.0f)); 220 | m_bullet.setAngularVelocity(0.0f); 221 | } 222 | 223 | 224 | 225 | public static void main(String args[]) { 226 | PApplet.main(new String[] { box2d_Bullet.class.getName() }); 227 | } 228 | 229 | } -------------------------------------------------------------------------------- /examples/box2d_Chain_RevoluteJoint/box2d_Chain_RevoluteJoint.java: -------------------------------------------------------------------------------- 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_Chain_RevoluteJoint; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.EdgeShape; 19 | import org.jbox2d.collision.shapes.PolygonShape; 20 | import org.jbox2d.common.Vec2; 21 | import org.jbox2d.dynamics.Body; 22 | import org.jbox2d.dynamics.BodyDef; 23 | import org.jbox2d.dynamics.BodyType; 24 | import org.jbox2d.dynamics.FixtureDef; 25 | import org.jbox2d.dynamics.joints.Joint; 26 | import org.jbox2d.dynamics.joints.RevoluteJointDef; 27 | 28 | import processing.core.*; 29 | import processing.opengl.PGraphics2D; 30 | 31 | 32 | public class box2d_Chain_RevoluteJoint extends PApplet { 33 | 34 | 35 | // 36 | // This examples shows how to use RevoluteJoints. 37 | // 38 | // 39 | // Controls: 40 | // 41 | // LMB ... drag bodies 42 | // LMB + SHIFT ... shoot bullet 43 | // MMB ... add particles 44 | // RMB ... remove particles 45 | // 'r' ... reset 46 | // 't' ... update/pause physics 47 | // 'f' ... toggle debug draw 48 | // 49 | 50 | int viewport_w = 1280; 51 | int viewport_h = 720; 52 | int viewport_x = 230; 53 | int viewport_y = 0; 54 | 55 | boolean UPDATE_PHYSICS = true; 56 | boolean USE_DEBUG_DRAW = false; 57 | 58 | DwWorld world; 59 | 60 | public void settings(){ 61 | size(viewport_w, viewport_h, P2D); 62 | smooth(8); 63 | } 64 | 65 | 66 | public void setup(){ 67 | surface.setLocation(viewport_x, viewport_y); 68 | reset(); 69 | frameRate(120); 70 | } 71 | 72 | 73 | public void release(){ 74 | if(world != null) world.release(); world = null; 75 | } 76 | 77 | 78 | public void reset(){ 79 | // release old resources 80 | release(); 81 | 82 | world = new DwWorld(this, 25); 83 | 84 | // create scene: rigid bodies, particles, etc ... 85 | initScene(); 86 | } 87 | 88 | 89 | 90 | public void draw(){ 91 | 92 | if(UPDATE_PHYSICS){ 93 | world.update(); 94 | } 95 | 96 | PGraphics2D canvas = (PGraphics2D) this.g; 97 | canvas.background(32); 98 | canvas.pushMatrix(); 99 | world.applyTransform(canvas); 100 | world.drawBulletSpawnTrack(canvas); 101 | if(USE_DEBUG_DRAW){ 102 | world.displayDebugDraw(canvas); 103 | // DwDebugDraw.display(canvas, world); 104 | } else { 105 | world.display(canvas); 106 | } 107 | canvas.popMatrix(); 108 | 109 | // info 110 | int num_bodies = world.getBodyCount(); 111 | int num_particles = world.getParticleCount(); 112 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 113 | surface.setTitle(txt_fps); 114 | } 115 | 116 | 117 | 118 | ////////////////////////////////////////////////////////////////////////////// 119 | // User Interaction 120 | ////////////////////////////////////////////////////////////////////////////// 121 | public void keyReleased(){ 122 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 123 | if(key == 'r') reset(); 124 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 125 | } 126 | 127 | 128 | 129 | ////////////////////////////////////////////////////////////////////////////// 130 | // Scene Setup 131 | ////////////////////////////////////////////////////////////////////////////// 132 | 133 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/Chain.java 134 | public void initScene() { 135 | 136 | Body ground = null; 137 | { 138 | BodyDef bd = new BodyDef(); 139 | ground = world.createBody(bd); 140 | 141 | EdgeShape shape = new EdgeShape(); 142 | shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); 143 | ground.createFixture(shape, 0.0f); 144 | } 145 | 146 | { 147 | float seg = 1.5f; 148 | 149 | PolygonShape shape = new PolygonShape(); 150 | shape.setAsBox(seg/2, 0.225f); 151 | 152 | FixtureDef fd = new FixtureDef(); 153 | fd.shape = shape; 154 | fd.density = 20.0f; 155 | fd.friction = 0.2f; 156 | 157 | RevoluteJointDef jd = new RevoluteJointDef(); 158 | jd.collideConnected = false; 159 | 160 | int count = 20; 161 | final float py = 25.0f; 162 | final float px = 5.0f; 163 | Body prevBody = ground; 164 | for (int i = 0; i < count; ++i) { 165 | BodyDef bd = new BodyDef(); 166 | bd.type = BodyType.DYNAMIC; 167 | bd.position.set(px + i*seg + seg/2, py); 168 | Body body = world.createBody(bd); 169 | body.createFixture(fd); 170 | 171 | Vec2 anchor = new Vec2(px + i*seg, py); 172 | jd.initialize(prevBody, body, anchor); 173 | Joint joint = world.createJoint(jd); 174 | 175 | float base = 64; 176 | float inorm = i / (float) count; 177 | float r = base + (255-base) * inorm; 178 | float g = base; 179 | float b = 255-r; 180 | world.bodies.add(joint, false, color(0), true, color(base, 255, base), 1); 181 | world.bodies.add(body, true, color(r,g,b), true, color(0), 1); 182 | 183 | prevBody = body; 184 | } 185 | } 186 | 187 | world.bodies.addAll(); 188 | } 189 | 190 | 191 | 192 | public static void main(String args[]) { 193 | PApplet.main(new String[] { box2d_Chain_RevoluteJoint.class.getName() }); 194 | } 195 | 196 | } -------------------------------------------------------------------------------- /examples/box2d_Collisions_SensorTest/box2d_Collisions_SensorTest.java: -------------------------------------------------------------------------------- 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_Collisions_SensorTest; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.CircleShape; 19 | import org.jbox2d.collision.shapes.EdgeShape; 20 | import org.jbox2d.common.Settings; 21 | import org.jbox2d.common.Vec2; 22 | import org.jbox2d.dynamics.Body; 23 | import org.jbox2d.dynamics.BodyDef; 24 | import org.jbox2d.dynamics.BodyType; 25 | import org.jbox2d.dynamics.Fixture; 26 | import org.jbox2d.dynamics.FixtureDef; 27 | import org.jbox2d.dynamics.contacts.Contact; 28 | import processing.core.*; 29 | import processing.opengl.PGraphics2D; 30 | 31 | 32 | public class box2d_Collisions_SensorTest extends PApplet { 33 | 34 | 35 | // 36 | // Collision Example. 37 | // A static circle body acts as a sensor and acts as a gravity center. 38 | // When other bodies get in contact with the sensor they are attracted to 39 | // the sensors center. 40 | // 41 | // A contact test is done by iteration through the world-contactlist. 42 | // 43 | // 44 | // Controls: 45 | // 46 | // LMB ... drag bodies 47 | // LMB + SHIFT ... shoot bullet 48 | // MMB ... add particles 49 | // RMB ... remove particles 50 | // 'r' ... reset 51 | // 't' ... update/pause physics 52 | // 'f' ... toggle debug draw 53 | // 54 | 55 | 56 | int viewport_w = 1280; 57 | int viewport_h = 720; 58 | int viewport_x = 230; 59 | int viewport_y = 0; 60 | 61 | boolean UPDATE_PHYSICS = true; 62 | boolean USE_DEBUG_DRAW = false; 63 | 64 | DwWorld world; 65 | 66 | public void settings(){ 67 | size(viewport_w, viewport_h, P2D); 68 | smooth(8); 69 | } 70 | 71 | 72 | public void setup(){ 73 | surface.setLocation(viewport_x, viewport_y); 74 | reset(); 75 | frameRate(120); 76 | } 77 | 78 | 79 | public void release(){ 80 | if(world != null) world.release(); world = null; 81 | } 82 | 83 | 84 | public void reset(){ 85 | // release old resources 86 | release(); 87 | 88 | world = new DwWorld(this, 25); 89 | 90 | // create scene: rigid bodies, particles, etc ... 91 | initScene(); 92 | } 93 | 94 | 95 | 96 | public void draw(){ 97 | 98 | if(UPDATE_PHYSICS){ 99 | updateSensor(); 100 | world.update(); 101 | } 102 | 103 | PGraphics2D canvas = (PGraphics2D) this.g; 104 | canvas.background(32); 105 | canvas.pushMatrix(); 106 | world.applyTransform(canvas); 107 | world.drawBulletSpawnTrack(canvas); 108 | if(USE_DEBUG_DRAW){ 109 | world.displayDebugDraw(canvas); 110 | // DwDebugDraw.display(canvas, world); 111 | } else { 112 | world.display(canvas); 113 | } 114 | canvas.popMatrix(); 115 | 116 | // info 117 | int num_bodies = world.getBodyCount(); 118 | int num_particles = world.getParticleCount(); 119 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 120 | surface.setTitle(txt_fps); 121 | } 122 | 123 | 124 | 125 | ////////////////////////////////////////////////////////////////////////////// 126 | // User Interaction 127 | ////////////////////////////////////////////////////////////////////////////// 128 | public void keyReleased(){ 129 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 130 | if(key == 'r') reset(); 131 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 132 | } 133 | 134 | 135 | 136 | 137 | ////////////////////////////////////////////////////////////////////////////// 138 | // Scene Setup 139 | ////////////////////////////////////////////////////////////////////////////// 140 | 141 | 142 | Fixture m_sensor; 143 | 144 | // mod of the original vesion 145 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/SensorTest.java 146 | public void initScene() { 147 | 148 | { 149 | BodyDef bd = new BodyDef(); 150 | Body ground = world.createBody(bd); 151 | 152 | { // floor 153 | EdgeShape shape = new EdgeShape(); 154 | shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); 155 | ground.createFixture(shape, 0.0f); 156 | } 157 | 158 | { // sensor 159 | CircleShape shape = new CircleShape(); 160 | shape.m_radius = 5.0f; 161 | shape.m_p.set(0.0f, 10.0f); 162 | 163 | FixtureDef fd = new FixtureDef(); 164 | fd.shape = shape; 165 | fd.isSensor = true; 166 | m_sensor = ground.createFixture(fd); 167 | } 168 | world.bodies.add(ground, true, color(255), true, color(0), 1f); 169 | } 170 | 171 | { 172 | BodyDef bd = new BodyDef(); 173 | bd.type = BodyType.DYNAMIC; 174 | 175 | CircleShape shape = new CircleShape(); 176 | shape.m_radius = 1.0f; 177 | 178 | for (int i = 0; i < 10; ++i) { 179 | bd.position.set(-10.0f + 3.0f * i, 20.0f); 180 | Body body = world.createBody(bd); 181 | body.createFixture(shape, 1.0f); 182 | world.bodies.add(body, true, color(0,255,0), true, color(0), 1f); 183 | } 184 | } 185 | 186 | world.bodies.addAll(); 187 | } 188 | 189 | 190 | 191 | public void updateSensor(){ 192 | 193 | Body bsensor = m_sensor.getBody(); 194 | CircleShape circle = (CircleShape) m_sensor.getShape(); 195 | Vec2 sensor_pos = bsensor.getWorldPoint(circle.m_p); 196 | 197 | // iterate through all contacts and apply a force on shapes that overlap the sensor. 198 | for(Contact contact = world.getContactList(); contact != null; contact = contact.m_next){ 199 | 200 | Fixture fixtureA = contact.getFixtureA(); 201 | Fixture fixtureB = contact.getFixtureB(); 202 | 203 | Body body = null; 204 | if(fixtureA == m_sensor) body = fixtureB.getBody(); 205 | else if(fixtureB == m_sensor) body = fixtureA.getBody(); 206 | else continue; 207 | 208 | Vec2 body_pos = body.getPosition(); 209 | Vec2 dist = sensor_pos.sub(body_pos); 210 | if (dist.lengthSquared() > Settings.EPSILON * Settings.EPSILON) { 211 | dist.normalize(); 212 | Vec2 force = dist.mulLocal(200f); 213 | body.applyForce(force, body_pos); 214 | } 215 | } 216 | } 217 | 218 | 219 | 220 | public static void main(String args[]) { 221 | PApplet.main(new String[] { box2d_Collisions_SensorTest.class.getName() }); 222 | } 223 | 224 | } -------------------------------------------------------------------------------- /examples/box2d_Collisions_SensorTestCallback/box2d_Collisions_SensorTestCallback.java: -------------------------------------------------------------------------------- 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_Collisions_SensorTestCallback; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import com.thomasdiewald.liquidfun.java.render.DwBody; 19 | 20 | import org.jbox2d.callbacks.ContactImpulse; 21 | import org.jbox2d.callbacks.ContactListener; 22 | import org.jbox2d.collision.Manifold; 23 | import org.jbox2d.collision.shapes.CircleShape; 24 | import org.jbox2d.collision.shapes.EdgeShape; 25 | import org.jbox2d.common.Settings; 26 | import org.jbox2d.common.Vec2; 27 | import org.jbox2d.dynamics.Body; 28 | import org.jbox2d.dynamics.BodyDef; 29 | import org.jbox2d.dynamics.BodyType; 30 | import org.jbox2d.dynamics.Fixture; 31 | import org.jbox2d.dynamics.FixtureDef; 32 | import org.jbox2d.dynamics.contacts.Contact; 33 | 34 | import processing.core.*; 35 | import processing.opengl.PGraphics2D; 36 | 37 | 38 | public class box2d_Collisions_SensorTestCallback extends PApplet { 39 | 40 | 41 | // 42 | // Collision Example. 43 | // A static circle body acts as a sensor and acts as a gravity center. 44 | // When other bodies get in contact with the sensor they are attracted to 45 | // the sensors center. 46 | // 47 | // A contact test is done by implementing a ContactListener. 48 | // 49 | // 50 | // Controls: 51 | // 52 | // LMB ... drag bodies 53 | // LMB + SHIFT ... shoot bullet 54 | // MMB ... add particles 55 | // RMB ... remove particles 56 | // 'r' ... reset 57 | // 't' ... update/pause physics 58 | // 'f' ... toggle debug draw 59 | // 60 | 61 | 62 | int viewport_w = 1280; 63 | int viewport_h = 720; 64 | int viewport_x = 230; 65 | int viewport_y = 0; 66 | 67 | boolean UPDATE_PHYSICS = true; 68 | boolean USE_DEBUG_DRAW = false; 69 | 70 | DwWorld world; 71 | 72 | public void settings(){ 73 | size(viewport_w, viewport_h, P2D); 74 | smooth(8); 75 | } 76 | 77 | 78 | public void setup(){ 79 | surface.setLocation(viewport_x, viewport_y); 80 | reset(); 81 | frameRate(120); 82 | } 83 | 84 | 85 | public void release(){ 86 | if(world != null) world.release(); world = null; 87 | } 88 | 89 | 90 | public void reset(){ 91 | // release old resources 92 | release(); 93 | 94 | world = new DwWorld(this, 25); 95 | 96 | // create scene: rigid bodies, particles, etc ... 97 | initScene(); 98 | } 99 | 100 | 101 | 102 | public void draw(){ 103 | 104 | if(UPDATE_PHYSICS){ 105 | updateSensor(); 106 | world.update(); 107 | } 108 | 109 | PGraphics2D canvas = (PGraphics2D) this.g; 110 | canvas.background(32); 111 | canvas.pushMatrix(); 112 | world.applyTransform(canvas); 113 | world.drawBulletSpawnTrack(canvas); 114 | if(USE_DEBUG_DRAW){ 115 | world.displayDebugDraw(canvas); 116 | // DwDebugDraw.display(canvas, world); 117 | } else { 118 | world.display(canvas); 119 | } 120 | canvas.popMatrix(); 121 | 122 | // info 123 | int num_bodies = world.getBodyCount(); 124 | int num_particles = world.getParticleCount(); 125 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 126 | surface.setTitle(txt_fps); 127 | } 128 | 129 | 130 | 131 | ////////////////////////////////////////////////////////////////////////////// 132 | // User Interaction 133 | ////////////////////////////////////////////////////////////////////////////// 134 | public void keyReleased(){ 135 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 136 | if(key == 'r') reset(); 137 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 138 | } 139 | 140 | 141 | 142 | 143 | ////////////////////////////////////////////////////////////////////////////// 144 | // Scene Setup 145 | ////////////////////////////////////////////////////////////////////////////// 146 | 147 | Fixture m_sensor; 148 | 149 | // mod of the original vesion 150 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/SensorTest.java 151 | public void initScene() { 152 | 153 | { 154 | BodyDef bd = new BodyDef(); 155 | Body ground = world.createBody(bd); 156 | 157 | { // floor 158 | EdgeShape shape = new EdgeShape(); 159 | shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); 160 | ground.createFixture(shape, 0.0f); 161 | } 162 | 163 | { // sensor 164 | CircleShape shape = new CircleShape(); 165 | shape.m_radius = 5.0f; 166 | shape.m_p.set(0.0f, 10.0f); 167 | FixtureDef fd = new FixtureDef(); 168 | fd.shape = shape; 169 | fd.isSensor = true; 170 | m_sensor = ground.createFixture(fd); 171 | } 172 | 173 | world.bodies.add(ground, true, color(255), true, color(0), 1f); 174 | } 175 | 176 | { 177 | BodyDef bd = new BodyDef(); 178 | bd.type = BodyType.DYNAMIC; 179 | 180 | CircleShape shape = new CircleShape(); 181 | shape.m_radius = 1.0f; 182 | 183 | for (int i = 0; i < 10; ++i) { 184 | bd.position.set(-10.0f + 3.0f * i, 20.0f); 185 | Body body = world.createBody(bd); 186 | body.createFixture(shape, 1.0f); 187 | 188 | DwBody dwbody = world.bodies.add(body, true, color(0,255,0), true, color(0), 1f); 189 | dwbody.m_userData = (Boolean) false; 190 | } 191 | } 192 | 193 | world.setContactListener(new MyContactListener()); 194 | } 195 | 196 | 197 | class MyContactListener implements ContactListener{ 198 | 199 | void enableSensorAttraction(Fixture fixture, boolean enable){ 200 | DwBody dwbody = DwWorld.getShape(fixture.getBody()); 201 | if(dwbody != null){ 202 | if(dwbody.m_userData instanceof Boolean){ 203 | dwbody.m_userData = enable; 204 | } 205 | } 206 | } 207 | 208 | @Override 209 | public void beginContact(Contact contact) { 210 | Fixture fixtureA = contact.getFixtureA(); 211 | Fixture fixtureB = contact.getFixtureB(); 212 | if (fixtureA == m_sensor) enableSensorAttraction(fixtureB, true); 213 | if (fixtureB == m_sensor) enableSensorAttraction(fixtureA, true); 214 | } 215 | 216 | @Override 217 | public void endContact(Contact contact) { 218 | Fixture fixtureA = contact.getFixtureA(); 219 | Fixture fixtureB = contact.getFixtureB(); 220 | if (fixtureA == m_sensor) enableSensorAttraction(fixtureB, false); 221 | if (fixtureB == m_sensor) enableSensorAttraction(fixtureA, false); 222 | } 223 | 224 | @Override 225 | public void preSolve(Contact contact, Manifold oldManifold) { 226 | } 227 | 228 | @Override 229 | public void postSolve(Contact contact, ContactImpulse impulse) { 230 | } 231 | 232 | } 233 | 234 | 235 | 236 | public void updateSensor() { 237 | 238 | Body bsensor = m_sensor.getBody(); 239 | CircleShape circle = (CircleShape) m_sensor.getShape(); 240 | Vec2 sensor_pos = bsensor.getWorldPoint(circle.m_p); 241 | 242 | // Traverse the bodies. Apply a force on shapes that overlap the sensor. 243 | for (Body body = world.getBodyList(); body != null; body = body.getNext()) { 244 | if(body == bsensor){ 245 | continue; 246 | } 247 | 248 | boolean is_touching = false; 249 | DwBody dwbody = DwWorld.getShape(body); 250 | if(dwbody != null){ 251 | if(dwbody.m_userData instanceof Boolean){ 252 | is_touching = (Boolean) dwbody.m_userData; 253 | } 254 | } 255 | 256 | 257 | if (is_touching) { 258 | Vec2 body_pos = body.getPosition(); 259 | 260 | Vec2 dist = sensor_pos.sub(body_pos); 261 | if (dist.lengthSquared() > Settings.EPSILON * Settings.EPSILON) { 262 | dist.normalize(); 263 | Vec2 force = dist.mulLocal(200f); 264 | body.applyForce(force, body_pos); 265 | } 266 | } 267 | } 268 | } 269 | 270 | 271 | 272 | 273 | 274 | 275 | public static void main(String args[]) { 276 | PApplet.main(new String[] { box2d_Collisions_SensorTestCallback.class.getName() }); 277 | } 278 | 279 | } -------------------------------------------------------------------------------- /examples/box2d_DominoTower/box2d_DominoTower.java: -------------------------------------------------------------------------------- 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_DominoTower; 15 | 16 | import com.thomasdiewald.liquidfun.java.DwWorld; 17 | 18 | import org.jbox2d.collision.shapes.PolygonShape; 19 | import org.jbox2d.common.Vec2; 20 | import org.jbox2d.dynamics.Body; 21 | import org.jbox2d.dynamics.BodyDef; 22 | import org.jbox2d.dynamics.BodyType; 23 | import org.jbox2d.dynamics.FixtureDef; 24 | 25 | import processing.core.*; 26 | import processing.opengl.PGraphics2D; 27 | 28 | 29 | public class box2d_DominoTower extends PApplet { 30 | 31 | // 32 | // Domino stacking example. 33 | // 34 | // Controls: 35 | // 36 | // LMB ... drag bodies 37 | // LMB + SHIFT ... shoot bullet 38 | // MMB ... add particles 39 | // RMB ... remove particles 40 | // 'r' ... reset 41 | // 't' ... update/pause physics 42 | // 'f' ... toggle debug draw 43 | // 44 | 45 | 46 | int viewport_w = 1280; 47 | int viewport_h = 720; 48 | int viewport_x = 230; 49 | int viewport_y = 0; 50 | 51 | boolean UPDATE_PHYSICS = true; 52 | boolean USE_DEBUG_DRAW = false; 53 | 54 | DwWorld world; 55 | 56 | 57 | public void settings(){ 58 | size(viewport_w, viewport_h, P2D); 59 | smooth(8); 60 | } 61 | 62 | public void setup(){ 63 | surface.setLocation(viewport_x, viewport_y); 64 | reset(); 65 | frameRate(120); 66 | } 67 | 68 | 69 | public void release(){ 70 | if(world != null) world.release(); world = null; 71 | } 72 | 73 | public void reset(){ 74 | // release old resources 75 | release(); 76 | 77 | world = new DwWorld(this, 20); 78 | 79 | 80 | // create scene: rigid bodies, particles, etc ... 81 | initScene(); 82 | } 83 | 84 | 85 | 86 | public void draw(){ 87 | 88 | if(UPDATE_PHYSICS){ 89 | world.update(); 90 | } 91 | 92 | 93 | PGraphics2D canvas = (PGraphics2D) this.g; 94 | canvas.background(32); 95 | canvas.pushMatrix(); 96 | world.applyTransform(canvas); 97 | world.drawBulletSpawnTrack(canvas); 98 | if(USE_DEBUG_DRAW){ 99 | world.displayDebugDraw(canvas); 100 | // DwDebugDraw.display(canvas, world); 101 | } else { 102 | world.display(canvas); 103 | } 104 | canvas.popMatrix(); 105 | 106 | // info 107 | int num_bodies = world.getBodyCount(); 108 | int num_particles = world.getParticleCount(); 109 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 110 | surface.setTitle(txt_fps); 111 | } 112 | 113 | 114 | 115 | 116 | 117 | ////////////////////////////////////////////////////////////////////////////// 118 | // User Interaction 119 | ////////////////////////////////////////////////////////////////////////////// 120 | 121 | public void keyReleased(){ 122 | if(key == 'r') reset(); 123 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 124 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 125 | } 126 | 127 | 128 | 129 | ////////////////////////////////////////////////////////////////////////////// 130 | // Scene Setup 131 | ////////////////////////////////////////////////////////////////////////////// 132 | 133 | final float dwidth = .20f; 134 | final float dheight = 1.0f; 135 | float ddensity;// = 10f; 136 | final float dfriction = 0.1f; 137 | int baseCount = 25; 138 | 139 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/DominoTower.java 140 | public void initScene() { 141 | 142 | float screen_scale = world.transform.screen_scale; 143 | float dimx = world.transform.box2d_dimx; 144 | float dimy = world.transform.box2d_dimy; 145 | float thick = 20 / screen_scale; 146 | 147 | { // Floor 148 | 149 | BodyDef bd = new BodyDef(); 150 | Body ground = world.createBody(bd); 151 | 152 | PolygonShape sd = new PolygonShape(); 153 | 154 | sd.setAsBox(dimx/2, thick); 155 | ground.createFixture(sd, 0); 156 | 157 | sd.setAsBox(thick, dimy/2, new Vec2(-dimx/2, dimy/2), 0); 158 | ground.createFixture(sd, 0); 159 | 160 | sd.setAsBox(thick, dimy/2, new Vec2(+dimx/2, dimy/2), 0); 161 | ground.createFixture(sd, 0); 162 | 163 | world.bodies.add(ground, true, color(0), false, color(0), 1f); 164 | } 165 | 166 | { // Bullets 167 | 168 | Body bullet1; 169 | Body bullet2; 170 | 171 | ddensity = 10f; 172 | 173 | PolygonShape sd = new PolygonShape(); 174 | sd.setAsBox(.7f, .7f); 175 | 176 | BodyDef bd = new BodyDef(); 177 | bd.type = BodyType.DYNAMIC; 178 | bd.bullet = true; 179 | 180 | FixtureDef fd = new FixtureDef(); 181 | fd.shape = sd; 182 | fd.friction = 0f; 183 | fd.restitution = 0.85f; 184 | 185 | fd.density = 25f; 186 | bd.position = new Vec2(30f, 50f); 187 | bullet1 = world.createBody(bd); 188 | bullet1.createFixture(fd); 189 | bullet1.setLinearVelocity(new Vec2(-25f, -25f)); 190 | bullet1.setAngularVelocity(6.7f); 191 | 192 | fd.density = 25f; 193 | bd.position = new Vec2(-30, 25f); 194 | bullet2 = world.createBody(bd); 195 | bullet2.createFixture(fd); 196 | bullet2.setLinearVelocity(new Vec2(35f, -10f)); 197 | bullet2.setAngularVelocity(-8.3f); 198 | 199 | world.bodies.add(bullet1, true, color(255), false, color(0), 1f); 200 | world.bodies.add(bullet2, true, color(255), false, color(0), 1f); 201 | } 202 | 203 | { 204 | float currX; 205 | // Make base 206 | for (int i = 0; i < baseCount; ++i) { 207 | currX = i * 1.5f * dheight - (1.5f * dheight * baseCount / 2f); 208 | makeDomino(currX, dheight / 2.0f, false); 209 | makeDomino(currX, dheight + dwidth / 2.0f, true); 210 | } 211 | currX = baseCount * 1.5f * dheight - (1.5f * dheight * baseCount / 2f); 212 | // Make 'I's 213 | for (int j = 1; j < baseCount; ++j) { 214 | if (j > 3) ddensity *= .8f; 215 | float currY = dheight * .5f + (dheight + 2f * dwidth) * .99f * j; // y at center of 'I'structure 216 | 217 | for (int i = 0; i < baseCount - j; ++i) { 218 | currX = i * 1.5f * dheight - (1.5f * dheight * (baseCount - j) / 2f);// +parent.random(-.05f,.05f); 219 | ddensity *= 2.5f; 220 | if (i == 0) { 221 | makeDomino(currX - (1.25f * dheight) + .5f * dwidth, currY - dwidth, false); 222 | } 223 | if (i == baseCount - j - 1) { 224 | // if (j != 1) //djm: why is this here? it makes it off balance 225 | makeDomino(currX + (1.25f * dheight) - .5f * dwidth, currY - dwidth, false); 226 | } 227 | ddensity /= 2.5f; 228 | makeDomino(currX, currY, false); 229 | makeDomino(currX, currY + .5f * (dwidth + dheight), true); 230 | makeDomino(currX, currY - .5f * (dwidth + dheight), true); 231 | } 232 | } 233 | } 234 | 235 | } 236 | 237 | 238 | int count = 0; 239 | public void makeDomino(float x, float y, boolean horizontal) { 240 | 241 | float thick = 20 / world.transform.screen_scale; 242 | y += thick; 243 | 244 | PolygonShape sd = new PolygonShape(); 245 | sd.setAsBox(.5f * dwidth, .5f * dheight); 246 | FixtureDef fd = new FixtureDef(); 247 | fd.shape = sd; 248 | fd.density = ddensity; 249 | BodyDef bd = new BodyDef(); 250 | bd.type = BodyType.DYNAMIC; 251 | fd.friction = dfriction; 252 | fd.restitution = 0.65f; 253 | bd.position = new Vec2(x, y); 254 | bd.angle = horizontal ? (float) (Math.PI / 2.0) : 0f; 255 | Body myBody = world.createBody(bd); 256 | myBody.createFixture(fd); 257 | 258 | 259 | colorMode(HSB, 360, 100, 100); 260 | int ch = (count/5) % 360; 261 | int cs = 100; 262 | int cb = 100; 263 | if(horizontal) cb = 50; 264 | int fcol = color(ch, cs, cb); 265 | int scol = color(ch, cs*0.5f, cb*0.5f, 128); 266 | world.bodies.add(myBody, true, fcol, true, scol, 1f); 267 | colorMode(RGB, 255); 268 | 269 | count++; 270 | } 271 | 272 | 273 | 274 | 275 | public static void main(String args[]) { 276 | PApplet.main(new String[] { box2d_DominoTower.class.getName() }); 277 | } 278 | 279 | } -------------------------------------------------------------------------------- /examples/box2d_Dominos/box2d_Dominos.java: -------------------------------------------------------------------------------- 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_Dominos; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.PolygonShape; 19 | import org.jbox2d.common.Vec2; 20 | import org.jbox2d.dynamics.Body; 21 | import org.jbox2d.dynamics.BodyDef; 22 | import org.jbox2d.dynamics.BodyType; 23 | import org.jbox2d.dynamics.FixtureDef; 24 | 25 | import processing.core.*; 26 | import processing.opengl.PGraphics2D; 27 | 28 | 29 | public class box2d_Dominos extends PApplet { 30 | 31 | // 32 | // Domino example. 33 | // 34 | // Controls: 35 | // 36 | // LMB ... drag bodies 37 | // LMB + SHIFT ... shoot bullet 38 | // MMB ... add particles 39 | // RMB ... remove particles 40 | // 'r' ... reset 41 | // 't' ... update/pause physics 42 | // 'f' ... toggle debug draw 43 | // 44 | 45 | int viewport_w = 1280; 46 | int viewport_h = 720; 47 | int viewport_x = 230; 48 | int viewport_y = 0; 49 | 50 | boolean UPDATE_PHYSICS = true; 51 | boolean USE_DEBUG_DRAW = false; 52 | 53 | DwWorld world; 54 | 55 | public void settings(){ 56 | size(viewport_w, viewport_h, P2D); 57 | smooth(8); 58 | } 59 | 60 | 61 | public void setup(){ 62 | surface.setLocation(viewport_x, viewport_y); 63 | reset(); 64 | frameRate(120); 65 | } 66 | 67 | 68 | public void release(){ 69 | if(world != null) world.release(); world = null; 70 | } 71 | 72 | 73 | public void reset(){ 74 | // release old resources 75 | release(); 76 | 77 | world = new DwWorld(this, 25); 78 | 79 | // create scene: rigid bodies, particles, etc ... 80 | initScene(); 81 | } 82 | 83 | 84 | 85 | public void draw(){ 86 | 87 | if(UPDATE_PHYSICS){ 88 | world.update(); 89 | } 90 | 91 | PGraphics2D canvas = (PGraphics2D) this.g; 92 | canvas.background(32); 93 | canvas.pushMatrix(); 94 | world.applyTransform(canvas); 95 | world.drawBulletSpawnTrack(canvas); 96 | if(USE_DEBUG_DRAW){ 97 | world.displayDebugDraw(canvas); 98 | // DwDebugDraw.display(canvas, world); 99 | } else { 100 | world.display(canvas); 101 | } 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 | } 121 | 122 | 123 | 124 | ////////////////////////////////////////////////////////////////////////////// 125 | // Scene Setup 126 | ////////////////////////////////////////////////////////////////////////////// 127 | 128 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/DominoTest.java 129 | public void initScene() { 130 | 131 | float screen_scale = world.transform.screen_scale; 132 | float dimx = world.transform.box2d_dimx; 133 | float dimy = world.transform.box2d_dimy; 134 | float thick = 20 / screen_scale; 135 | 136 | { // Floor 137 | 138 | BodyDef bd = new BodyDef(); 139 | Body ground = world.createBody(bd); 140 | 141 | PolygonShape sd = new PolygonShape(); 142 | 143 | sd.setAsBox(dimx/2, thick); 144 | ground.createFixture(sd, 0); 145 | 146 | sd.setAsBox(thick, dimy/2, new Vec2(-dimx/2, dimy/2), 0); 147 | ground.createFixture(sd, 0); 148 | 149 | sd.setAsBox(thick, dimy/2, new Vec2(+dimx/2, dimy/2), 0); 150 | ground.createFixture(sd, 0); 151 | 152 | world.bodies.add(ground, true, color(0), false, color(0), 1f); 153 | } 154 | 155 | { // Platforms 156 | for (int i = 0; i < 4; i++) { 157 | FixtureDef fd = new FixtureDef(); 158 | PolygonShape sd = new PolygonShape(); 159 | sd.setAsBox(15.0f, 0.125f); 160 | fd.shape = sd; 161 | 162 | BodyDef bd = new BodyDef(); 163 | bd.position = new Vec2(0.0f, 5f + 5f * i); 164 | Body body = world.createBody(bd); 165 | body.createFixture(fd); 166 | 167 | world.bodies.add(body, true, color(0), false, color(0), 1f); 168 | } 169 | } 170 | 171 | { // Dominos 172 | FixtureDef fd = new FixtureDef(); 173 | PolygonShape sd = new PolygonShape(); 174 | sd.setAsBox(0.125f, 2f); 175 | fd.shape = sd; 176 | fd.density = 25.0f; 177 | 178 | BodyDef bd = new BodyDef(); 179 | bd.type = BodyType.DYNAMIC; 180 | float friction = .5f; 181 | int num_col = 4; 182 | int num_row = 25; 183 | 184 | colorMode(HSB, 360, 100, 100); 185 | 186 | for (int i = 0; i < num_col; ++i) { 187 | for (int j = 0; j < num_row; j++) { 188 | fd.friction = friction; 189 | bd.position = new Vec2(-14.75f + j * (29.5f / (num_row - 1)), 7.3f + 5f * i); 190 | if (i == 2 && j == 0) { 191 | bd.angle = -0.1f; 192 | bd.position.x += .1f; 193 | } else if (i == 3 && j == num_row - 1) { 194 | bd.angle = .1f; 195 | bd.position.x -= .1f; 196 | } else 197 | bd.angle = 0f; 198 | Body bdomino = world.createBody(bd); 199 | bdomino.createFixture(fd); 200 | 201 | // create shape, and define individual fill 202 | int hue = (int) ((i * num_row + j) / (float)(num_col * num_row) * 360); 203 | int fcol = color(hue, 100, 100); 204 | int scol = color(hue, 50, 50, 128); 205 | 206 | world.bodies.add(bdomino, true, fcol, true, scol, 1f); 207 | } 208 | } 209 | 210 | colorMode(RGB, 255); 211 | } 212 | 213 | } 214 | 215 | 216 | 217 | public static void main(String args[]) { 218 | PApplet.main(new String[] { box2d_Dominos.class.getName() }); 219 | } 220 | 221 | } -------------------------------------------------------------------------------- /examples/box2d_MobileBalanced/box2d_MobileBalanced.java: -------------------------------------------------------------------------------- 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_MobileBalanced; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.PolygonShape; 19 | import org.jbox2d.common.Vec2; 20 | import org.jbox2d.dynamics.Body; 21 | import org.jbox2d.dynamics.BodyDef; 22 | import org.jbox2d.dynamics.BodyType; 23 | import org.jbox2d.dynamics.Fixture; 24 | import org.jbox2d.dynamics.joints.RevoluteJointDef; 25 | 26 | import processing.core.*; 27 | import processing.opengl.PGraphics2D; 28 | 29 | 30 | public class box2d_MobileBalanced extends PApplet { 31 | 32 | // 33 | // A balanced binary tree. 34 | // The Edges are made of bodies, the nodes are made or RevoluteJoints. 35 | // 36 | // 37 | // Controls: 38 | // 39 | // LMB ... drag bodies 40 | // LMB + SHIFT ... shoot bullet 41 | // MMB ... add particles 42 | // RMB ... remove particles 43 | // 'r' ... reset 44 | // 't' ... update/pause physics 45 | // 'f' ... toggle debug draw 46 | // 47 | 48 | int viewport_w = 1280; 49 | int viewport_h = 720; 50 | int viewport_x = 230; 51 | int viewport_y = 0; 52 | 53 | boolean UPDATE_PHYSICS = true; 54 | boolean USE_DEBUG_DRAW = false; 55 | 56 | DwWorld world; 57 | 58 | public void settings(){ 59 | size(viewport_w, viewport_h, P2D); 60 | smooth(8); 61 | } 62 | 63 | public void setup(){ 64 | surface.setLocation(viewport_x, viewport_y); 65 | reset(); 66 | frameRate(120); 67 | } 68 | 69 | 70 | public void release(){ 71 | if(world != null) world.release(); world = null; 72 | } 73 | 74 | 75 | public void reset(){ 76 | // release old resources 77 | release(); 78 | 79 | world = new DwWorld(this, 50); 80 | world.transform.setCamera(0, 18, 50); 81 | 82 | // create scene: rigid bodies, particles, etc ... 83 | initScene(); 84 | } 85 | 86 | 87 | 88 | public void draw(){ 89 | 90 | if(UPDATE_PHYSICS){ 91 | world.update(); 92 | } 93 | 94 | 95 | PGraphics2D canvas = (PGraphics2D) this.g; 96 | canvas.background(32); 97 | canvas.pushMatrix(); 98 | world.applyTransform(canvas); 99 | world.drawBulletSpawnTrack(canvas); 100 | if(USE_DEBUG_DRAW){ 101 | world.displayDebugDraw(canvas); 102 | // DwDebugDraw.display(canvas, world); 103 | } else { 104 | world.display(canvas); 105 | } 106 | canvas.popMatrix(); 107 | 108 | 109 | // info 110 | int num_bodies = world.getBodyCount(); 111 | int num_particles = world.getParticleCount(); 112 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 113 | surface.setTitle(txt_fps); 114 | } 115 | 116 | 117 | 118 | 119 | 120 | 121 | ////////////////////////////////////////////////////////////////////////////// 122 | // User Interaction 123 | ////////////////////////////////////////////////////////////////////////////// 124 | public void keyReleased(){ 125 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 126 | if(key == 'r') reset(); 127 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 128 | } 129 | 130 | 131 | 132 | 133 | ////////////////////////////////////////////////////////////////////////////// 134 | // Scene Setup 135 | ////////////////////////////////////////////////////////////////////////////// 136 | 137 | 138 | int e_depth = 6; 139 | 140 | // https://github.com/erincatto/Box2D/blob/master/Box2D/Testbed/Tests/MobileBalanced.h 141 | public void initScene() { 142 | Body ground = null; 143 | { 144 | BodyDef bd = new BodyDef(); 145 | bd.position.set(0.0f, 20.0f); 146 | ground = world.createBody(bd); 147 | } 148 | 149 | float a = 0.5f; 150 | Vec2 h = new Vec2(0.0f, a); 151 | 152 | colorMode(HSB, 1f); 153 | 154 | Body root = AddNode(ground, new Vec2(), 0, 3.0f, a); 155 | 156 | colorMode(RGB, 255); 157 | 158 | RevoluteJointDef jointDef = new RevoluteJointDef(); 159 | jointDef.bodyA = ground; 160 | jointDef.bodyB = root; 161 | jointDef.localAnchorA.setZero(); 162 | jointDef.localAnchorB = h; 163 | world.createJoint(jointDef); 164 | 165 | world.bodies.addAll(); 166 | } 167 | 168 | 169 | Body AddNode(Body parent, Vec2 localAnchor, int depth, float offset, float a){ 170 | 171 | a *= 0.90f; 172 | 173 | float fdepth = 1 - depth / (float) (e_depth+1); 174 | float hue = 220 / 360f; 175 | 176 | float density = 20.0f; 177 | Vec2 h = new Vec2(0.0f, a); 178 | 179 | Vec2 p = parent.getPosition().add(localAnchor).sub(h); 180 | 181 | BodyDef bodyDef = new BodyDef(); 182 | bodyDef.type = BodyType.DYNAMIC; 183 | bodyDef.position = p; 184 | Body body = world.createBody(bodyDef); 185 | world.bodies.add(body, true, color(0), true, color(0), 1f); 186 | 187 | PolygonShape shape = new PolygonShape(); 188 | shape.setAsBox(0.25f * a, a); 189 | Fixture fixture1 = body.createFixture(shape, density); 190 | world.bodies.add(fixture1, true, color(hue, fdepth, 1), true, color(0), 1f); 191 | 192 | if (depth == e_depth){ 193 | return body; 194 | } 195 | 196 | shape.setAsBox(offset, 0.25f * a, new Vec2(0, -a), 0.0f); 197 | Fixture fixture2 = body.createFixture(shape, density); 198 | world.bodies.add(fixture2, true, color(hue, fdepth, 1), true, color(0), 1f); 199 | 200 | Vec2 a1 = new Vec2(offset, -a); 201 | Vec2 a2 = new Vec2(-offset, -a); 202 | Body body1 = AddNode(body, a1, depth + 1, 0.5f * offset, a); 203 | Body body2 = AddNode(body, a2, depth + 1, 0.5f * offset, a); 204 | 205 | RevoluteJointDef jointDef = new RevoluteJointDef(); 206 | jointDef.bodyA = body; 207 | jointDef.localAnchorB = h; 208 | 209 | jointDef.localAnchorA = a1; 210 | jointDef.bodyB = body1; 211 | world.createJoint(jointDef); 212 | 213 | jointDef.localAnchorA = a2; 214 | jointDef.bodyB = body2; 215 | world.createJoint(jointDef); 216 | 217 | return body; 218 | } 219 | 220 | 221 | 222 | 223 | public static void main(String args[]) { 224 | PApplet.main(new String[] { box2d_MobileBalanced.class.getName() }); 225 | } 226 | 227 | } -------------------------------------------------------------------------------- /examples/box2d_PulleyJoint/box2d_PulleyJoint.java: -------------------------------------------------------------------------------- 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_PulleyJoint; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | 19 | import org.jbox2d.collision.shapes.CircleShape; 20 | import org.jbox2d.collision.shapes.EdgeShape; 21 | import org.jbox2d.collision.shapes.PolygonShape; 22 | import org.jbox2d.common.Vec2; 23 | import org.jbox2d.dynamics.Body; 24 | import org.jbox2d.dynamics.BodyDef; 25 | import org.jbox2d.dynamics.BodyType; 26 | import org.jbox2d.dynamics.joints.Joint; 27 | import org.jbox2d.dynamics.joints.PulleyJoint; 28 | import org.jbox2d.dynamics.joints.PulleyJointDef; 29 | import processing.core.*; 30 | import processing.opengl.PGraphics2D; 31 | 32 | 33 | public class box2d_PulleyJoint extends PApplet { 34 | 35 | // 36 | // This examples shows how to use PulleyJoints. 37 | // 38 | // Controls: 39 | // 40 | // LMB ... drag bodies 41 | // LMB + SHIFT ... shoot bullet 42 | // MMB ... add particles 43 | // RMB ... remove particles 44 | // 'r' ... reset 45 | // 't' ... update/pause physics 46 | // 'f' ... toggle debug draw 47 | // 48 | 49 | int viewport_w = 1280; 50 | int viewport_h = 720; 51 | int viewport_x = 230; 52 | int viewport_y = 0; 53 | 54 | boolean UPDATE_PHYSICS = true; 55 | boolean USE_DEBUG_DRAW = false; 56 | 57 | DwWorld world; 58 | 59 | public void settings(){ 60 | size(viewport_w, viewport_h, P2D); 61 | smooth(8); 62 | } 63 | 64 | 65 | public void setup(){ 66 | surface.setLocation(viewport_x, viewport_y); 67 | reset(); 68 | frameRate(120); 69 | } 70 | 71 | 72 | public void release(){ 73 | if(world != null) world.release(); world = null; 74 | } 75 | 76 | 77 | public void reset(){ 78 | // release old resources 79 | release(); 80 | 81 | world = new DwWorld(this, 20); 82 | 83 | // create scene: rigid bodies, particles, etc ... 84 | initScene(); 85 | } 86 | 87 | 88 | 89 | public void draw(){ 90 | 91 | if(UPDATE_PHYSICS){ 92 | world.update(); 93 | } 94 | 95 | PGraphics2D canvas = (PGraphics2D) this.g; 96 | canvas.background(32); 97 | canvas.pushMatrix(); 98 | world.applyTransform(canvas); 99 | world.drawBulletSpawnTrack(canvas); 100 | if(USE_DEBUG_DRAW){ 101 | world.displayDebugDraw(canvas); 102 | // DwDebugDraw.display(canvas, world); 103 | } else { 104 | world.display(canvas); 105 | } 106 | canvas.popMatrix(); 107 | 108 | // info 109 | int num_bodies = world.getBodyCount(); 110 | int num_particles = world.getParticleCount(); 111 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 112 | surface.setTitle(txt_fps); 113 | } 114 | 115 | 116 | 117 | ////////////////////////////////////////////////////////////////////////////// 118 | // User Interaction 119 | ////////////////////////////////////////////////////////////////////////////// 120 | public void keyReleased(){ 121 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 122 | if(key == 'r') reset(); 123 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 124 | } 125 | 126 | 127 | 128 | ////////////////////////////////////////////////////////////////////////////// 129 | // Scene Setup 130 | ////////////////////////////////////////////////////////////////////////////// 131 | 132 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/Pulleys.java 133 | public void initScene() { 134 | 135 | float y = 16.0f; 136 | float L = 12.0f; 137 | float a = 1.0f; 138 | float b = 2.0f; 139 | Body ground = null; 140 | { 141 | BodyDef bd = new BodyDef(); 142 | ground = world.createBody(bd); 143 | 144 | EdgeShape shape = new EdgeShape(); 145 | shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); 146 | ground.createFixture(shape, 0.0f); 147 | 148 | CircleShape circle = new CircleShape(); 149 | circle.m_radius = 2.0f; 150 | 151 | circle.m_p.set(-10.0f, y + b + L); 152 | ground.createFixture(circle, 0.0f); 153 | 154 | circle.m_p.set(10.0f, y + b + L); 155 | ground.createFixture(circle, 0.0f); 156 | 157 | world.bodies.add(ground, true, color(220, 128), true, color(255), 1f); 158 | } 159 | 160 | { 161 | 162 | PolygonShape shape = new PolygonShape(); 163 | shape.setAsBox(a, b); 164 | 165 | BodyDef bd = new BodyDef(); 166 | bd.type = BodyType.DYNAMIC; 167 | 168 | bd.position.set(-10.0f, y); 169 | Body body1 = world.createBody(bd); 170 | body1.createFixture(shape, 5.0f); 171 | 172 | bd.position.set(10.0f, y); 173 | Body body2 = world.createBody(bd); 174 | body2.createFixture(shape, 5.0f); 175 | 176 | world.bodies.add(body1, true, color(0,128,255), true, color(0), 1f); 177 | world.bodies.add(body2, true, color(0,128,255), true, color(0), 1f); 178 | 179 | PulleyJointDef pulleyDef = new PulleyJointDef(); 180 | Vec2 anchor1 = new Vec2(-10.0f, y + b); 181 | Vec2 anchor2 = new Vec2(10.0f, y + b); 182 | Vec2 groundAnchor1 = new Vec2(-10.0f, y + b + L); 183 | Vec2 groundAnchor2 = new Vec2(10.0f, y + b + L); 184 | pulleyDef.initialize(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, 2.0f); 185 | 186 | Joint m_joint1 = (PulleyJoint) world.createJoint(pulleyDef); 187 | 188 | world.bodies.add(m_joint1, false, color(0), true, color(255,128,64), 1f); 189 | } 190 | 191 | 192 | } 193 | 194 | 195 | 196 | public static void main(String args[]) { 197 | PApplet.main(new String[] { box2d_PulleyJoint.class.getName() }); 198 | } 199 | 200 | } -------------------------------------------------------------------------------- /examples/box2d_RainingBodies/box2d_RainingBodies.java: -------------------------------------------------------------------------------- 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_RainingBodies; 15 | 16 | import com.thomasdiewald.liquidfun.java.DwWorld; 17 | import org.jbox2d.collision.shapes.CircleShape; 18 | import org.jbox2d.collision.shapes.PolygonShape; 19 | import org.jbox2d.collision.shapes.Shape; 20 | import org.jbox2d.common.Vec2; 21 | import org.jbox2d.dynamics.Body; 22 | import org.jbox2d.dynamics.BodyDef; 23 | import org.jbox2d.dynamics.BodyType; 24 | import org.jbox2d.dynamics.Fixture; 25 | import processing.core.*; 26 | import processing.opengl.PGraphics2D; 27 | 28 | 29 | public class box2d_RainingBodies extends PApplet { 30 | 31 | // 32 | // Randomly falling bodies. Automatically removed from the world if the exceed 33 | // some boundary. 34 | // 35 | // Controls: 36 | // 37 | // LMB ... drag bodies 38 | // LMB + SHIFT ... shoot bullet 39 | // MMB ... add particles 40 | // RMB ... remove particles 41 | // 'r' ... reset 42 | // 't' ... update/pause physics 43 | // 'f' ... toggle debug draw 44 | // 45 | 46 | 47 | int viewport_w = 1280; 48 | int viewport_h = 720; 49 | int viewport_x = 230; 50 | int viewport_y = 0; 51 | 52 | boolean UPDATE_PHYSICS = true; 53 | boolean USE_DEBUG_DRAW = false; 54 | 55 | DwWorld world; 56 | 57 | public void settings(){ 58 | size(viewport_w, viewport_h, P2D); 59 | smooth(8); 60 | } 61 | 62 | public void setup(){ 63 | surface.setLocation(viewport_x, viewport_y); 64 | reset(); 65 | frameRate(120); 66 | } 67 | 68 | 69 | public void release(){ 70 | if(world != null) world.release(); world = null; 71 | } 72 | 73 | public void reset(){ 74 | // release old resources 75 | release(); 76 | 77 | world = new DwWorld(this, 20); 78 | 79 | // create scene: rigid bodies, particles, etc ... 80 | initScene(); 81 | } 82 | 83 | 84 | 85 | public void draw(){ 86 | 87 | if(UPDATE_PHYSICS){ 88 | if(frameCount % 10 == 0){ 89 | addBodies(); 90 | } 91 | world.update(); 92 | } 93 | 94 | 95 | PGraphics2D canvas = (PGraphics2D) this.g; 96 | 97 | canvas.background(32); 98 | canvas.pushMatrix(); 99 | world.applyTransform(canvas); 100 | world.drawBulletSpawnTrack(canvas); 101 | 102 | if(USE_DEBUG_DRAW){ 103 | world.displayDebugDraw(canvas); 104 | // DwDebugDraw.display(canvas, world); 105 | } else { 106 | world.display(canvas); 107 | } 108 | canvas.popMatrix(); 109 | 110 | // info 111 | int num_bodies = world.getBodyCount(); 112 | int num_particles = world.getParticleCount(); 113 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 114 | surface.setTitle(txt_fps); 115 | } 116 | 117 | 118 | 119 | 120 | ////////////////////////////////////////////////////////////////////////////// 121 | // User Interaction 122 | ////////////////////////////////////////////////////////////////////////////// 123 | 124 | public void keyReleased(){ 125 | if(key == 'r') reset(); 126 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 127 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 128 | } 129 | 130 | 131 | 132 | ////////////////////////////////////////////////////////////////////////////// 133 | // Scene Setup 134 | ////////////////////////////////////////////////////////////////////////////// 135 | 136 | int MAX_NUM = 800; 137 | int m_count = 0; 138 | 139 | public void initScene() { 140 | 141 | m_count = 0; 142 | 143 | float screen_scale = world.transform.screen_scale; 144 | float b2d_screen_w = world.transform.box2d_dimx; 145 | float b2d_screen_h = world.transform.box2d_dimy; 146 | float b2d_thickness = 10 / screen_scale; 147 | 148 | { // Walls 149 | BodyDef bd = new BodyDef(); 150 | bd.position.set(0, 0); 151 | 152 | Body ground = world.createBody(bd); 153 | PolygonShape sd = new PolygonShape(); 154 | 155 | float x, y, w, h; 156 | 157 | float angle = 60 * PI/180; 158 | for(int i = 0; i < 10; i++){ 159 | x = random(-0.5f, 0.5f) * b2d_screen_w; 160 | y = random( 0, 0.5f) * b2d_screen_h; 161 | w = random(15, 20); 162 | h = b2d_thickness; 163 | sd.setAsBox(w/2f, h/2f, new Vec2(x, y), random(-1, 1) * angle); 164 | ground.createFixture(sd, 0); 165 | } 166 | 167 | world.bodies.add(ground, true, color(0), !true, color(0), 1f); 168 | } 169 | } 170 | 171 | 172 | 173 | public void addBodies(){ 174 | if (world.getBodyCount() < MAX_NUM) { 175 | 176 | float b2d_screen_w = world.transform.box2d_dimx; 177 | float b2d_screen_h = world.transform.box2d_dimy; 178 | 179 | float x = random(-0.4f, 0.4f) * b2d_screen_w; 180 | float y = random(-2f, 2) + b2d_screen_h; 181 | 182 | float w = random(0.5f, 2.2f); 183 | float h = random(0.5f, 1.2f); 184 | 185 | BodyDef bd = new BodyDef(); 186 | bd.type = BodyType.DYNAMIC; 187 | bd.position.set(x, y); 188 | Body body = world.createBody(bd); 189 | 190 | Shape shape = null; 191 | if(random(1) < 0.5){ 192 | PolygonShape pshape = new PolygonShape(); 193 | pshape.setAsBox(w, h, new Vec2(0,0), random(TWO_PI)); 194 | shape = pshape; 195 | } else { 196 | CircleShape cshape = new CircleShape(); 197 | cshape.m_p.set(0,0); 198 | cshape.m_radius = w / 2f; 199 | shape = cshape; 200 | } 201 | 202 | Fixture fixture = body.createFixture(shape, 0.01f); 203 | fixture.m_friction = 0.1f; 204 | fixture.m_restitution = 0.5f; 205 | 206 | colorMode(HSB, 360, 100, 100); 207 | 208 | float r = (360 * m_count /(float)MAX_NUM) % 360; 209 | float g = 100; 210 | float b = 100; 211 | 212 | world.bodies.add(body, true, color(r,g,b), true, color(r, g, b *0.5f), 1f); 213 | colorMode(RGB, 255, 255, 255); 214 | 215 | m_count++; 216 | } 217 | } 218 | 219 | 220 | 221 | 222 | 223 | public static void main(String args[]) { 224 | PApplet.main(new String[] { box2d_RainingBodies.class.getName() }); 225 | } 226 | 227 | } -------------------------------------------------------------------------------- /examples/box2d_RopeJoint/box2d_RopeJoint.java: -------------------------------------------------------------------------------- 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_RopeJoint; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.EdgeShape; 19 | import org.jbox2d.collision.shapes.PolygonShape; 20 | import org.jbox2d.common.Vec2; 21 | import org.jbox2d.dynamics.Body; 22 | import org.jbox2d.dynamics.BodyDef; 23 | import org.jbox2d.dynamics.BodyType; 24 | import org.jbox2d.dynamics.FixtureDef; 25 | import org.jbox2d.dynamics.joints.Joint; 26 | import org.jbox2d.dynamics.joints.RevoluteJointDef; 27 | import org.jbox2d.dynamics.joints.RopeJointDef; 28 | 29 | import processing.core.*; 30 | import processing.opengl.PGraphics2D; 31 | 32 | 33 | public class box2d_RopeJoint extends PApplet { 34 | 35 | // 36 | // This examples shows how to use RopeJoints. 37 | // 38 | // Controls: 39 | // 40 | // LMB ... drag bodies 41 | // LMB + SHIFT ... shoot bullet 42 | // MMB ... add particles 43 | // RMB ... remove particles 44 | // 'r' ... reset 45 | // 't' ... update/pause physics 46 | // 'f' ... toggle debug draw 47 | // 'j' ... toggle joint 48 | // 49 | 50 | int viewport_w = 1280; 51 | int viewport_h = 720; 52 | int viewport_x = 230; 53 | int viewport_y = 0; 54 | 55 | boolean UPDATE_PHYSICS = true; 56 | boolean USE_DEBUG_DRAW = false; 57 | 58 | DwWorld world; 59 | 60 | public void settings(){ 61 | size(viewport_w, viewport_h, P2D); 62 | smooth(8); 63 | } 64 | 65 | 66 | public void setup(){ 67 | surface.setLocation(viewport_x, viewport_y); 68 | reset(); 69 | frameRate(120); 70 | } 71 | 72 | 73 | public void release(){ 74 | if(world != null) world.release(); world = null; 75 | } 76 | 77 | 78 | public void reset(){ 79 | // release old resources 80 | release(); 81 | 82 | world = new DwWorld(this, 30); 83 | 84 | // create scene: rigid bodies, particles, etc ... 85 | initScene(); 86 | } 87 | 88 | 89 | 90 | public void draw(){ 91 | 92 | if(UPDATE_PHYSICS){ 93 | world.update(); 94 | } 95 | 96 | PGraphics2D canvas = (PGraphics2D) this.g; 97 | canvas.background(32); 98 | canvas.pushMatrix(); 99 | world.applyTransform(canvas); 100 | world.drawBulletSpawnTrack(canvas); 101 | if(USE_DEBUG_DRAW){ 102 | world.displayDebugDraw(canvas); 103 | // DwDebugDraw.display(canvas, world); 104 | } else { 105 | world.display(canvas); 106 | } 107 | canvas.popMatrix(); 108 | 109 | // info 110 | int num_bodies = world.getBodyCount(); 111 | int num_particles = world.getParticleCount(); 112 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 113 | surface.setTitle(txt_fps); 114 | } 115 | 116 | 117 | 118 | ////////////////////////////////////////////////////////////////////////////// 119 | // User Interaction 120 | ////////////////////////////////////////////////////////////////////////////// 121 | public void keyReleased(){ 122 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 123 | if(key == 'r') reset(); 124 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 125 | 126 | 127 | if(key == 'j'){ 128 | if (m_rope != null) { 129 | world.destroyJoint(m_rope); 130 | m_rope = null; 131 | } else { 132 | m_rope = world.createJoint(m_ropeDef); 133 | world.bodies.add(m_rope, false, color(0), true, color(255,128,0), 2f); 134 | } 135 | } 136 | } 137 | 138 | 139 | 140 | ////////////////////////////////////////////////////////////////////////////// 141 | // Scene Setup 142 | ////////////////////////////////////////////////////////////////////////////// 143 | 144 | RopeJointDef m_ropeDef; 145 | Joint m_rope; 146 | 147 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/RopeTest.java 148 | public void initScene() { 149 | 150 | Body ground = null; 151 | { 152 | BodyDef bd = new BodyDef(); 153 | ground = world.createBody(bd); 154 | 155 | EdgeShape shape = new EdgeShape(); 156 | shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); 157 | ground.createFixture(shape, 0.0f); 158 | } 159 | 160 | { 161 | PolygonShape shape = new PolygonShape(); 162 | shape.setAsBox(0.5f, 0.125f); 163 | 164 | FixtureDef fd = new FixtureDef(); 165 | fd.shape = shape; 166 | fd.density = 20.0f; 167 | fd.friction = 0.2f; 168 | fd.filter.categoryBits = 0x0001; 169 | fd.filter.maskBits = 0xFFFF & ~0x0002; 170 | 171 | RevoluteJointDef jd = new RevoluteJointDef(); 172 | jd.collideConnected = false; 173 | 174 | 175 | final int N = 10; 176 | final float y = 15.0f; 177 | m_ropeDef = new RopeJointDef(); 178 | m_ropeDef.localAnchorA.set(0.0f, y); 179 | 180 | Body prevBody = ground; 181 | for (int i = 0; i < N; ++i) { 182 | BodyDef bd = new BodyDef(); 183 | bd.type = BodyType.DYNAMIC; 184 | bd.position.set(0.5f + 1.0f * i, y); 185 | if (i == N - 1) { 186 | shape.setAsBox(1.5f, 1.5f); 187 | fd.density = 100.0f; 188 | fd.filter.categoryBits = 0x0002; 189 | bd.position.set(1.0f * i, y); 190 | bd.angularDamping = 0.4f; 191 | } 192 | 193 | Body body = world.createBody(bd); 194 | body.createFixture(fd); 195 | 196 | world.bodies.add(body, true, color(255 * i/(float)N), true, color(0), 1f); 197 | 198 | Vec2 anchor = new Vec2(i, y); 199 | jd.initialize(prevBody, body, anchor); 200 | Joint joint = world.createJoint(jd); 201 | 202 | world.bodies.add(joint, false, color(0), true, color(0,128,255), 2f); 203 | 204 | prevBody = body; 205 | } 206 | 207 | m_ropeDef.localAnchorB.setZero(); 208 | 209 | float extraLength = 0.01f; 210 | m_ropeDef.maxLength = N - 1.0f + extraLength; 211 | m_ropeDef.bodyB = prevBody; 212 | } 213 | 214 | { 215 | m_ropeDef.bodyA = ground; 216 | m_rope = world.createJoint(m_ropeDef); 217 | world.bodies.add(m_rope, false, color(0), true, color(255,128,0), 2f); 218 | } 219 | 220 | 221 | world.bodies.addAll(); 222 | } 223 | 224 | 225 | 226 | public static void main(String args[]) { 227 | PApplet.main(new String[] { box2d_RopeJoint.class.getName() }); 228 | } 229 | 230 | } -------------------------------------------------------------------------------- /examples/box2d_Tumbler/box2d_Tumbler.java: -------------------------------------------------------------------------------- 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_Tumbler; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.CircleShape; 19 | import org.jbox2d.collision.shapes.PolygonShape; 20 | import org.jbox2d.common.MathUtils; 21 | import org.jbox2d.common.Vec2; 22 | import org.jbox2d.dynamics.Body; 23 | import org.jbox2d.dynamics.BodyDef; 24 | import org.jbox2d.dynamics.BodyType; 25 | import org.jbox2d.dynamics.Fixture; 26 | import org.jbox2d.dynamics.joints.RevoluteJoint; 27 | import org.jbox2d.dynamics.joints.RevoluteJointDef; 28 | 29 | import processing.core.*; 30 | import processing.opengl.PGraphics2D; 31 | 32 | 33 | public class box2d_Tumbler extends PApplet { 34 | 35 | // 36 | // A square tumbler is animated using a RevoluteJoint (motor). 37 | // Small boxes are dynamically added. 38 | // 39 | // Controls: 40 | // 41 | // LMB ... drag bodies 42 | // LMB + SHIFT ... shoot bullet 43 | // MMB ... add particles 44 | // RMB ... remove particles 45 | // 'r' ... reset 46 | // 't' ... update/pause physics 47 | // 'f' ... toggle debug draw 48 | // 49 | 50 | 51 | 52 | int viewport_w = 1280; 53 | int viewport_h = 720; 54 | int viewport_x = 230; 55 | int viewport_y = 0; 56 | 57 | boolean UPDATE_PHYSICS = true; 58 | boolean USE_DEBUG_DRAW = false; 59 | 60 | 61 | DwWorld world; 62 | 63 | public void settings(){ 64 | size(viewport_w, viewport_h, P2D); 65 | smooth(8); 66 | } 67 | 68 | public void setup(){ 69 | surface.setLocation(viewport_x, viewport_y); 70 | reset(); 71 | frameRate(120); 72 | } 73 | 74 | 75 | public void release(){ 76 | if(world != null) world.release(); world = null; 77 | } 78 | 79 | 80 | public void reset(){ 81 | // release old resources 82 | release(); 83 | 84 | world = new DwWorld(this, 22); 85 | world.transform.setScreen(width, height, 22, width/2, height/2); 86 | 87 | // create scene: rigid bodies, particles, etc ... 88 | initScene(); 89 | } 90 | 91 | 92 | 93 | public void draw(){ 94 | 95 | if(UPDATE_PHYSICS){ 96 | if(frameCount % 4 == 0){ 97 | addBodies(); 98 | } 99 | world.update(); 100 | } 101 | 102 | 103 | PGraphics2D canvas = (PGraphics2D) this.g; 104 | canvas.background(32); 105 | canvas.pushMatrix(); 106 | world.applyTransform(canvas); 107 | world.drawBulletSpawnTrack(canvas); 108 | if(USE_DEBUG_DRAW){ 109 | world.displayDebugDraw(canvas); 110 | // DwDebugDraw.display(canvas, world); 111 | } else { 112 | world.display(canvas); 113 | } 114 | canvas.popMatrix(); 115 | 116 | 117 | // info 118 | int num_bodies = world.getBodyCount(); 119 | int num_particles = world.getParticleCount(); 120 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 121 | surface.setTitle(txt_fps); 122 | } 123 | 124 | 125 | 126 | 127 | 128 | 129 | ////////////////////////////////////////////////////////////////////////////// 130 | // User Interaction 131 | ////////////////////////////////////////////////////////////////////////////// 132 | public void keyReleased(){ 133 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 134 | if(key == 'r') reset(); 135 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 136 | } 137 | 138 | 139 | 140 | 141 | ////////////////////////////////////////////////////////////////////////////// 142 | // Scene Setup 143 | ////////////////////////////////////////////////////////////////////////////// 144 | int MAX_NUM = 800; 145 | int m_count = 0; 146 | RevoluteJoint m_joint; 147 | 148 | 149 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/Tumbler.java 150 | public void initScene() { 151 | 152 | 153 | { 154 | BodyDef bd = new BodyDef(); 155 | Body groundbody = world.createBody(bd); 156 | 157 | bd.type = BodyType.DYNAMIC; 158 | bd.allowSleep = false; 159 | bd.position.set(0.0f, 0.0f); 160 | Body body = world.createBody(bd); 161 | 162 | PolygonShape shape = new PolygonShape(); 163 | shape.setAsBox(1, 11.0f, new Vec2(10.0f, 0.0f), 0.0f); 164 | body.createFixture(shape, 15.0f); 165 | shape.setAsBox(1, 11.0f, new Vec2(-10.0f, 0.0f), 0.0f); 166 | body.createFixture(shape, 15.0f); 167 | shape.setAsBox(11.0f, 1, new Vec2(0.0f, 10.0f), 0.0f); 168 | body.createFixture(shape, 15.0f); 169 | shape.setAsBox(11.0f, 1, new Vec2(0.0f, -10.0f), 0.0f); 170 | body.createFixture(shape, 15.0f); 171 | 172 | 173 | CircleShape obstacle = new CircleShape(); 174 | obstacle.m_radius = 1; 175 | obstacle.m_p.set(-2, -6.5f); 176 | body.createFixture(obstacle, 115.0f); 177 | obstacle.m_p.set(2, +6.5f); 178 | body.createFixture(obstacle, 115.0f); 179 | // obstacle.m_p.set(-7.5f, 0); 180 | // body.createFixture(obstacle, 15.0f); 181 | // obstacle.m_p.set(+7.5f, 0); 182 | // body.createFixture(obstacle, 15.0f); 183 | 184 | 185 | world.bodies.add(body, true, color(224), true, color(0), 1f); 186 | 187 | RevoluteJointDef jd = new RevoluteJointDef(); 188 | jd.bodyA = groundbody; 189 | jd.bodyB = body; 190 | jd.localAnchorA.set(0.0f, 0.0f); 191 | jd.localAnchorB.set(0.0f, 0.0f); 192 | jd.referenceAngle = 0.0f; 193 | jd.motorSpeed = 0.1f * MathUtils.PI; 194 | jd.maxMotorTorque = 1e7f; 195 | jd.enableMotor = true; 196 | m_joint = (RevoluteJoint) world.createJoint(jd); 197 | } 198 | m_count = 0; 199 | 200 | 201 | // creates shapes for all rigid bodies in the world. 202 | world.bodies.addAll(); 203 | } 204 | 205 | 206 | public void addBodies(){ 207 | if (m_count < MAX_NUM) { 208 | 209 | float x = random(-0.7f, 0.7f); 210 | float y = random(-0.7f, 0.7f); 211 | 212 | BodyDef bd = new BodyDef(); 213 | bd.type = BodyType.DYNAMIC; 214 | bd.position.set(x, y); 215 | Body body = world.createBody(bd); 216 | 217 | PolygonShape shape = new PolygonShape(); 218 | shape.setAsBox(0.18f, 0.18f); 219 | Fixture fixture = body.createFixture(shape, 0.01f); 220 | fixture.m_friction = 0.1f; 221 | fixture.m_restitution = 0.5f; 222 | 223 | ++m_count; 224 | 225 | colorMode(HSB, 360, 100, 100); 226 | float r = (360 * m_count /(float)MAX_NUM) % 360; 227 | float g = 100; 228 | float b = 100; 229 | world.bodies.add(body, true, color(r,g,b), true, color(r, g, b *0.5f), 1f); 230 | colorMode(RGB, 255, 255, 255); 231 | } 232 | } 233 | 234 | 235 | 236 | 237 | public static void main(String args[]) { 238 | PApplet.main(new String[] { box2d_Tumbler.class.getName() }); 239 | } 240 | 241 | } -------------------------------------------------------------------------------- /examples/box2d_TumblerMod/box2d_TumblerMod.java: -------------------------------------------------------------------------------- 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_TumblerMod; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.ChainShape; 19 | import org.jbox2d.collision.shapes.CircleShape; 20 | import org.jbox2d.collision.shapes.PolygonShape; 21 | import org.jbox2d.common.MathUtils; 22 | import org.jbox2d.common.Vec2; 23 | import org.jbox2d.dynamics.Body; 24 | import org.jbox2d.dynamics.BodyDef; 25 | import org.jbox2d.dynamics.BodyType; 26 | import org.jbox2d.dynamics.Fixture; 27 | import org.jbox2d.dynamics.joints.RevoluteJoint; 28 | import org.jbox2d.dynamics.joints.RevoluteJointDef; 29 | 30 | import processing.core.*; 31 | import processing.opengl.PGraphics2D; 32 | 33 | 34 | public class box2d_TumblerMod extends PApplet { 35 | 36 | // 37 | // A custom shaped tumbler is animated using a RevoluteJoint (motor). 38 | // Small boxes are dynamically added. 39 | // 40 | // Controls: 41 | // 42 | // LMB ... drag bodies 43 | // LMB + SHIFT ... shoot bullet 44 | // MMB ... add particles 45 | // RMB ... remove particles 46 | // 'r' ... reset 47 | // 't' ... update/pause physics 48 | // 'f' ... toggle debug draw 49 | // 50 | 51 | int viewport_w = 1280; 52 | int viewport_h = 720; 53 | int viewport_x = 230; 54 | int viewport_y = 0; 55 | 56 | boolean UPDATE_PHYSICS = true; 57 | boolean USE_DEBUG_DRAW = false; 58 | 59 | DwWorld world; 60 | 61 | public void settings(){ 62 | size(viewport_w, viewport_h, P2D); 63 | smooth(8); 64 | } 65 | 66 | public void setup(){ 67 | surface.setLocation(viewport_x, viewport_y); 68 | reset(); 69 | frameRate(120); 70 | } 71 | 72 | 73 | public void release(){ 74 | if(world != null) world.release(); world = null; 75 | } 76 | 77 | 78 | public void reset(){ 79 | // release old resources 80 | release(); 81 | 82 | // create world 83 | world = new DwWorld(this, 20); 84 | world.transform.setScreen(width, height, 22, width/2, height/2); 85 | 86 | // create scene: rigid bodies, particles, etc ... 87 | initScene(); 88 | } 89 | 90 | 91 | public void draw(){ 92 | 93 | if(UPDATE_PHYSICS){ 94 | if(frameCount % 4 == 0){ 95 | addBodies(); 96 | } 97 | world.update(); 98 | } 99 | 100 | 101 | PGraphics2D canvas = (PGraphics2D) this.g; 102 | canvas.background(32); 103 | canvas.pushMatrix(); 104 | world.applyTransform(canvas); 105 | world.drawBulletSpawnTrack(canvas); 106 | if(USE_DEBUG_DRAW){ 107 | world.displayDebugDraw(canvas); 108 | // DwDebugDraw.display(canvas, world); 109 | } else { 110 | world.display(canvas); 111 | } 112 | canvas.popMatrix(); 113 | 114 | 115 | // info 116 | int num_bodies = world.getBodyCount(); 117 | int num_particles = world.getParticleCount(); 118 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 119 | surface.setTitle(txt_fps); 120 | } 121 | 122 | 123 | 124 | 125 | 126 | 127 | ////////////////////////////////////////////////////////////////////////////// 128 | // User Interaction 129 | ////////////////////////////////////////////////////////////////////////////// 130 | 131 | public void keyReleased(){ 132 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 133 | if(key == 'r') reset(); 134 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 135 | } 136 | 137 | 138 | 139 | ////////////////////////////////////////////////////////////////////////////// 140 | // Scene Setup 141 | ////////////////////////////////////////////////////////////////////////////// 142 | int MAX_NUM = 800; 143 | RevoluteJoint m_joint; 144 | int m_count; 145 | 146 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/Tumbler.java 147 | public void initScene() { 148 | 149 | 150 | { 151 | BodyDef bd = new BodyDef(); 152 | Body groundbody = world.createBody(bd); 153 | 154 | bd.type = BodyType.DYNAMIC; 155 | bd.allowSleep = false; 156 | bd.position.set(0.0f, 0.0f); 157 | 158 | Body bwheel = world.createBody(bd); 159 | // bodies.add(bwheel); 160 | 161 | ChainShape shape = new ChainShape(); 162 | int num_verts = 128; 163 | float rad = 10; 164 | float angle_step = (float) (Math.PI * 2 / num_verts); 165 | 166 | float dent_size = 1.5f; 167 | int num_dents = 5; 168 | 169 | // wheel 170 | Vec2[] vertices = new Vec2[num_verts]; 171 | for(int i = 0; i < num_verts; i++){ 172 | float inorm = (float) ((Math.PI * 2) * i / (float) num_verts); 173 | float rad_off = (float) Math.cos(inorm * num_dents) * dent_size; 174 | float x = (rad + rad_off) * (float) Math.cos(angle_step * i); 175 | float y = (rad + rad_off) * (float) Math.sin(angle_step * i); 176 | vertices[i] = new Vec2(x, y); 177 | } 178 | 179 | shape.createLoop(vertices, num_verts); 180 | Fixture wheel = bwheel.createFixture(shape, 15.0f); 181 | world.bodies.add(wheel, true, color(240), false, color(255), 1f); 182 | 183 | // obstacles inside wheel 184 | CircleShape sobstacle = new CircleShape(); 185 | sobstacle.m_radius = 4f/num_dents; 186 | angle_step = (float) (Math.PI * 2 / num_dents); 187 | for(int i = 0; i < num_dents; i++){ 188 | float angle = angle_step * 0.5f + angle_step * i; 189 | float radius = rad - 4f; 190 | float x = radius * (float) Math.cos(angle); 191 | float y = radius * (float) Math.sin(angle); 192 | sobstacle.m_p.set(x, y); 193 | Fixture fobstacle = bwheel.createFixture(sobstacle, 150.0f); 194 | world.bodies.add(fobstacle, true, color(64), false, color(255), 1f); 195 | } 196 | 197 | // motor 198 | RevoluteJointDef jd = new RevoluteJointDef(); 199 | jd.bodyA = groundbody; 200 | jd.bodyB = bwheel; 201 | jd.localAnchorA.set(0.0f, 0.0f); 202 | jd.localAnchorB.set(0.0f, 0.0f); 203 | jd.referenceAngle = 0.0f; 204 | jd.motorSpeed = 0.1f * MathUtils.PI; 205 | jd.maxMotorTorque = 1000000f; 206 | jd.enableMotor = true; 207 | m_joint = (RevoluteJoint) world.createJoint(jd); 208 | } 209 | m_count = 0; 210 | 211 | } 212 | 213 | 214 | public void addBodies(){ 215 | if (m_count < MAX_NUM) { 216 | 217 | float x = random(-0.7f, 0.7f); 218 | float y = random(-0.7f, 0.7f); 219 | 220 | BodyDef bd = new BodyDef(); 221 | bd.type = BodyType.DYNAMIC; 222 | bd.position.set(x, y); 223 | Body body = world.createBody(bd); 224 | 225 | PolygonShape shape = new PolygonShape(); 226 | shape.setAsBox(0.18f, 0.18f); 227 | Fixture fixture = body.createFixture(shape, 0.01f); 228 | fixture.m_friction = 0.1f; 229 | fixture.m_restitution = 0.5f; 230 | 231 | ++m_count; 232 | 233 | colorMode(HSB, 360, 100, 100); 234 | float hue = (360 * m_count /(float)MAX_NUM) % 360; 235 | world.bodies.add(body, true, color(hue, 100, 100), true, color(hue, 100, 50), 1f); 236 | colorMode(RGB, 255, 255, 255); 237 | } 238 | } 239 | 240 | 241 | 242 | 243 | public static void main(String args[]) { 244 | PApplet.main(new String[] { box2d_TumblerMod.class.getName() }); 245 | } 246 | 247 | } -------------------------------------------------------------------------------- /examples/box2d_VaryingFriction/box2d_VaryingFriction.java: -------------------------------------------------------------------------------- 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_VaryingFriction; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | 19 | import org.jbox2d.collision.shapes.EdgeShape; 20 | import org.jbox2d.collision.shapes.PolygonShape; 21 | import org.jbox2d.common.Vec2; 22 | import org.jbox2d.dynamics.Body; 23 | import org.jbox2d.dynamics.BodyDef; 24 | import org.jbox2d.dynamics.BodyType; 25 | import org.jbox2d.dynamics.FixtureDef; 26 | import processing.core.*; 27 | import processing.opengl.PGraphics2D; 28 | 29 | 30 | public class box2d_VaryingFriction extends PApplet { 31 | 32 | // 33 | // this examples shows demonstrates the behaviour of different friction-values. 34 | // 35 | // Controls: 36 | // 37 | // LMB ... drag bodies 38 | // LMB + SHIFT ... shoot bullet 39 | // MMB ... add particles 40 | // RMB ... remove particles 41 | // 'r' ... reset 42 | // 't' ... update/pause physics 43 | // 'f' ... toggle debug draw 44 | // 45 | 46 | 47 | int viewport_w = 1280; 48 | int viewport_h = 720; 49 | int viewport_x = 230; 50 | int viewport_y = 0; 51 | 52 | boolean UPDATE_PHYSICS = true; 53 | boolean USE_DEBUG_DRAW = false; 54 | 55 | DwWorld world; 56 | 57 | public void settings(){ 58 | size(viewport_w, viewport_h, P2D); 59 | smooth(8); 60 | } 61 | 62 | public void setup(){ 63 | surface.setLocation(viewport_x, viewport_y); 64 | reset(); 65 | frameRate(120); 66 | } 67 | 68 | 69 | public void release(){ 70 | if(world != null) world.release(); world = null; 71 | } 72 | 73 | 74 | public void reset(){ 75 | // release old resources 76 | release(); 77 | 78 | world = new DwWorld(this, 25); 79 | 80 | // create scene: rigid bodies, particles, etc ... 81 | initScene(); 82 | } 83 | 84 | 85 | 86 | public void draw(){ 87 | 88 | if(UPDATE_PHYSICS){ 89 | world.update(); 90 | } 91 | 92 | 93 | PGraphics2D canvas = (PGraphics2D) this.g; 94 | canvas.background(32); 95 | canvas.pushMatrix(); 96 | world.applyTransform(canvas); 97 | world.drawBulletSpawnTrack(canvas); 98 | if(USE_DEBUG_DRAW){ 99 | world.displayDebugDraw(canvas); 100 | // DwDebugDraw.display(canvas, world); 101 | } else { 102 | world.display(canvas); 103 | } 104 | canvas.popMatrix(); 105 | 106 | 107 | // info 108 | int num_bodies = world.getBodyCount(); 109 | int num_particles = world.getParticleCount(); 110 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 111 | surface.setTitle(txt_fps); 112 | } 113 | 114 | 115 | 116 | 117 | 118 | 119 | ////////////////////////////////////////////////////////////////////////////// 120 | // User Interaction 121 | ////////////////////////////////////////////////////////////////////////////// 122 | public void keyReleased(){ 123 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 124 | if(key == 'r') reset(); 125 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 126 | } 127 | 128 | 129 | 130 | 131 | ////////////////////////////////////////////////////////////////////////////// 132 | // Scene Setup 133 | ////////////////////////////////////////////////////////////////////////////// 134 | 135 | 136 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/VaryingFrictionTest.java 137 | public void initScene() { 138 | { 139 | BodyDef bd = new BodyDef(); 140 | Body ground = world.createBody(bd); 141 | 142 | EdgeShape shape = new EdgeShape(); 143 | shape.set(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f)); 144 | ground.createFixture(shape, 0.0f); 145 | 146 | world.bodies.add(ground, false, color(0), true, color(200), 1f); 147 | } 148 | 149 | { 150 | PolygonShape shape = new PolygonShape(); 151 | shape.setAsBox(13.0f, 0.25f); 152 | 153 | BodyDef bd = new BodyDef(); 154 | bd.position.set(-4.0f, 22.0f); 155 | bd.angle = -0.25f; 156 | 157 | Body ground = world.createBody(bd); 158 | ground.createFixture(shape, 0.0f); 159 | } 160 | 161 | { 162 | PolygonShape shape = new PolygonShape(); 163 | shape.setAsBox(0.25f, 1.0f); 164 | 165 | BodyDef bd = new BodyDef(); 166 | bd.position.set(10.5f, 19.0f); 167 | 168 | Body ground = world.createBody(bd); 169 | ground.createFixture(shape, 0.0f); 170 | } 171 | 172 | { 173 | PolygonShape shape = new PolygonShape(); 174 | shape.setAsBox(13.0f, 0.25f); 175 | 176 | BodyDef bd = new BodyDef(); 177 | bd.position.set(4.0f, 14.0f); 178 | bd.angle = 0.25f; 179 | 180 | Body ground = world.createBody(bd); 181 | ground.createFixture(shape, 0.0f); 182 | } 183 | 184 | { 185 | PolygonShape shape = new PolygonShape(); 186 | shape.setAsBox(0.25f, 1.0f); 187 | 188 | BodyDef bd = new BodyDef(); 189 | bd.position.set(-10.5f, 11.0f); 190 | 191 | Body ground = world.createBody(bd); 192 | ground.createFixture(shape, 0.0f); 193 | } 194 | 195 | { 196 | PolygonShape shape = new PolygonShape(); 197 | shape.setAsBox(13.0f, 0.25f); 198 | 199 | BodyDef bd = new BodyDef(); 200 | bd.position.set(-4.0f, 6.0f); 201 | bd.angle = -0.25f; 202 | 203 | Body ground = world.createBody(bd); 204 | ground.createFixture(shape, 0.0f); 205 | } 206 | 207 | { 208 | PolygonShape shape = new PolygonShape(); 209 | shape.setAsBox(0.5f, 0.5f); 210 | 211 | FixtureDef fd = new FixtureDef(); 212 | fd.shape = shape; 213 | fd.density = 25.0f; 214 | 215 | float friction[] = { 0.75f, 0.5f, 0.35f, 0.1f, 0.0f }; 216 | 217 | for (int i = 0; i < 5; ++i) { 218 | BodyDef bd = new BodyDef(); 219 | bd.type = BodyType.DYNAMIC; 220 | bd.position.set(-15.0f + 4.0f * i, 28.0f); 221 | Body body = world.createBody(bd); 222 | 223 | fd.friction = friction[i]; 224 | body.createFixture(fd); 225 | } 226 | } 227 | 228 | world.bodies.addAll(); 229 | } 230 | 231 | 232 | 233 | 234 | 235 | 236 | public static void main(String args[]) { 237 | PApplet.main(new String[] { box2d_VaryingFriction.class.getName() }); 238 | } 239 | 240 | } -------------------------------------------------------------------------------- /examples/box2d_VaryingRestitution/box2d_VaryingRestitution.java: -------------------------------------------------------------------------------- 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_VaryingRestitution; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.CircleShape; 19 | import org.jbox2d.collision.shapes.EdgeShape; 20 | import org.jbox2d.common.Vec2; 21 | import org.jbox2d.dynamics.Body; 22 | import org.jbox2d.dynamics.BodyDef; 23 | import org.jbox2d.dynamics.BodyType; 24 | import org.jbox2d.dynamics.FixtureDef; 25 | 26 | import processing.core.*; 27 | import processing.opengl.PGraphics2D; 28 | 29 | 30 | public class box2d_VaryingRestitution extends PApplet { 31 | 32 | // 33 | // this examples shows demonstrates the behaviour of different restitution-values. 34 | // 35 | // Controls: 36 | // 37 | // LMB ... drag bodies 38 | // LMB + SHIFT ... shoot bullet 39 | // MMB ... add particles 40 | // RMB ... remove particles 41 | // 'r' ... reset 42 | // 't' ... update/pause physics 43 | // 'f' ... toggle debug draw 44 | // 45 | 46 | 47 | int viewport_w = 1280; 48 | int viewport_h = 720; 49 | int viewport_x = 230; 50 | int viewport_y = 0; 51 | 52 | boolean UPDATE_PHYSICS = true; 53 | boolean USE_DEBUG_DRAW = false; 54 | 55 | DwWorld world; 56 | 57 | public void settings(){ 58 | size(viewport_w, viewport_h, P2D); 59 | smooth(8); 60 | } 61 | 62 | public void setup(){ 63 | surface.setLocation(viewport_x, viewport_y); 64 | reset(); 65 | frameRate(120); 66 | } 67 | 68 | 69 | public void release(){ 70 | if(world != null) world.release(); world = null; 71 | } 72 | 73 | 74 | public void reset(){ 75 | // release old resources 76 | release(); 77 | 78 | world = new DwWorld(this, 15); 79 | 80 | // create scene: rigid bodies, particles, etc ... 81 | initScene(); 82 | } 83 | 84 | 85 | 86 | public void draw(){ 87 | 88 | if(UPDATE_PHYSICS){ 89 | world.update(); 90 | } 91 | 92 | 93 | PGraphics2D canvas = (PGraphics2D) this.g; 94 | canvas.background(32); 95 | canvas.pushMatrix(); 96 | world.applyTransform(canvas); 97 | world.drawBulletSpawnTrack(canvas); 98 | if(USE_DEBUG_DRAW){ 99 | world.displayDebugDraw(canvas); 100 | // DwDebugDraw.display(canvas, world); 101 | } else { 102 | world.display(canvas); 103 | } 104 | canvas.popMatrix(); 105 | 106 | 107 | // info 108 | int num_bodies = world.getBodyCount(); 109 | int num_particles = world.getParticleCount(); 110 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 111 | surface.setTitle(txt_fps); 112 | } 113 | 114 | 115 | 116 | 117 | 118 | 119 | ////////////////////////////////////////////////////////////////////////////// 120 | // User Interaction 121 | ////////////////////////////////////////////////////////////////////////////// 122 | public void keyReleased(){ 123 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 124 | if(key == 'r') reset(); 125 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 126 | } 127 | 128 | 129 | 130 | 131 | ////////////////////////////////////////////////////////////////////////////// 132 | // Scene Setup 133 | ////////////////////////////////////////////////////////////////////////////// 134 | 135 | 136 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/VaryingRestitution.java 137 | public void initScene() { 138 | { 139 | BodyDef bd = new BodyDef(); 140 | Body ground = world.createBody(bd); 141 | 142 | EdgeShape shape = new EdgeShape(); 143 | shape.set(new Vec2(-40.0f, 5.0f), new Vec2(40.0f, 5.0f)); 144 | ground.createFixture(shape, 0.0f); 145 | 146 | world.bodies.add(ground, false, color(0), true, color(200), 1f); 147 | } 148 | 149 | { 150 | CircleShape shape = new CircleShape(); 151 | shape.m_radius = 0.7f; 152 | 153 | FixtureDef fd = new FixtureDef(); 154 | fd.shape = shape; 155 | fd.density = 1.0f; 156 | 157 | 158 | int count = 40; 159 | for (int i = 0; i < count; ++i) { 160 | BodyDef bd = new BodyDef(); 161 | bd.type = BodyType.DYNAMIC; 162 | bd.position.set(-count * 0.8f + 1.6f * i, 40.0f); 163 | 164 | Body body = world.createBody(bd); 165 | 166 | fd.restitution = i / (float)count; 167 | body.createFixture(fd); 168 | 169 | float base = 65; 170 | float col = (255 - base) * fd.restitution; 171 | 172 | world.bodies.add(body, true, color(base + col, base, base), false, color(200), 1f); 173 | } 174 | } 175 | 176 | } 177 | 178 | 179 | 180 | 181 | 182 | 183 | public static void main(String args[]) { 184 | PApplet.main(new String[] { box2d_VaryingRestitution.class.getName() }); 185 | } 186 | 187 | } -------------------------------------------------------------------------------- /examples/liquidfun_DamBreak/liquidfun_DamBreak.java: -------------------------------------------------------------------------------- 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 liquidfun_DamBreak; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.ChainShape; 19 | import org.jbox2d.collision.shapes.PolygonShape; 20 | import org.jbox2d.common.Color3f; 21 | import org.jbox2d.common.Vec2; 22 | import org.jbox2d.dynamics.Body; 23 | import org.jbox2d.dynamics.BodyDef; 24 | import org.jbox2d.particle.ParticleGroupDef; 25 | import org.jbox2d.particle.ParticleType; 26 | 27 | import processing.core.*; 28 | import processing.opengl.PGraphics2D; 29 | 30 | 31 | public class liquidfun_DamBreak extends PApplet { 32 | 33 | 34 | // 35 | // Simulation of a clash of two big particle-groups. 36 | // 37 | // 38 | // Controls: 39 | // 40 | // LMB ... drag bodies 41 | // LMB + SHIFT ... shoot bullet 42 | // MMB ... add particles 43 | // RMB ... remove particles 44 | // 'r' ... reset 45 | // 't' ... update/pause physics 46 | // 'f' ... toggle debug draw 47 | // 48 | 49 | 50 | int viewport_w = 1280; 51 | int viewport_h = 720; 52 | int viewport_x = 230; 53 | int viewport_y = 0; 54 | 55 | boolean UPDATE_PHYSICS = true; 56 | boolean USE_DEBUG_DRAW = false; 57 | 58 | DwWorld world; 59 | 60 | // PImage sprite; 61 | 62 | public void settings(){ 63 | size(viewport_w, viewport_h, P2D); 64 | smooth(8); 65 | //PJOGL.profile = 3; 66 | } 67 | 68 | 69 | public void setup(){ 70 | surface.setLocation(viewport_x, viewport_y); 71 | // sprite = loadImage("sprite.png"); 72 | 73 | 74 | reset(); 75 | frameRate(120); 76 | } 77 | 78 | 79 | public void release(){ 80 | if(world != null) world.release(); world = null; 81 | } 82 | 83 | 84 | public void reset(){ 85 | // release old resources 86 | release(); 87 | 88 | world = new DwWorld(this, 18); 89 | 90 | // create scene: rigid bodies, particles, etc ... 91 | initScene(); 92 | } 93 | 94 | 95 | 96 | public void draw(){ 97 | if(UPDATE_PHYSICS){ 98 | world.update(); 99 | } 100 | 101 | PGraphics2D canvas = (PGraphics2D) this.g; 102 | canvas.background(32); 103 | canvas.pushMatrix(); 104 | world.applyTransform(canvas); 105 | world.drawBulletSpawnTrack(canvas); 106 | if(USE_DEBUG_DRAW){ 107 | world.displayDebugDraw(canvas); 108 | // DwDebugDraw.display(canvas, world); 109 | } else { 110 | world.display(canvas); 111 | } 112 | canvas.popMatrix(); 113 | 114 | // info 115 | int num_bodies = world.getBodyCount(); 116 | int num_particles = world.getParticleCount(); 117 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 118 | surface.setTitle(txt_fps); 119 | } 120 | 121 | 122 | 123 | ////////////////////////////////////////////////////////////////////////////// 124 | // User Interaction 125 | ////////////////////////////////////////////////////////////////////////////// 126 | public void keyReleased(){ 127 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 128 | if(key == 'r') reset(); 129 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 130 | } 131 | 132 | 133 | 134 | ////////////////////////////////////////////////////////////////////////////// 135 | // Scene Setup 136 | ////////////////////////////////////////////////////////////////////////////// 137 | 138 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/DamBreak.java 139 | public void initScene() { 140 | 141 | float dimx = world.transform.box2d_dimx; 142 | float dimy = world.transform.box2d_dimy; 143 | 144 | float dimxh = dimx/2; 145 | float dimyh = dimy/2; 146 | 147 | { 148 | BodyDef bd = new BodyDef(); 149 | Body ground = world.createBody(bd); 150 | 151 | ChainShape shape = new ChainShape(); 152 | Vec2[] vertices = {new Vec2(-dimxh, 0), new Vec2(dimxh, 0), new Vec2(dimxh, dimy), new Vec2(-dimxh, dimy)}; 153 | shape.createLoop(vertices, 4); 154 | ground.createFixture(shape, 0.0f); 155 | 156 | world.bodies.add(ground, false, color(0), true, color(0), 1f); 157 | } 158 | 159 | 160 | 161 | { 162 | PolygonShape shape = new PolygonShape(); 163 | ParticleGroupDef pd = new ParticleGroupDef(); 164 | 165 | pd.flags = 0 166 | | ParticleType.b2_waterParticle 167 | | ParticleType.b2_viscousParticle 168 | | ParticleType.b2_colorMixingParticle 169 | // | ParticleType.b2_powderParticle 170 | // | ParticleType.b2_springParticle 171 | // | ParticleType.b2_tensileParticle 172 | ; 173 | 174 | float sx = dimxh * 0.25f; 175 | float sy = dimyh * 0.95f; 176 | 177 | shape.setAsBox(sx, sy, new Vec2(-dimxh/2, dimyh), 0); 178 | pd.shape = shape; 179 | pd.setColor(new Color3f(0.00f, 0.2f, 1)); 180 | world.createParticleGroup(pd); 181 | 182 | shape.setAsBox(sx, sy, new Vec2(+dimxh/2, dimyh), 0); 183 | pd.shape = shape; 184 | pd.setColor(new Color3f(1.00f, 0.2f, 0.00f)); 185 | world.createParticleGroup(pd); 186 | } 187 | } 188 | 189 | 190 | 191 | public static void main(String args[]) { 192 | PApplet.main(new String[] { liquidfun_DamBreak.class.getName() }); 193 | } 194 | 195 | } -------------------------------------------------------------------------------- /examples/liquidfun_DamBreak_LiquidFx/liquidfun_DamBreak_LiquidFx.java: -------------------------------------------------------------------------------- 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 liquidfun_DamBreak_LiquidFx; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import com.thomasdiewald.pixelflow.java.DwPixelFlow; 19 | import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwLiquidFX; 20 | 21 | import org.jbox2d.collision.shapes.ChainShape; 22 | import org.jbox2d.collision.shapes.PolygonShape; 23 | import org.jbox2d.common.Color3f; 24 | import org.jbox2d.common.Vec2; 25 | import org.jbox2d.dynamics.Body; 26 | import org.jbox2d.dynamics.BodyDef; 27 | import org.jbox2d.particle.ParticleGroupDef; 28 | import org.jbox2d.particle.ParticleType; 29 | 30 | import processing.core.*; 31 | import processing.opengl.PGraphics2D; 32 | 33 | 34 | public class liquidfun_DamBreak_LiquidFx extends PApplet { 35 | 36 | // 37 | // Simulation of a clash of two big particle-groups. 38 | // 39 | // required libraries: 40 | // - PixelFlow, https://github.com/diwi/PixelFlow 41 | // 42 | // 43 | // Controls: 44 | // 45 | // LMB ... drag bodies 46 | // LMB + SHIFT ... shoot bullet 47 | // MMB ... add particles 48 | // RMB ... remove particles 49 | // 'r' ... reset 50 | // 't' ... update/pause physics 51 | // 'f' ... toggle debug draw 52 | // 'g' ... toggle DwLiquidFX 53 | // 54 | 55 | int viewport_w = 1280; 56 | int viewport_h = 720; 57 | int viewport_x = 230; 58 | int viewport_y = 0; 59 | 60 | boolean UPDATE_PHYSICS = true; 61 | boolean USE_DEBUG_DRAW = false; 62 | boolean APPLY_LIQUID_FX = true; 63 | 64 | DwWorld world; 65 | 66 | DwPixelFlow pixelflow; 67 | DwLiquidFX liquidfx; 68 | 69 | PGraphics2D pg_particles; 70 | 71 | // PImage sprite; 72 | 73 | public void settings(){ 74 | size(viewport_w, viewport_h, P2D); 75 | smooth(8); 76 | } 77 | 78 | 79 | public void setup(){ 80 | surface.setLocation(viewport_x, viewport_y); 81 | // sprite = loadImage("sprite.png"); 82 | 83 | pixelflow = new DwPixelFlow(this); 84 | liquidfx = new DwLiquidFX(pixelflow); 85 | 86 | pg_particles = (PGraphics2D) createGraphics(width, height, P2D); 87 | 88 | reset(); 89 | frameRate(120); 90 | } 91 | 92 | 93 | public void release(){ 94 | if(world != null) world.release(); world = null; 95 | } 96 | 97 | 98 | public void reset(){ 99 | // release old resources 100 | release(); 101 | 102 | world = new DwWorld(this, 18); 103 | world.particles.param.falloff_exp1 = 3; 104 | world.particles.param.falloff_exp2 = 1; 105 | world.particles.param.radius_scale = 2; 106 | 107 | // create scene: rigid bodies, particles, etc ... 108 | initScene(); 109 | } 110 | 111 | 112 | 113 | public void draw(){ 114 | if(UPDATE_PHYSICS){ 115 | world.update(); 116 | } 117 | 118 | 119 | int BACKGROUND = 32; 120 | 121 | if(USE_DEBUG_DRAW){ 122 | PGraphics2D canvas = (PGraphics2D) this.g; 123 | 124 | canvas.background(BACKGROUND); 125 | canvas.pushMatrix(); 126 | world.applyTransform(canvas); 127 | world.drawBulletSpawnTrack(canvas); 128 | world.displayDebugDraw(canvas); 129 | canvas.popMatrix(); 130 | } else { 131 | PGraphics2D canvas = (PGraphics2D) pg_particles; 132 | 133 | canvas.beginDraw(); 134 | canvas.clear(); 135 | canvas.background(BACKGROUND, 0); 136 | world.applyTransform(canvas); 137 | world.particles.display(canvas, 0); 138 | canvas.endDraw(); 139 | 140 | if(APPLY_LIQUID_FX) 141 | { 142 | liquidfx.param.base_LoD = 1; 143 | liquidfx.param.base_blur_radius = 2; 144 | liquidfx.param.base_threshold = 0.7f; 145 | liquidfx.param.highlight_enabled = true; 146 | liquidfx.param.highlight_LoD = 1; 147 | liquidfx.param.highlight_decay = 0.6f; 148 | liquidfx.param.sss_enabled = true; 149 | liquidfx.param.sss_LoD = 3; 150 | liquidfx.param.sss_decay = 0.5f; 151 | liquidfx.apply(canvas); 152 | } 153 | 154 | background(BACKGROUND); 155 | image(canvas, 0, 0); 156 | pushMatrix(); 157 | world.applyTransform(this.g); 158 | world.drawBulletSpawnTrack(this.g); 159 | popMatrix(); 160 | } 161 | 162 | 163 | 164 | 165 | // info 166 | int num_bodies = world.getBodyCount(); 167 | int num_particles = world.getParticleCount(); 168 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 169 | surface.setTitle(txt_fps); 170 | } 171 | 172 | 173 | 174 | ////////////////////////////////////////////////////////////////////////////// 175 | // User Interaction 176 | ////////////////////////////////////////////////////////////////////////////// 177 | public void keyReleased(){ 178 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 179 | if(key == 'r') reset(); 180 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 181 | if(key == 'g') APPLY_LIQUID_FX = !APPLY_LIQUID_FX; 182 | } 183 | 184 | 185 | 186 | ////////////////////////////////////////////////////////////////////////////// 187 | // Scene Setup 188 | ////////////////////////////////////////////////////////////////////////////// 189 | 190 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/DamBreak.java 191 | public void initScene() { 192 | 193 | float dimx = world.transform.box2d_dimx; 194 | float dimy = world.transform.box2d_dimy; 195 | 196 | float dimxh = dimx/2; 197 | float dimyh = dimy/2; 198 | 199 | { 200 | BodyDef bd = new BodyDef(); 201 | Body ground = world.createBody(bd); 202 | 203 | ChainShape shape = new ChainShape(); 204 | Vec2[] vertices = {new Vec2(-dimxh, 0), new Vec2(dimxh, 0), new Vec2(dimxh, dimy), new Vec2(-dimxh, dimy)}; 205 | shape.createLoop(vertices, 4); 206 | ground.createFixture(shape, 0.0f); 207 | 208 | world.bodies.add(ground, false, color(0), true, color(0), 1f); 209 | } 210 | 211 | 212 | 213 | { 214 | PolygonShape shape = new PolygonShape(); 215 | ParticleGroupDef pd = new ParticleGroupDef(); 216 | 217 | pd.flags = 0 218 | | ParticleType.b2_waterParticle 219 | | ParticleType.b2_viscousParticle 220 | | ParticleType.b2_colorMixingParticle 221 | // | ParticleType.b2_powderParticle 222 | // | ParticleType.b2_springParticle 223 | // | ParticleType.b2_tensileParticle 224 | ; 225 | 226 | float sx = dimxh * 0.25f; 227 | float sy = dimyh * 0.95f; 228 | 229 | shape.setAsBox(sx, sy, new Vec2(-dimxh/2, dimyh), 0); 230 | pd.shape = shape; 231 | pd.setColor(new Color3f(0.00f, 0.2f, 1)); 232 | world.createParticleGroup(pd); 233 | 234 | shape.setAsBox(sx, sy, new Vec2(+dimxh/2, dimyh), 0); 235 | pd.shape = shape; 236 | pd.setColor(new Color3f(1.00f, 0.2f, 0.00f)); 237 | world.createParticleGroup(pd); 238 | } 239 | } 240 | 241 | 242 | 243 | public static void main(String args[]) { 244 | PApplet.main(new String[] { liquidfun_DamBreak_LiquidFx.class.getName() }); 245 | } 246 | 247 | } -------------------------------------------------------------------------------- /examples/liquidfun_DamBreak_PShapeParticles/liquidfun_DamBreak_PShapeParticles.java: -------------------------------------------------------------------------------- 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 liquidfun_DamBreak_PShapeParticles; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import com.thomasdiewald.liquidfun.java.render.DwParticleRenderGL; 19 | import com.thomasdiewald.liquidfun.java.render.DwParticleRenderP5; 20 | 21 | import org.jbox2d.collision.shapes.ChainShape; 22 | import org.jbox2d.collision.shapes.PolygonShape; 23 | import org.jbox2d.common.Color3f; 24 | import org.jbox2d.common.Vec2; 25 | import org.jbox2d.dynamics.Body; 26 | import org.jbox2d.dynamics.BodyDef; 27 | import org.jbox2d.particle.ParticleGroupDef; 28 | import org.jbox2d.particle.ParticleType; 29 | 30 | import processing.core.*; 31 | import processing.opengl.PGraphics2D; 32 | 33 | 34 | public class liquidfun_DamBreak_PShapeParticles extends PApplet { 35 | 36 | 37 | // 38 | // Simulation of a clash of two big particle-groups. 39 | // 40 | // 41 | // Controls: 42 | // 43 | // LMB ... drag bodies 44 | // LMB + SHIFT ... shoot bullet 45 | // MMB ... add particles 46 | // RMB ... remove particles 47 | // 'r' ... reset 48 | // 't' ... update/pause physics 49 | // 'f' ... toggle debug draw 50 | // 51 | 52 | 53 | int viewport_w = 1280; 54 | int viewport_h = 720; 55 | int viewport_x = 230; 56 | int viewport_y = 0; 57 | 58 | boolean UPDATE_PHYSICS = true; 59 | boolean USE_DEBUG_DRAW = false; 60 | 61 | DwWorld world; 62 | 63 | // PImage sprite; 64 | 65 | public void settings(){ 66 | size(viewport_w, viewport_h, P2D); 67 | smooth(8); 68 | } 69 | 70 | 71 | public void setup(){ 72 | surface.setLocation(viewport_x, viewport_y); 73 | // sprite = loadImage("sprite.png"); 74 | 75 | 76 | reset(); 77 | frameRate(120); 78 | } 79 | 80 | 81 | public void release(){ 82 | if(world != null) world.release(); world = null; 83 | } 84 | 85 | 86 | public void reset(){ 87 | // release old resources 88 | release(); 89 | 90 | // if false, PShape-Quads are used for particles, instead of openGL points. 91 | // this replaces the default particle renderer (OpenGL) with an alternative 92 | // renderer where particles are rendered as PShape-Quads. 93 | // It renders a bit slower then the OpenGL version and grouped rendering 94 | // is also not possible. 95 | DwWorld.INIT_GL_PARTICLES = false; 96 | 97 | // create world 98 | world = new DwWorld(this, 18); 99 | 100 | // just for checking 101 | System.out.println("PShape Particles = "+(world.particles instanceof DwParticleRenderP5)); 102 | System.out.println("OpenGL Particles = "+(world.particles instanceof DwParticleRenderGL)); 103 | 104 | // create scene: rigid bodies, particles, etc ... 105 | initScene(); 106 | } 107 | 108 | 109 | 110 | public void draw(){ 111 | if(UPDATE_PHYSICS){ 112 | world.update(); 113 | } 114 | 115 | PGraphics2D canvas = (PGraphics2D) this.g; 116 | canvas.background(32); 117 | canvas.pushMatrix(); 118 | world.applyTransform(canvas); 119 | world.drawBulletSpawnTrack(canvas); 120 | if(USE_DEBUG_DRAW){ 121 | world.displayDebugDraw(canvas); 122 | // DwDebugDraw.display(canvas, world); 123 | } else { 124 | world.display(canvas); 125 | } 126 | canvas.popMatrix(); 127 | 128 | // info 129 | int num_bodies = world.getBodyCount(); 130 | int num_particles = world.getParticleCount(); 131 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 132 | surface.setTitle(txt_fps); 133 | } 134 | 135 | 136 | 137 | ////////////////////////////////////////////////////////////////////////////// 138 | // User Interaction 139 | ////////////////////////////////////////////////////////////////////////////// 140 | public void keyReleased(){ 141 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 142 | if(key == 'r') reset(); 143 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 144 | } 145 | 146 | 147 | 148 | ////////////////////////////////////////////////////////////////////////////// 149 | // Scene Setup 150 | ////////////////////////////////////////////////////////////////////////////// 151 | 152 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/DamBreak.java 153 | public void initScene() { 154 | 155 | float dimx = world.transform.box2d_dimx; 156 | float dimy = world.transform.box2d_dimy; 157 | 158 | float dimxh = dimx/2; 159 | float dimyh = dimy/2; 160 | 161 | { 162 | BodyDef bd = new BodyDef(); 163 | Body ground = world.createBody(bd); 164 | 165 | ChainShape shape = new ChainShape(); 166 | Vec2[] vertices = {new Vec2(-dimxh, 0), new Vec2(dimxh, 0), new Vec2(dimxh, dimy), new Vec2(-dimxh, dimy)}; 167 | shape.createLoop(vertices, 4); 168 | ground.createFixture(shape, 0.0f); 169 | 170 | world.bodies.add(ground, false, color(0), true, color(0), 1f); 171 | } 172 | 173 | 174 | 175 | { 176 | PolygonShape shape = new PolygonShape(); 177 | ParticleGroupDef pd = new ParticleGroupDef(); 178 | 179 | pd.flags = 0 180 | | ParticleType.b2_waterParticle 181 | | ParticleType.b2_viscousParticle 182 | | ParticleType.b2_colorMixingParticle 183 | // | ParticleType.b2_powderParticle 184 | // | ParticleType.b2_springParticle 185 | // | ParticleType.b2_tensileParticle 186 | ; 187 | 188 | float sx = dimxh * 0.25f; 189 | float sy = dimyh * 0.95f; 190 | 191 | shape.setAsBox(sx, sy, new Vec2(-dimxh/2, dimyh), 0); 192 | pd.shape = shape; 193 | pd.setColor(new Color3f(0.00f, 0.2f, 1)); 194 | world.createParticleGroup(pd); 195 | 196 | shape.setAsBox(sx, sy, new Vec2(+dimxh/2, dimyh), 0); 197 | pd.shape = shape; 198 | pd.setColor(new Color3f(1.00f, 0.2f, 0.00f)); 199 | world.createParticleGroup(pd); 200 | } 201 | } 202 | 203 | 204 | 205 | public static void main(String args[]) { 206 | PApplet.main(new String[] { liquidfun_DamBreak_PShapeParticles.class.getName() }); 207 | } 208 | 209 | } -------------------------------------------------------------------------------- /examples/liquidfun_LiquidTimer/liquidfun_LiquidTimer.java: -------------------------------------------------------------------------------- 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 liquidfun_LiquidTimer; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.ChainShape; 19 | import org.jbox2d.collision.shapes.EdgeShape; 20 | import org.jbox2d.collision.shapes.PolygonShape; 21 | import org.jbox2d.common.Color3f; 22 | import org.jbox2d.common.Vec2; 23 | import org.jbox2d.dynamics.Body; 24 | import org.jbox2d.dynamics.BodyDef; 25 | import org.jbox2d.particle.ParticleGroupDef; 26 | import org.jbox2d.particle.ParticleType; 27 | 28 | import processing.core.*; 29 | import processing.opengl.PGraphics2D; 30 | 31 | 32 | public class liquidfun_LiquidTimer extends PApplet { 33 | 34 | 35 | // 36 | // Liquid Timer Demo 37 | // 38 | // 39 | // 40 | // Controls: 41 | // 42 | // LMB ... drag bodies 43 | // LMB + SHIFT ... shoot bullet 44 | // MMB ... add particles 45 | // RMB ... remove particles 46 | // 'r' ... reset 47 | // 't' ... update/pause physics 48 | // 'f' ... toggle debug draw 49 | // 50 | 51 | 52 | int viewport_w = 1280; 53 | int viewport_h = 720; 54 | int viewport_x = 230; 55 | int viewport_y = 0; 56 | 57 | boolean UPDATE_PHYSICS = true; 58 | boolean USE_DEBUG_DRAW = false; 59 | 60 | DwWorld world; 61 | // PImage sprite; 62 | 63 | public void settings(){ 64 | size(viewport_w, viewport_h, P2D); 65 | smooth(8); 66 | } 67 | 68 | 69 | public void setup(){ 70 | surface.setLocation(viewport_x, viewport_y); 71 | // sprite = loadImage("sprite.png"); 72 | reset(); 73 | frameRate(120); 74 | } 75 | 76 | 77 | public void release(){ 78 | if(world != null) world.release(); world = null; 79 | } 80 | 81 | 82 | public void reset(){ 83 | // release old resources 84 | release(); 85 | 86 | world = new DwWorld(this, 18); 87 | 88 | // create scene: rigid bodies, particles, etc ... 89 | initScene(); 90 | } 91 | 92 | 93 | 94 | public void draw(){ 95 | 96 | if(UPDATE_PHYSICS){ 97 | world.update(); 98 | } 99 | 100 | PGraphics2D canvas = (PGraphics2D) this.g; 101 | canvas.background(32); 102 | canvas.pushMatrix(); 103 | world.applyTransform(canvas); 104 | world.drawBulletSpawnTrack(canvas); 105 | if(USE_DEBUG_DRAW){ 106 | world.displayDebugDraw(canvas); 107 | // DwDebugDraw.display(canvas, world); 108 | } else { 109 | world.display(canvas); 110 | } 111 | canvas.popMatrix(); 112 | 113 | // info 114 | int num_bodies = world.getBodyCount(); 115 | int num_particles = world.getParticleCount(); 116 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 117 | surface.setTitle(txt_fps); 118 | } 119 | 120 | 121 | 122 | ////////////////////////////////////////////////////////////////////////////// 123 | // User Interaction 124 | ////////////////////////////////////////////////////////////////////////////// 125 | public void keyReleased(){ 126 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 127 | if(key == 'r') reset(); 128 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 129 | } 130 | 131 | 132 | 133 | ////////////////////////////////////////////////////////////////////////////// 134 | // Scene Setup 135 | ////////////////////////////////////////////////////////////////////////////// 136 | 137 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/LiquidTimer.java 138 | public void initScene() { 139 | 140 | { 141 | BodyDef bd = new BodyDef(); 142 | Body ground = world.createBody(bd); 143 | 144 | ChainShape shape = new ChainShape(); 145 | final Vec2[] vertices = {new Vec2(-20, 0), new Vec2(20, 0), new Vec2(20, 40), new Vec2(-20, 40)}; 146 | shape.createLoop(vertices, 4); 147 | ground.createFixture(shape, 0.0f); 148 | 149 | world.bodies.add(ground, false, color(0), true, color(255), 1f); 150 | } 151 | 152 | 153 | { 154 | BodyDef bd = new BodyDef(); 155 | Body body = world.createBody(bd); 156 | EdgeShape shape = new EdgeShape(); 157 | shape.set(new Vec2(-20, 32), new Vec2(-12, 32)); 158 | body.createFixture(shape, 0.1f); 159 | world.bodies.add(body, false, color(0), true, color(255), 1f); 160 | } 161 | 162 | { 163 | BodyDef bd = new BodyDef(); 164 | Body body = world.createBody(bd); 165 | EdgeShape shape = new EdgeShape(); 166 | shape.set(new Vec2(-11, 32), new Vec2(20, 32)); 167 | body.createFixture(shape, 0.1f); 168 | world.bodies.add(body, false, color(0), true, color(255), 1f); 169 | } 170 | 171 | { 172 | BodyDef bd = new BodyDef(); 173 | Body body = world.createBody(bd); 174 | EdgeShape shape = new EdgeShape(); 175 | shape.set(new Vec2(-12, 32), new Vec2(-12, 28)); 176 | body.createFixture(shape, 0.1f); 177 | world.bodies.add(body, false, color(0), true, color(255), 1f); 178 | } 179 | 180 | { 181 | BodyDef bd = new BodyDef(); 182 | Body body = world.createBody(bd); 183 | EdgeShape shape = new EdgeShape(); 184 | shape.set(new Vec2(-11, 32), new Vec2(-11, 28)); 185 | body.createFixture(shape, 0.1f); 186 | world.bodies.add(body, false, color(0), true, color(255), 1f); 187 | } 188 | 189 | { 190 | BodyDef bd = new BodyDef(); 191 | Body body = world.createBody(bd); 192 | EdgeShape shape = new EdgeShape(); 193 | shape.set(new Vec2(-16, 24), new Vec2(8, 20)); 194 | body.createFixture(shape, 0.1f); 195 | world.bodies.add(body, false, color(0), true, color(255), 1f); 196 | } 197 | 198 | { 199 | BodyDef bd = new BodyDef(); 200 | Body body = world.createBody(bd); 201 | EdgeShape shape = new EdgeShape(); 202 | shape.set(new Vec2(16, 16), new Vec2(-8, 12)); 203 | body.createFixture(shape, 0.1f); 204 | world.bodies.add(body, false, color(0), true, color(255), 1f); 205 | } 206 | 207 | { 208 | BodyDef bd = new BodyDef(); 209 | Body body = world.createBody(bd); 210 | EdgeShape shape = new EdgeShape(); 211 | shape.set(new Vec2(-12, 8), new Vec2(-12, 0)); 212 | body.createFixture(shape, 0.1f); 213 | world.bodies.add(body, false, color(0), true, color(255), 1f); 214 | } 215 | 216 | { 217 | BodyDef bd = new BodyDef(); 218 | Body body = world.createBody(bd); 219 | EdgeShape shape = new EdgeShape(); 220 | shape.set(new Vec2(-4, 8), new Vec2(-4, 0)); 221 | body.createFixture(shape, 0.1f); 222 | world.bodies.add(body, false, color(0), true, color(255), 1f); 223 | } 224 | 225 | { 226 | BodyDef bd = new BodyDef(); 227 | Body body = world.createBody(bd); 228 | EdgeShape shape = new EdgeShape(); 229 | shape.set(new Vec2(4, 8), new Vec2(4, 0)); 230 | body.createFixture(shape, 0.1f); 231 | world.bodies.add(body, false, color(0), true, color(255), 1f); 232 | } 233 | 234 | { 235 | BodyDef bd = new BodyDef(); 236 | Body body = world.createBody(bd); 237 | EdgeShape shape = new EdgeShape(); 238 | shape.set(new Vec2(12, 8), new Vec2(12, 0)); 239 | body.createFixture(shape, 0.1f); 240 | world.bodies.add(body, false, color(0), true, color(255), 1f); 241 | } 242 | 243 | world.bodies.addAll(); 244 | 245 | 246 | 247 | world.setParticleRadius(0.15f); 248 | // world.setParticleDamping(1f); 249 | { 250 | PolygonShape shape = new PolygonShape(); 251 | shape.setAsBox(20, 4, new Vec2(0, 36), 0); 252 | ParticleGroupDef pd = new ParticleGroupDef(); 253 | pd.flags = ParticleType.b2_waterParticle | ParticleType.b2_viscousParticle; 254 | // pd.flags = ParticleType.b2_tensileParticle | ParticleType.b2_viscousParticle; 255 | pd.shape = shape; 256 | pd.setColor(new Color3f(1, 0.2f, 0.05f)); 257 | world.createParticleGroup(pd); 258 | } 259 | 260 | } 261 | 262 | 263 | 264 | public static void main(String args[]) { 265 | PApplet.main(new String[] { liquidfun_LiquidTimer.class.getName() }); 266 | } 267 | 268 | } -------------------------------------------------------------------------------- /examples/liquidfun_WaveMachine/liquidfun_WaveMachine.java: -------------------------------------------------------------------------------- 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 liquidfun_WaveMachine; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import org.jbox2d.collision.shapes.PolygonShape; 19 | import org.jbox2d.common.Color3f; 20 | import org.jbox2d.common.MathUtils; 21 | import org.jbox2d.common.Vec2; 22 | import org.jbox2d.dynamics.Body; 23 | import org.jbox2d.dynamics.BodyDef; 24 | import org.jbox2d.dynamics.BodyType; 25 | import org.jbox2d.dynamics.joints.RevoluteJoint; 26 | import org.jbox2d.dynamics.joints.RevoluteJointDef; 27 | import org.jbox2d.particle.ParticleGroupDef; 28 | import org.jbox2d.particle.ParticleType; 29 | 30 | import processing.core.*; 31 | import processing.opengl.PGraphics2D; 32 | 33 | 34 | public class liquidfun_WaveMachine extends PApplet { 35 | 36 | // 37 | // Wave Machine Example. 38 | // 39 | // 40 | // Controls: 41 | // 42 | // LMB ... drag bodies 43 | // LMB + SHIFT ... shoot bullet 44 | // MMB ... add particles 45 | // RMB ... remove particles 46 | // 'r' ... reset 47 | // 't' ... update/pause physics 48 | // 'f' ... toggle debug draw 49 | // 50 | 51 | 52 | int viewport_w = 1280; 53 | int viewport_h = 720; 54 | int viewport_x = 230; 55 | int viewport_y = 0; 56 | 57 | boolean UPDATE_PHYSICS = true; 58 | boolean USE_DEBUG_DRAW = false; 59 | 60 | DwWorld world; 61 | // PImage sprite; 62 | 63 | public void settings(){ 64 | size(viewport_w, viewport_h, P2D); 65 | smooth(8); 66 | } 67 | 68 | 69 | public void setup(){ 70 | surface.setLocation(viewport_x, viewport_y); 71 | // sprite = loadImage("sprite.png"); 72 | reset(); 73 | frameRate(120); 74 | } 75 | 76 | 77 | public void release(){ 78 | if(world != null) world.release(); world = null; 79 | } 80 | 81 | 82 | public void reset(){ 83 | // release old resources 84 | release(); 85 | 86 | world = new DwWorld(this, 20); 87 | world.transform.setScreen(width, height, 20, width/2, height/2); 88 | 89 | // create scene: rigid bodies, particles, etc ... 90 | initScene(); 91 | } 92 | 93 | 94 | 95 | public void draw(){ 96 | 97 | if(UPDATE_PHYSICS){ 98 | wave(); 99 | world.update(); 100 | } 101 | 102 | PGraphics2D canvas = (PGraphics2D) this.g; 103 | canvas.background(32); 104 | canvas.pushMatrix(); 105 | world.applyTransform(canvas); 106 | world.drawBulletSpawnTrack(canvas); 107 | if(USE_DEBUG_DRAW){ 108 | world.displayDebugDraw(canvas); 109 | // DwDebugDraw.display(canvas, world); 110 | } else { 111 | world.display(canvas); 112 | } 113 | canvas.popMatrix(); 114 | 115 | // info 116 | int num_bodies = world.getBodyCount(); 117 | int num_particles = world.getParticleCount(); 118 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 119 | surface.setTitle(txt_fps); 120 | } 121 | 122 | 123 | 124 | ////////////////////////////////////////////////////////////////////////////// 125 | // User Interaction 126 | ////////////////////////////////////////////////////////////////////////////// 127 | public void keyReleased(){ 128 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 129 | if(key == 'r') reset(); 130 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 131 | } 132 | 133 | 134 | 135 | ////////////////////////////////////////////////////////////////////////////// 136 | // Scene Setup 137 | ////////////////////////////////////////////////////////////////////////////// 138 | 139 | RevoluteJoint m_joint; 140 | float m_time; 141 | 142 | 143 | public void wave() { 144 | m_time += 1 / 120f; 145 | m_joint.setMotorSpeed(0.1f * MathUtils.cos(m_time) * MathUtils.PI); 146 | } 147 | 148 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/WaveMachine.java 149 | public void initScene() { 150 | 151 | { 152 | BodyDef bd = new BodyDef(); 153 | Body ground = world.createBody(bd); 154 | 155 | bd.type = BodyType.DYNAMIC; 156 | bd.allowSleep = false; 157 | bd.position.set(0.0f, 0.0f); 158 | Body body = world.createBody(bd); 159 | 160 | PolygonShape shape = new PolygonShape(); 161 | shape.setAsBox(1, 9.5f, new Vec2(19.0f, 0.0f), 0.0f); 162 | body.createFixture(shape, 5.0f); 163 | shape.setAsBox(1, 9.5f, new Vec2(-19.0f, 0.0f), 0.0f); 164 | body.createFixture(shape, 5.0f); 165 | shape.setAsBox(20.0f, 1, new Vec2(0.0f, 11.0f), 0.0f); 166 | body.createFixture(shape, 5.0f); 167 | shape.setAsBox(20.0f, 1, new Vec2(0.0f, -11.0f), 0.0f); 168 | body.createFixture(shape, 5.0f); 169 | 170 | world.bodies.add(body, true, color(0), true, color(0), 1f); 171 | 172 | RevoluteJointDef jd = new RevoluteJointDef(); 173 | jd.bodyA = ground; 174 | jd.bodyB = body; 175 | jd.localAnchorA.set(0.0f, 0.0f); 176 | jd.localAnchorB.set(0.0f, 0.0f); 177 | jd.referenceAngle = 0.0f; 178 | jd.motorSpeed = 0.05f * MathUtils.PI; 179 | jd.maxMotorTorque = 1e7f; 180 | jd.enableMotor = true; 181 | m_joint = (RevoluteJoint) world.createJoint(jd); 182 | } 183 | 184 | world.bodies.addAll(); 185 | 186 | 187 | 188 | world.setParticleRadius(0.15f); 189 | world.setParticleDamping(0.6f); 190 | 191 | { 192 | ParticleGroupDef pd = new ParticleGroupDef(); 193 | pd.flags = ParticleType.b2_waterParticle | ParticleType.b2_viscousParticle; 194 | pd.setColor(new Color3f(1, 0.15f, 0.05f)); 195 | PolygonShape shape = new PolygonShape(); 196 | shape.setAsBox(17.0f, 9.0f, new Vec2(0.0f, 0.0f), 0.0f); 197 | 198 | pd.shape = shape; 199 | world.createParticleGroup(pd); 200 | } 201 | 202 | m_time = 0; 203 | 204 | } 205 | 206 | 207 | 208 | 209 | 210 | public static void main(String args[]) { 211 | PApplet.main(new String[] { liquidfun_WaveMachine.class.getName() }); 212 | } 213 | 214 | } -------------------------------------------------------------------------------- /examples/liquidfun_WaveMachine_LiquidFx/liquidfun_WaveMachine_LiquidFx.java: -------------------------------------------------------------------------------- 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 liquidfun_WaveMachine_LiquidFx; 15 | 16 | 17 | import com.thomasdiewald.liquidfun.java.DwWorld; 18 | import com.thomasdiewald.pixelflow.java.DwPixelFlow; 19 | import com.thomasdiewald.pixelflow.java.imageprocessing.filter.DwLiquidFX; 20 | 21 | import org.jbox2d.collision.shapes.PolygonShape; 22 | import org.jbox2d.common.Color3f; 23 | import org.jbox2d.common.MathUtils; 24 | import org.jbox2d.common.Vec2; 25 | import org.jbox2d.dynamics.Body; 26 | import org.jbox2d.dynamics.BodyDef; 27 | import org.jbox2d.dynamics.BodyType; 28 | import org.jbox2d.dynamics.joints.RevoluteJoint; 29 | import org.jbox2d.dynamics.joints.RevoluteJointDef; 30 | import org.jbox2d.particle.ParticleGroupDef; 31 | import org.jbox2d.particle.ParticleType; 32 | 33 | import processing.core.*; 34 | import processing.opengl.PGraphics2D; 35 | 36 | 37 | public class liquidfun_WaveMachine_LiquidFx extends PApplet { 38 | 39 | // 40 | // Wave Machine Example. 41 | // 42 | // required libraries: 43 | // - PixelFlow, https://github.com/diwi/PixelFlow 44 | // 45 | // 46 | // Controls: 47 | // 48 | // LMB ... drag bodies 49 | // LMB + SHIFT ... shoot bullet 50 | // MMB ... add particles 51 | // RMB ... remove particles 52 | // 'r' ... reset 53 | // 't' ... update/pause physics 54 | // 'f' ... toggle debug draw 55 | // 'g' ... toggle DwLiquidFX 56 | // 57 | 58 | 59 | int viewport_w = 1280; 60 | int viewport_h = 720; 61 | int viewport_x = 230; 62 | int viewport_y = 0; 63 | 64 | boolean UPDATE_PHYSICS = true; 65 | boolean USE_DEBUG_DRAW = false; 66 | boolean APPLY_LIQUID_FX = true; 67 | 68 | DwWorld world; 69 | // PImage sprite; 70 | 71 | DwPixelFlow pixelflow; 72 | DwLiquidFX liquidfx; 73 | 74 | PGraphics2D pg_particles; 75 | 76 | public void settings(){ 77 | size(viewport_w, viewport_h, P2D); 78 | smooth(8); 79 | } 80 | 81 | 82 | public void setup(){ 83 | surface.setLocation(viewport_x, viewport_y); 84 | // sprite = loadImage("sprite.png"); 85 | 86 | pixelflow = new DwPixelFlow(this); 87 | liquidfx = new DwLiquidFX(pixelflow); 88 | 89 | pg_particles = (PGraphics2D) createGraphics(width, height, P2D); 90 | 91 | 92 | reset(); 93 | frameRate(120); 94 | } 95 | 96 | 97 | public void release(){ 98 | if(world != null) world.release(); world = null; 99 | } 100 | 101 | 102 | public void reset(){ 103 | // release old resources 104 | release(); 105 | 106 | world = new DwWorld(this, 20); 107 | world.transform.setScreen(width, height, 20, width/2, height/2); 108 | 109 | // world.particles.param.falloff_exp1 = 2; 110 | // world.particles.param.falloff_exp2 = 2; 111 | // world.particles.param.radius_scale = 3; 112 | 113 | world.particles.param.falloff_exp1 = 3; 114 | world.particles.param.falloff_exp2 = 1; 115 | world.particles.param.radius_scale = 2; 116 | 117 | // create scene: rigid bodies, particles, etc ... 118 | initScene(); 119 | } 120 | 121 | 122 | 123 | public void draw(){ 124 | 125 | if(UPDATE_PHYSICS){ 126 | wave(); 127 | world.update(); 128 | } 129 | 130 | int BACKGROUND = 32; 131 | 132 | if(USE_DEBUG_DRAW){ 133 | PGraphics2D canvas = (PGraphics2D) this.g; 134 | 135 | canvas.background(BACKGROUND); 136 | canvas.pushMatrix(); 137 | world.applyTransform(canvas); 138 | world.drawBulletSpawnTrack(canvas); 139 | world.displayDebugDraw(canvas); 140 | canvas.popMatrix(); 141 | } else { 142 | PGraphics2D canvas = (PGraphics2D) pg_particles; 143 | 144 | canvas.beginDraw(); 145 | canvas.clear(); 146 | canvas.background(BACKGROUND, 0); 147 | world.applyTransform(canvas); 148 | world.particles.display(canvas, 0); 149 | canvas.endDraw(); 150 | 151 | if(APPLY_LIQUID_FX) 152 | { 153 | liquidfx.param.base_LoD = 1; 154 | liquidfx.param.base_blur_radius = 2; 155 | liquidfx.param.base_threshold = 0.7f; 156 | liquidfx.param.highlight_enabled = true; 157 | liquidfx.param.highlight_LoD = 1; 158 | liquidfx.param.highlight_decay = 0.6f; 159 | liquidfx.param.sss_enabled = true; 160 | liquidfx.param.sss_LoD = 3; 161 | liquidfx.param.sss_decay = 0.5f; 162 | liquidfx.apply(canvas); 163 | } 164 | 165 | background(BACKGROUND); 166 | image(canvas, 0, 0); 167 | pushMatrix(); 168 | world.applyTransform(this.g); 169 | world.bodies.display((PGraphics2D) this.g); 170 | world.drawBulletSpawnTrack(this.g); 171 | popMatrix(); 172 | } 173 | 174 | // info 175 | int num_bodies = world.getBodyCount(); 176 | int num_particles = world.getParticleCount(); 177 | String txt_fps = String.format(getClass().getName()+ " [bodies: %d] [particles: %d] [fps %6.2f]", num_bodies, num_particles, frameRate); 178 | surface.setTitle(txt_fps); 179 | } 180 | 181 | 182 | 183 | ////////////////////////////////////////////////////////////////////////////// 184 | // User Interaction 185 | ////////////////////////////////////////////////////////////////////////////// 186 | public void keyReleased(){ 187 | if(key == 't') UPDATE_PHYSICS = !UPDATE_PHYSICS; 188 | if(key == 'r') reset(); 189 | if(key == 'f') USE_DEBUG_DRAW = !USE_DEBUG_DRAW; 190 | if(key == 'g') APPLY_LIQUID_FX = !APPLY_LIQUID_FX; 191 | } 192 | 193 | 194 | 195 | ////////////////////////////////////////////////////////////////////////////// 196 | // Scene Setup 197 | ////////////////////////////////////////////////////////////////////////////// 198 | 199 | RevoluteJoint m_joint; 200 | float m_time; 201 | 202 | 203 | public void wave() { 204 | m_time += 1 / 120f; 205 | m_joint.setMotorSpeed(0.1f * MathUtils.cos(m_time) * MathUtils.PI); 206 | } 207 | 208 | // https://github.com/jbox2d/jbox2d/blob/master/jbox2d-testbed/src/main/java/org/jbox2d/testbed/tests/WaveMachine.java 209 | public void initScene() { 210 | 211 | { 212 | BodyDef bd = new BodyDef(); 213 | Body ground = world.createBody(bd); 214 | 215 | bd.type = BodyType.DYNAMIC; 216 | bd.allowSleep = false; 217 | bd.position.set(0.0f, 0.0f); 218 | Body body = world.createBody(bd); 219 | 220 | PolygonShape shape = new PolygonShape(); 221 | shape.setAsBox(1, 9.5f, new Vec2(19.0f, 0.0f), 0.0f); 222 | body.createFixture(shape, 5.0f); 223 | shape.setAsBox(1, 9.5f, new Vec2(-19.0f, 0.0f), 0.0f); 224 | body.createFixture(shape, 5.0f); 225 | shape.setAsBox(20.0f, 1, new Vec2(0.0f, 11.0f), 0.0f); 226 | body.createFixture(shape, 5.0f); 227 | shape.setAsBox(20.0f, 1, new Vec2(0.0f, -11.0f), 0.0f); 228 | body.createFixture(shape, 5.0f); 229 | 230 | world.bodies.add(body, true, color(0), true, color(0), 1f); 231 | 232 | RevoluteJointDef jd = new RevoluteJointDef(); 233 | jd.bodyA = ground; 234 | jd.bodyB = body; 235 | jd.localAnchorA.set(0.0f, 0.0f); 236 | jd.localAnchorB.set(0.0f, 0.0f); 237 | jd.referenceAngle = 0.0f; 238 | jd.motorSpeed = 0.05f * MathUtils.PI; 239 | jd.maxMotorTorque = 1e7f; 240 | jd.enableMotor = true; 241 | m_joint = (RevoluteJoint) world.createJoint(jd); 242 | } 243 | 244 | world.bodies.addAll(); 245 | 246 | 247 | 248 | world.setParticleRadius(0.15f); 249 | world.setParticleDamping(0.6f); 250 | 251 | { 252 | ParticleGroupDef pd = new ParticleGroupDef(); 253 | pd.flags = ParticleType.b2_waterParticle | ParticleType.b2_viscousParticle; 254 | // pd.setColor(new Color3f(1, 0.10f, 0.01f)); 255 | // pd.setColor(new Color3f(0.05f, 0.15f, 1)); 256 | pd.setColor(new Color3f(0.15f, 1, 0.05f)); 257 | PolygonShape shape = new PolygonShape(); 258 | shape.setAsBox(17.0f, 9.0f, new Vec2(0.0f, 0.0f), 0.0f); 259 | 260 | pd.shape = shape; 261 | world.createParticleGroup(pd); 262 | } 263 | 264 | m_time = 0; 265 | 266 | } 267 | 268 | 269 | 270 | 271 | 272 | public static void main(String args[]) { 273 | PApplet.main(new String[] { liquidfun_WaveMachine_LiquidFx.class.getName() }); 274 | } 275 | 276 | } -------------------------------------------------------------------------------- /screenshots/LiquidFunProcessing_DebugDraw1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/LiquidFunProcessing_DebugDraw1.png -------------------------------------------------------------------------------- /screenshots/LiquidFunProcessing_Draw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/LiquidFunProcessing_Draw.png -------------------------------------------------------------------------------- /screenshots/LiquidFunProcessing_Orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/LiquidFunProcessing_Orange.png -------------------------------------------------------------------------------- /screenshots/LiquidFunProcessing_Timer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/LiquidFunProcessing_Timer.png -------------------------------------------------------------------------------- /screenshots/LiquidFunProcessing_Wavemaschine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/LiquidFunProcessing_Wavemaschine.png -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_BalancedTree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_BalancedTree.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_BlobJoints.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_BlobJoints.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_Chains.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_Chains.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_CircleStress.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_CircleStress.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_Collisions.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_Collisions.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_DamBreak.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_DamBreak.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_DominoPyramid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_DominoPyramid.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_Dominos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_Dominos.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_Examples1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_Examples1.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_Examples2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_Examples2.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_ParticleDrawing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_ParticleDrawing.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_ParticleDrawing1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_ParticleDrawing1.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_ParticleEmitter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_ParticleEmitter.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_ParticleRenderGroup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_ParticleRenderGroup.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_ParticleTypes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_ParticleTypes.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_PistonStress.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_PistonStress.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_Rain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_Rain.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_Tumbler.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_Tumbler.jpg -------------------------------------------------------------------------------- /screenshots/examples/diewald_LiquidFunProcessing_WaveMachine.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/examples/diewald_LiquidFunProcessing_WaveMachine.jpg -------------------------------------------------------------------------------- /screenshots/rendermodes/diewald_LiquidFunProcessing_RenderDebug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/rendermodes/diewald_LiquidFunProcessing_RenderDebug.jpg -------------------------------------------------------------------------------- /screenshots/rendermodes/diewald_LiquidFunProcessing_RenderLiquidFx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/rendermodes/diewald_LiquidFunProcessing_RenderLiquidFx.jpg -------------------------------------------------------------------------------- /screenshots/rendermodes/diewald_LiquidFunProcessing_RenderRaw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/diwi/LiquidFunProcessing/9f6560320f2616c243afffd0e61bc7d243908280/screenshots/rendermodes/diewald_LiquidFunProcessing_RenderRaw.jpg -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/glsl/particle_render.frag: -------------------------------------------------------------------------------- 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 | #version 150 15 | 16 | out vec4 fragColor; 17 | in vec4 var_col; 18 | 19 | uniform sampler2D tex_sprite; 20 | uniform float falloff_exp1 = 1.0; 21 | uniform float falloff_exp2 = 1.0; 22 | uniform float falloff_mult = 1.0; 23 | uniform float color_mult = 1.0; 24 | 25 | uniform float use_sprite = 0.0; 26 | 27 | void main() { 28 | 29 | fragColor = var_col * color_mult; 30 | 31 | if(use_sprite == 1.0){ 32 | fragColor *= texture(tex_sprite, gl_PointCoord); 33 | } else { 34 | vec2 pcoord_norm = abs(gl_PointCoord * 2.0 - 1.0); // abs[-1, 1] 35 | 36 | float falloff = clamp(length(pcoord_norm), 0.0, 1.0); 37 | falloff = pow(falloff, falloff_exp1); 38 | falloff = 1.0 - falloff; 39 | falloff = pow(falloff, falloff_exp2); 40 | 41 | fragColor.a *= falloff * falloff_mult; 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/glsl/particle_render.vert: -------------------------------------------------------------------------------- 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 | #version 150 15 | 16 | uniform mat4 mat_mvp; 17 | uniform float point_size; 18 | 19 | in vec2 pos; // position 20 | in vec2 vel; // velocity 21 | in vec4 col; // color 22 | in vec2 con; // contact [weight, count] 23 | 24 | out vec4 var_col; 25 | 26 | void main() { 27 | gl_Position = mat_mvp * vec4(pos, 0, 1); 28 | //gl_PointSize = point_size; 29 | 30 | var_col = col; 31 | 32 | // float vel_mag = clamp(length(vel) * 0.8, 0.5, 1.5); 33 | // var_col.rgb *= vel_mag; 34 | 35 | 36 | // float con_mult = clamp(con.x * 0.8, 0.5, 1.5); 37 | // var_col.rgb *= con_mult; 38 | 39 | 40 | float vel_mag = length(vel) / 100.0f; 41 | float con_mult = con.x / 50.0f; 42 | 43 | float sum = 1.0 + (con_mult + vel_mag); 44 | sum *= sum; 45 | sum *= sum; 46 | sum *= sum; 47 | //sum = pow(sum, 10); 48 | 49 | 50 | var_col.rgb *= sum; 51 | 52 | // if(sum > 1.2){ 53 | // var_col.rgb = vec3(1.0); 54 | // } 55 | 56 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/glsl/particle_render2.frag: -------------------------------------------------------------------------------- 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 | #version 150 15 | 16 | out vec4 fragColor; 17 | in vec4 tint; 18 | 19 | uniform sampler2D tex_sprite; 20 | 21 | void main() { 22 | fragColor = texture(tex_sprite, gl_PointCoord) * tint; 23 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/glsl/particle_render2.vert: -------------------------------------------------------------------------------- 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 | #version 150 15 | 16 | uniform mat4 mat_mvp; 17 | 18 | in vec2 pos; 19 | in vec4 col; 20 | 21 | out vec4 tint; 22 | 23 | void main() { 24 | gl_Position = mat_mvp * vec4(pos, 0, 1); 25 | tint = col; 26 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/DwParticleEmitter.java: -------------------------------------------------------------------------------- 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 com.thomasdiewald.liquidfun.java; 15 | 16 | import org.jbox2d.common.Vec2; 17 | import org.jbox2d.dynamics.World; 18 | import org.jbox2d.particle.ParticleDef; 19 | 20 | 21 | /** 22 | * 23 | * Custom Particle Emitter.
24 | * 25 | * @author Thomas Diewald 26 | * 27 | */ 28 | public class DwParticleEmitter { 29 | 30 | public World world; 31 | public DwViewportTransform transform; 32 | public ParticleDef pdef = new ParticleDef(); 33 | 34 | public float emit_dir = (float) (Math.PI * 0.5f); 35 | public float emit_vel = 20; 36 | public Vec2 emit_pos = new Vec2(); 37 | 38 | public float emit_dir_jitter = 0.2f; // [0, PI*2] 39 | public float emit_vel_jitter = 0.5f; // noise mult 40 | public float emit_pos_jitter = 0.4f; // spawn radius, world-space 41 | 42 | 43 | protected int counter = 0; 44 | 45 | public DwParticleEmitter(World world, DwViewportTransform transform){ 46 | this.world = world; 47 | this.transform = transform; 48 | } 49 | 50 | 51 | /** 52 | * inline Emitter-definition.
53 | * Velocity and Position must be defined in screen-space dimensions. 54 | */ 55 | public void setInScreen(float pos_x, float pos_y, float vel, float dir_deg, int col_argb, int flags){ 56 | emit_pos = transform.getScreen2box(pos_x, pos_y, emit_pos); 57 | emit_vel = vel / transform.screen_scale; 58 | emit_dir = dir_deg * DwUtils.TO_RAD; 59 | pdef.color.set(col_argb); 60 | pdef.flags = flags; 61 | } 62 | 63 | /** 64 | * inline Emitter-definition.
65 | * Velocity and Position must be defined in world-space dimensions. 66 | */ 67 | public void setInWorld(float pos_x, float pos_y, float vel, float dir_deg, int col_argb, int flags){ 68 | emit_pos.set(pos_x, pos_y); 69 | emit_vel = vel; 70 | emit_dir = dir_deg * DwUtils.TO_RAD; 71 | pdef.color.set(col_argb); 72 | pdef.flags = flags; 73 | } 74 | 75 | 76 | 77 | 78 | 79 | public void emitParticles(int count){ 80 | for(int i = 0; i < count; i++){ 81 | emitParticle(); 82 | } 83 | } 84 | 85 | public void emitParticle(){ 86 | 87 | // velocity (noise) 88 | float val1 = (float) (Math.sin(counter / 10f)) * 0.2f; 89 | float val2 = (float) (Math.cos(counter / 100f)); 90 | float srandnoise = val1 * val2; 91 | 92 | float rot_angle = emit_dir + srandnoise * emit_dir_jitter; 93 | float vel_mag = emit_vel + srandnoise * emit_vel_jitter; 94 | 95 | float vel_x = (float) (Math.cos(rot_angle) * vel_mag); 96 | float vel_y = (float) (Math.sin(rot_angle) * vel_mag); 97 | 98 | // position 99 | float[] jitter = DwUtils.sampleDisk_Halton(counter, 0.5f); 100 | 101 | float pos_x = emit_pos.x + jitter[0] * emit_pos_jitter; 102 | float pos_y = emit_pos.y + jitter[1] * emit_pos_jitter; 103 | 104 | // create Particle 105 | pdef.position.set(pos_x, pos_y); 106 | pdef.velocity.set(vel_x, vel_y); 107 | world.createParticle(pdef); 108 | 109 | counter++; 110 | } 111 | 112 | 113 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/DwViewportTransform.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java; 14 | 15 | import org.jbox2d.common.IViewportTransform; 16 | import org.jbox2d.common.Mat22; 17 | import org.jbox2d.common.Vec2; 18 | 19 | import processing.core.PApplet; 20 | import processing.core.PGraphics; 21 | import processing.core.PMatrix2D; 22 | 23 | /** 24 | * 25 | * 26 | * Coordinate transformation box2d-world <-> screen 27 | * 28 | * @author Thomas Diewald 29 | * 30 | */ 31 | public class DwViewportTransform implements IViewportTransform { 32 | 33 | // flip vertically 34 | protected boolean flip_y = true; 35 | 36 | // box2d stuff 37 | public final Mat22 mat_world_to_screen = new Mat22(1,0,0,1); // identity 38 | public final Mat22 mat_screen_to_world = new Mat22(1,0,0,1); // identity 39 | public final Vec2 center = new Vec2(); 40 | public final Vec2 extents = new Vec2(); 41 | 42 | 43 | // processing stuff, but more or less the same as above 44 | public final PMatrix2D mat_box2screen = new PMatrix2D(); 45 | public final PMatrix2D mat_screen2box = new PMatrix2D(); 46 | 47 | public float screen_scale = 15; 48 | public float screen_dimx; 49 | public float screen_dimy; 50 | public float box2d_dimx; 51 | public float box2d_dimy; 52 | 53 | 54 | public DwViewportTransform() { 55 | } 56 | 57 | public DwViewportTransform(PApplet papplet) { 58 | this(papplet.g); 59 | } 60 | 61 | public DwViewportTransform(PGraphics pg) { 62 | float w = pg.width; 63 | float h = pg.height; 64 | float s = screen_scale; 65 | setScreen(w, h, s, w/2, h); 66 | } 67 | 68 | public DwViewportTransform(float screen_w, int screen_h) { 69 | float w = screen_w; 70 | float h = screen_h; 71 | float s = screen_scale; 72 | setScreen(w, h, s, w/2, h); 73 | } 74 | 75 | 76 | public DwViewportTransform(DwViewportTransform vpt) { 77 | flip_y = vpt.flip_y; 78 | setExtents(vpt.extents); 79 | setCamera(vpt.center.x, vpt.center.y, vpt.screen_scale); 80 | } 81 | 82 | 83 | public DwViewportTransform setSceneScale(float scale){ 84 | screen_scale = scale; 85 | updateMatrix(); 86 | return this; 87 | } 88 | 89 | 90 | public DwViewportTransform setScreen(float dim_x, float dim_y, float scale, float origin_x, float origin_y){ 91 | 92 | float dim_xh = dim_x / 2; 93 | float dim_yh = dim_y / 2; 94 | 95 | float cam_x = (origin_x - dim_xh) / scale; 96 | float cam_y = (origin_y - dim_yh) / scale; 97 | 98 | setExtents(dim_xh, dim_yh); 99 | setCamera(cam_x, cam_y, scale); 100 | return this; 101 | } 102 | 103 | 104 | public void setCamera(float x, float y) { 105 | center.set(x, y); 106 | updateMatrix(); 107 | } 108 | 109 | 110 | 111 | /** 112 | * set origin, in world 113 | */ 114 | @Override 115 | public void setCamera(float x, float y, float scale) { 116 | screen_scale = scale; 117 | center.set(x, y); 118 | updateMatrix(); 119 | } 120 | 121 | @Override 122 | public Vec2 getExtents() { 123 | return extents; 124 | } 125 | 126 | /** 127 | * set origin, in screen coords 128 | */ 129 | @Override 130 | public void setExtents(Vec2 argExtents) { 131 | setExtents(argExtents.x, argExtents.y); 132 | updateMatrix(); 133 | } 134 | 135 | /** 136 | * set origin, in screen coords 137 | */ 138 | @Override 139 | public void setExtents(float halfWidth, float halfHeight) { 140 | extents.set(halfWidth, halfHeight); 141 | } 142 | 143 | @Override 144 | public Vec2 getCenter() { 145 | return center; 146 | } 147 | 148 | @Override 149 | public void setCenter(Vec2 argPos) { 150 | center.set(argPos); 151 | } 152 | 153 | @Override 154 | public void setCenter(float x, float y) { 155 | center.set(x, y); 156 | } 157 | 158 | @Override 159 | public boolean isYFlip() { 160 | return flip_y; 161 | } 162 | 163 | @Override 164 | public void setYFlip(boolean yFlip) { 165 | this.flip_y = yFlip; 166 | } 167 | 168 | @Override 169 | public Mat22 getMat22Representation() { 170 | return mat_world_to_screen; 171 | } 172 | 173 | @Override 174 | public void mulByTransform(Mat22 transform) { 175 | // mat.mulLocal(transform); 176 | System.out.println("DwViewportTransform.mulByTransform is not implemented"); 177 | } 178 | 179 | 180 | 181 | 182 | 183 | 184 | protected void updateMatrix(){ 185 | 186 | // Box2d Matrix: 187 | 188 | // matrix: box2d -> screen 189 | mat_world_to_screen.ex.x = screen_scale; 190 | mat_world_to_screen.ex.y = 0; 191 | mat_world_to_screen.ey.x = 0; 192 | mat_world_to_screen.ey.y = flip_y ? -screen_scale : screen_scale; 193 | 194 | // matrix: screen -> box2d 195 | mat_world_to_screen.invertToOut(mat_screen_to_world); 196 | 197 | 198 | // Processing matrix: 199 | 200 | // matrix: box2d -> screen 201 | mat_box2screen.reset(); 202 | mat_box2screen.translate(extents.x, extents.y); 203 | mat_box2screen.scale(screen_scale, flip_y ? -screen_scale : screen_scale); 204 | mat_box2screen.translate(-center.x, -center.y); 205 | 206 | // matrix: screen -> box2d 207 | mat_screen2box.set(mat_box2screen); 208 | mat_screen2box.invert(); 209 | 210 | 211 | // screen size 212 | screen_dimx = extents.x * 2; 213 | screen_dimy = extents.y * 2; 214 | 215 | // screen size in box world dimensions 216 | box2d_dimx = screen_dimx / screen_scale; 217 | box2d_dimy = screen_dimy / screen_scale; 218 | 219 | } 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | @Override 233 | public void getWorldVectorToScreen(Vec2 world, Vec2 screen) { 234 | mat_world_to_screen.mulToOut(world, screen); 235 | } 236 | 237 | @Override 238 | public void getScreenVectorToWorld(Vec2 screen, Vec2 world) { 239 | mat_screen_to_world.mulToOut(screen, world); 240 | } 241 | 242 | @Override 243 | public void getWorldToScreen(Vec2 world, Vec2 screen) { 244 | screen.x = world.x - center.x; 245 | screen.y = world.y - center.y; 246 | mat_world_to_screen.mulToOut(screen, screen); 247 | screen.x += extents.x; 248 | screen.y += extents.y; 249 | } 250 | 251 | @Override 252 | public void getScreenToWorld(Vec2 screen, Vec2 world) { 253 | world.x = screen.x - extents.x; 254 | world.y = screen.y - extents.y; 255 | mat_screen_to_world.mulToOut(world, world); 256 | world.x += center.x; 257 | world.y += center.y; 258 | } 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | // just some buffers 269 | protected float[] xy1 = new float[2]; 270 | protected float[] xy2 = new float[2]; 271 | 272 | 273 | public Vec2 getBox2screen(float in_box_x, float in_box_y, Vec2 out_screen){ 274 | xy1[0] = in_box_x; 275 | xy1[1] = in_box_y; 276 | mat_box2screen.mult(xy1, xy2); 277 | if(out_screen == null){ 278 | return new Vec2(xy2[0], xy2[1]); 279 | } 280 | return out_screen.set(xy2[0], xy2[1]); 281 | } 282 | 283 | public float[] getBox2screen(float in_box_x, float in_box_y, float[] out_screen){ 284 | xy1[0] = in_box_x; 285 | xy1[1] = in_box_y; 286 | if(out_screen == null){ 287 | out_screen = new float[2]; 288 | } 289 | mat_box2screen.mult(xy1, out_screen); 290 | return out_screen; 291 | } 292 | 293 | 294 | public Vec2 getScreen2box(float in_screen_x, float in_screen_y, Vec2 out_box){ 295 | xy1[0] = in_screen_x; 296 | xy1[1] = in_screen_y; 297 | mat_screen2box.mult(xy1, xy2); 298 | if(out_box == null){ 299 | return new Vec2(xy2[0], xy2[1]); 300 | } 301 | return out_box.set(xy2[0], xy2[1]); 302 | } 303 | 304 | 305 | public float[] getScreen2box(float in_screen_x, float in_screen_y, float[] out_box){ 306 | xy1[0] = in_screen_x; 307 | xy1[1] = in_screen_y; 308 | if(out_box == null){ 309 | out_box = new float[2]; 310 | } 311 | mat_screen2box.mult(xy1, out_box); 312 | return out_box; 313 | } 314 | 315 | 316 | 317 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/interaction/DwInteractionEvent.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.interaction; 13 | 14 | import processing.event.KeyEvent; 15 | import processing.event.MouseEvent; 16 | 17 | 18 | /** 19 | * Interface for mouse interactions, mainly used by DwWorld to have some 20 | * default interaction handlers. 21 | * 22 | * @author Thomas Diewald 23 | * 24 | */ 25 | public interface DwInteractionEvent { 26 | 27 | public void enable(boolean enable); 28 | public boolean isEnabled(); 29 | 30 | public boolean isActive(); 31 | 32 | public void setMouseButton(int button); 33 | public int getMouseButton(); 34 | 35 | public void mouseEvent(MouseEvent event); 36 | public void keyEvent(KeyEvent event); 37 | public void updateEvent(); 38 | 39 | public void setMouseOffset(int mouseX_off, int mouseY_off); 40 | } 41 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/interaction/DwMouseDragBodies.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.interaction; 14 | 15 | import org.jbox2d.callbacks.QueryCallback; 16 | import org.jbox2d.collision.AABB; 17 | import org.jbox2d.common.Vec2; 18 | import org.jbox2d.dynamics.Body; 19 | import org.jbox2d.dynamics.BodyDef; 20 | import org.jbox2d.dynamics.BodyType; 21 | import org.jbox2d.dynamics.Fixture; 22 | import org.jbox2d.dynamics.World; 23 | import org.jbox2d.dynamics.joints.MouseJoint; 24 | import org.jbox2d.dynamics.joints.MouseJointDef; 25 | 26 | import com.thomasdiewald.liquidfun.java.DwViewportTransform; 27 | 28 | import processing.core.PConstants; 29 | import processing.event.KeyEvent; 30 | import processing.event.MouseEvent; 31 | 32 | 33 | /** 34 | * 35 | * @author Thomas Diewald 36 | * 37 | */ 38 | public class DwMouseDragBodies implements DwInteractionEvent, QueryCallback{ 39 | 40 | public World world; 41 | public DwViewportTransform vptransform; 42 | 43 | public boolean active = false; 44 | public AABB aabb = new AABB(); 45 | public Vec2 point = new Vec2(); 46 | public Fixture fixture = null; 47 | public MouseJoint mouse_joint; 48 | 49 | public final Vec2 mouse = new Vec2(); 50 | public float mult_dragforce = 1000000f; 51 | public boolean enable_static_drag = false; 52 | 53 | public int button = PConstants.LEFT; 54 | // public int button = PConstants.CENTER; 55 | // public int button = PConstants.RIGHT; 56 | 57 | public DwMouseDragBodies(World world, DwViewportTransform vptransform){ 58 | this.world = world; 59 | this.vptransform = vptransform; 60 | } 61 | 62 | // public boolean query(Vec2 world_xy){ 63 | // fixture = null; 64 | // point.set(world_xy); 65 | // aabb.lowerBound.set(point.x - 0.001f, point.y - 0.001f); 66 | // aabb.upperBound.set(point.x + 0.001f, point.y + 0.001f); 67 | // world.queryAABB(this, aabb); 68 | // return fixture != null; 69 | // } 70 | 71 | public boolean query(float screen_x, float screen_y){ 72 | vptransform.getScreen2box(screen_x, screen_y, mouse); 73 | fixture = null; 74 | point.set(mouse); 75 | aabb.lowerBound.set(point.x - 0.001f, point.y - 0.001f); 76 | aabb.upperBound.set(point.x + 0.001f, point.y + 0.001f); 77 | world.queryAABB(this, aabb); 78 | return fixture != null; 79 | } 80 | 81 | 82 | public void press(float screen_x, float screen_y) { 83 | if (query(screen_x, screen_y)) { 84 | Body body = fixture.getBody(); 85 | MouseJointDef def = new MouseJointDef(); 86 | def.bodyA = world.createBody(new BodyDef()); 87 | def.bodyB = fixture.getBody(); 88 | def.collideConnected = true; 89 | def.target.set(point); 90 | def.maxForce = mult_dragforce * body.getMass(); 91 | mouse_joint = (MouseJoint) world.createJoint(def); 92 | body.setAwake(true); 93 | } 94 | active = (mouse_joint != null); 95 | } 96 | 97 | 98 | public void update(float screen_x, float screen_y) { 99 | if (active) { 100 | vptransform.getScreen2box(screen_x, screen_y, mouse); 101 | mouse_joint.setTarget(mouse); 102 | } 103 | } 104 | 105 | 106 | public void release(float screen_x, float screen_y) { 107 | if (active) { 108 | if(body_type_cpy != null){ 109 | fixture.getBody().setType(body_type_cpy); 110 | body_type_cpy = null; 111 | } 112 | fixture = null; 113 | world.destroyJoint(mouse_joint); 114 | mouse_joint = null; 115 | } 116 | active = false; 117 | } 118 | 119 | 120 | 121 | public boolean is_enabled = true; 122 | 123 | @Override 124 | public void enable(boolean enable) { 125 | is_enabled = enable; 126 | } 127 | 128 | @Override 129 | public boolean isEnabled() { 130 | return is_enabled; 131 | } 132 | 133 | 134 | 135 | @Override 136 | public boolean isActive(){ 137 | return active; 138 | } 139 | 140 | @Override 141 | public void setMouseButton(int button){ 142 | this.button = button; 143 | } 144 | 145 | @Override 146 | public int getMouseButton(){ 147 | return button; 148 | } 149 | 150 | public BodyType body_type_cpy = null; 151 | 152 | @Override 153 | public boolean reportFixture(Fixture argFixture) { 154 | Body body = argFixture.getBody(); 155 | 156 | // static bodies can be moved too, but need to set to dynamic for the 157 | // mouse-joint to work. 158 | BodyType type = body.getType(); 159 | if (BodyType.DYNAMIC == type || enable_static_drag) { 160 | if (argFixture.testPoint(point)) { 161 | body_type_cpy = type; 162 | fixture = argFixture; 163 | body.setType(BodyType.DYNAMIC); 164 | return false; 165 | } 166 | } 167 | return true; 168 | } 169 | 170 | 171 | int mouseX_off = 0; 172 | int mouseY_off = 0; 173 | int mouseX; 174 | int mouseY; 175 | 176 | @Override 177 | public void mouseEvent(MouseEvent event){ 178 | if(!is_enabled){ 179 | return; 180 | } 181 | 182 | mouseX = mouseX_off + event.getX(); 183 | mouseY = mouseY_off + event.getY(); 184 | if(event.getButton() == this.button){ 185 | switch(event.getAction()){ 186 | case MouseEvent.PRESS: press (mouseX, mouseY); break; 187 | case MouseEvent.RELEASE: release(mouseX, mouseY); break; 188 | } 189 | } 190 | } 191 | 192 | public int key_combi = 0; 193 | public boolean key_combi_active = true; 194 | public boolean key_combi_enabled = true; 195 | 196 | @Override 197 | public void keyEvent(KeyEvent event){ 198 | switch(event.getAction()){ 199 | case KeyEvent.PRESS: 200 | key_combi_active = false; 201 | break; 202 | case KeyEvent.RELEASE: 203 | key_combi_active = true; 204 | break; 205 | } 206 | } 207 | 208 | @Override 209 | public void updateEvent(){ 210 | update(mouseX, mouseY); 211 | } 212 | 213 | @Override 214 | public void setMouseOffset(int mouseX_off, int mouseY_off){ 215 | this.mouseX_off = mouseX_off; 216 | this.mouseY_off = mouseY_off; 217 | } 218 | 219 | 220 | 221 | } 222 | 223 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/interaction/DwMouseDragParticles.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.interaction; 14 | 15 | import org.jbox2d.callbacks.ParticleQueryCallback; 16 | import org.jbox2d.collision.AABB; 17 | import org.jbox2d.collision.shapes.CircleShape; 18 | import org.jbox2d.common.Transform; 19 | import org.jbox2d.common.Vec2; 20 | import org.jbox2d.dynamics.World; 21 | 22 | import com.thomasdiewald.liquidfun.java.DwViewportTransform; 23 | 24 | import processing.core.PConstants; 25 | import processing.event.KeyEvent; 26 | import processing.event.MouseEvent; 27 | 28 | 29 | /** 30 | * 31 | * @author Thomas Diewald 32 | * 33 | */ 34 | public class DwMouseDragParticles implements DwInteractionEvent, ParticleQueryCallback { 35 | 36 | public World world; 37 | public DwViewportTransform transform; 38 | 39 | protected DwMouseDragBodies body_dragger; 40 | 41 | public boolean active = false; 42 | 43 | 44 | public int button = PConstants.LEFT; 45 | //public int button = PConstants.CENTER; 46 | //public int button = PConstants.RIGHT; 47 | 48 | 49 | public Transform xf = new Transform(); 50 | public AABB aabb = new AABB(); 51 | public CircleShape query_shape = new CircleShape(); 52 | 53 | public float dt = 1 / 60f; 54 | public Vec2 pos = new Vec2(0, 0); 55 | public Vec2 vel = new Vec2(0, 0); 56 | public Vec2 acc = new Vec2(0, 0); 57 | 58 | public final Vec2 mouse = new Vec2(); 59 | 60 | public DwMouseDragParticles(World world, DwViewportTransform transform){ 61 | this.world = world; 62 | this.transform = transform; 63 | xf.setIdentity(); 64 | query_shape.m_radius = 2; 65 | 66 | body_dragger = new DwMouseDragBodies(world, transform); 67 | } 68 | 69 | 70 | public void press(float screen_x, float screen_y) { 71 | // bodies have priority 72 | if(body_dragger.query(screen_x, screen_y)){ 73 | return; 74 | } 75 | 76 | transform.getScreen2box(screen_x, screen_y, mouse); 77 | this.vel.set(0, 0); 78 | this.pos.set(mouse); 79 | query_shape.m_p.set(pos); 80 | query_shape.computeAABB(aabb, xf, 0); 81 | world.queryAABB(this, aabb); 82 | active = true; 83 | } 84 | 85 | 86 | public void update(float screen_x, float screen_y) { 87 | if (active) { 88 | transform.getScreen2box(screen_x, screen_y, mouse); 89 | float delay = 0.1f; 90 | acc.x = 2f / delay * ((mouse.x - pos.x) / delay - vel.x); 91 | acc.y = 2f / delay * ((mouse.y - pos.y) / delay - vel.y); 92 | vel.x += dt * acc.x; 93 | vel.y += dt * acc.y; 94 | pos.x += dt * vel.x; 95 | pos.y += dt * vel.y; 96 | query_shape.m_p.set(pos); 97 | query_shape.computeAABB(aabb, xf, 0); 98 | world.queryAABB(this, aabb); 99 | } 100 | } 101 | 102 | public void release(float screen_x, float screen_y) { 103 | active = false; 104 | } 105 | 106 | 107 | public boolean is_enabled = true; 108 | 109 | @Override 110 | public void enable(boolean enable) { 111 | is_enabled = enable; 112 | } 113 | 114 | @Override 115 | public boolean isEnabled() { 116 | return is_enabled; 117 | } 118 | 119 | @Override 120 | public boolean isActive(){ 121 | return active; 122 | } 123 | 124 | @Override 125 | public void setMouseButton(int button){ 126 | this.button = button; 127 | } 128 | 129 | @Override 130 | public int getMouseButton(){ 131 | return button; 132 | } 133 | 134 | @Override 135 | public boolean reportParticle(int index) { 136 | Vec2 particle_pos = world.getParticlePositionBuffer()[index]; 137 | if (query_shape.testPoint(xf, particle_pos)) { 138 | Vec2 particle_vel = world.getParticleVelocityBuffer()[index]; 139 | particle_vel.set(vel); 140 | } 141 | return true; 142 | } 143 | 144 | 145 | 146 | 147 | 148 | 149 | int mouseX; 150 | int mouseY; 151 | int mouseX_off = 0; 152 | int mouseY_off = 0; 153 | 154 | @Override 155 | public void mouseEvent(MouseEvent event){ 156 | if(!is_enabled){ 157 | return; 158 | } 159 | mouseX = mouseX_off + event.getX(); 160 | mouseY = mouseY_off + event.getY(); 161 | if(event.getButton() == this.button){ 162 | switch(event.getAction()){ 163 | case MouseEvent.PRESS: 164 | if(key_combi_enabled == key_combi_active){ 165 | press(mouseX, mouseY); 166 | } 167 | break; 168 | case MouseEvent.RELEASE: 169 | release(mouseX, mouseY); 170 | break; 171 | } 172 | } 173 | } 174 | 175 | public int key_combi = 0; 176 | public boolean key_combi_active = true; 177 | public boolean key_combi_enabled = true; 178 | 179 | @Override 180 | public void keyEvent(KeyEvent event){ 181 | switch(event.getAction()){ 182 | case KeyEvent.PRESS: 183 | key_combi_active = false; 184 | break; 185 | case KeyEvent.RELEASE: 186 | key_combi_active = true; 187 | break; 188 | } 189 | } 190 | 191 | @Override 192 | public void updateEvent(){ 193 | update(mouseX, mouseY); 194 | } 195 | 196 | 197 | @Override 198 | public void setMouseOffset(int mouseX_off, int mouseY_off){ 199 | this.mouseX_off = mouseX_off; 200 | this.mouseY_off = mouseY_off; 201 | } 202 | 203 | } 204 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/interaction/DwMouseShootBullet.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.interaction; 14 | 15 | 16 | import java.util.Stack; 17 | 18 | import org.jbox2d.collision.shapes.CircleShape; 19 | import org.jbox2d.common.Vec2; 20 | import org.jbox2d.dynamics.Body; 21 | import org.jbox2d.dynamics.BodyDef; 22 | import org.jbox2d.dynamics.BodyType; 23 | import org.jbox2d.dynamics.FixtureDef; 24 | import org.jbox2d.dynamics.World; 25 | 26 | import com.thomasdiewald.liquidfun.java.DwViewportTransform; 27 | 28 | import processing.core.PConstants; 29 | import processing.core.PGraphics; 30 | import processing.event.KeyEvent; 31 | import processing.event.MouseEvent; 32 | 33 | 34 | 35 | /** 36 | * 37 | * @author Thomas Diewald 38 | * 39 | */ 40 | public class DwMouseShootBullet implements DwInteractionEvent { 41 | 42 | public World world; 43 | public DwViewportTransform transform; 44 | 45 | public boolean is_active = false; 46 | public int button = PConstants.LEFT; 47 | 48 | public Vec2 bomb_spawn_start = new Vec2(); 49 | public Vec2 bomb_spawn_end = new Vec2(); 50 | public Vec2 bomb_velocity = new Vec2(); 51 | public float velocity_mult = 2f; 52 | public float density_mult = 1f; 53 | 54 | 55 | public BodyDef body_def = new BodyDef(); 56 | public CircleShape cirlce_shape = new CircleShape(); 57 | public FixtureDef fixture_def = new FixtureDef(); 58 | 59 | protected DwMouseDragBodies body_dragger; 60 | 61 | protected Stack bullets = new Stack<>(); 62 | 63 | 64 | public DwMouseShootBullet(World world, DwViewportTransform transform){ 65 | this.world = world; 66 | this.transform = transform; 67 | 68 | // bullet specific settings 69 | cirlce_shape.m_radius = 0.3f; 70 | 71 | fixture_def.shape = cirlce_shape; 72 | fixture_def.density = 200f; 73 | fixture_def.restitution = 0.1f; 74 | 75 | body_def.type = BodyType.DYNAMIC; 76 | body_def.bullet = true; 77 | 78 | body_dragger = new DwMouseDragBodies(world, transform); 79 | } 80 | 81 | public void beginSpawn(float screen_x, float screen_y){ 82 | // bodies have priority 83 | if(body_dragger.query(screen_x, screen_y)){ 84 | return; 85 | } 86 | 87 | transform.getScreen2box(screen_x, screen_y, bomb_spawn_start); 88 | bomb_spawn_end.set(bomb_spawn_start); 89 | is_active = true; 90 | } 91 | 92 | public void updateSpawn(float screen_x, float screen_y){ 93 | if(is_active){ 94 | transform.getScreen2box(screen_x, screen_y, bomb_spawn_end); 95 | } 96 | } 97 | 98 | public void endSpawn(float screen_x, float screen_y){ 99 | if(is_active){ 100 | transform.getScreen2box(screen_x, screen_y, bomb_spawn_end); 101 | bomb_velocity = bomb_spawn_end.sub(bomb_spawn_start); 102 | 103 | // velocity and density 104 | float vel_len = 1f + bomb_velocity.length(); 105 | 106 | float mult = (1f + vel_len * vel_len) * velocity_mult; 107 | 108 | fixture_def.density = (1 + vel_len * vel_len) * density_mult; 109 | 110 | bomb_velocity.normalize(); 111 | bomb_velocity.mulLocal(mult); 112 | 113 | shoot(bomb_spawn_start, bomb_velocity); 114 | is_active = false; 115 | } 116 | } 117 | 118 | public void drawSpawnTrack(PGraphics pg){ 119 | if(is_active){ 120 | pg.strokeWeight(1f / transform.screen_scale); 121 | pg.stroke(200,128,128, 128); 122 | pg.line(bomb_spawn_start.x, bomb_spawn_start.y, bomb_spawn_end.x, bomb_spawn_end.y); 123 | } 124 | } 125 | 126 | public void shoot(Vec2 position, Vec2 velocity) { 127 | body_def.position.set(position); 128 | Body bullet = world.createBody(body_def); 129 | bullet.setLinearVelocity(velocity); 130 | bullet.createFixture(fixture_def); 131 | 132 | bullets.push(bullet); 133 | } 134 | 135 | 136 | public Body popBullet(){ 137 | if(bullets.isEmpty()){ 138 | return null; 139 | } 140 | return bullets.pop(); 141 | } 142 | 143 | 144 | public boolean is_enabled = true; 145 | 146 | @Override 147 | public void enable(boolean enable) { 148 | is_enabled = enable; 149 | } 150 | 151 | @Override 152 | public boolean isEnabled() { 153 | return is_enabled; 154 | } 155 | 156 | @Override 157 | public boolean isActive() { 158 | return is_active; 159 | } 160 | 161 | @Override 162 | public void setMouseButton(int button) { 163 | this.button = button; 164 | } 165 | 166 | @Override 167 | public int getMouseButton() { 168 | return button; 169 | } 170 | 171 | 172 | 173 | int mouseX; 174 | int mouseY; 175 | int mouseX_off = 0; 176 | int mouseY_off = 0; 177 | 178 | @Override 179 | public void mouseEvent(MouseEvent event){ 180 | if(!is_enabled){ 181 | return; 182 | } 183 | mouseX = mouseX_off + event.getX(); 184 | mouseY = mouseY_off + event.getY(); 185 | if(event.getButton() == this.button){ 186 | switch(event.getAction()){ 187 | case MouseEvent.PRESS: 188 | if(key_combi_enabled == key_combi_active){ 189 | beginSpawn(mouseX, mouseY); 190 | } 191 | break; 192 | case MouseEvent.RELEASE: 193 | endSpawn(mouseX, mouseY); 194 | break; 195 | } 196 | } 197 | } 198 | 199 | public int key_combi = KeyEvent.SHIFT; 200 | public boolean key_combi_active = false; 201 | public boolean key_combi_enabled = true; 202 | 203 | @Override 204 | public void keyEvent(KeyEvent event){ 205 | switch(event.getAction()){ 206 | case KeyEvent.PRESS: 207 | key_combi_active = ((key_combi ^ event.getModifiers()) == 0); 208 | break; 209 | case KeyEvent.RELEASE: 210 | key_combi_active = false; 211 | break; 212 | } 213 | 214 | } 215 | 216 | 217 | @Override 218 | public void updateEvent() { 219 | updateSpawn(mouseX, mouseY); 220 | } 221 | 222 | @Override 223 | public void setMouseOffset(int mouseX_off, int mouseY_off){ 224 | this.mouseX_off = mouseX_off; 225 | this.mouseY_off = mouseY_off; 226 | } 227 | 228 | 229 | } 230 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/interaction/DwParticleDestroyer.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.interaction; 14 | 15 | import org.jbox2d.callbacks.ParticleDestructionListener; 16 | import org.jbox2d.collision.shapes.CircleShape; 17 | import org.jbox2d.collision.shapes.PolygonShape; 18 | import org.jbox2d.collision.shapes.Shape; 19 | import org.jbox2d.collision.shapes.ShapeType; 20 | import org.jbox2d.common.Transform; 21 | import org.jbox2d.dynamics.World; 22 | import org.jbox2d.particle.ParticleGroup; 23 | 24 | import com.thomasdiewald.liquidfun.java.DwViewportTransform; 25 | 26 | import processing.core.PConstants; 27 | import processing.event.KeyEvent; 28 | import processing.event.MouseEvent; 29 | 30 | 31 | /** 32 | * 33 | * Class that handles mouse-interaction with Box2D/LiquidFun Particles.
34 | * 35 | * 36 | * @author Thomas Diewald 37 | * 38 | */ 39 | public class DwParticleDestroyer implements DwInteractionEvent, ParticleDestructionListener{ 40 | 41 | public World world; 42 | public DwViewportTransform transform; 43 | 44 | public boolean enable_callback = false; 45 | 46 | public Transform shape_transform = new Transform(); 47 | public Shape shape; 48 | 49 | public DwParticleDestroyer(World world, DwViewportTransform vptransform){ 50 | this.world = world; 51 | this.transform = vptransform; 52 | this.shape_transform.setIdentity(); 53 | 54 | setCircleShape(30); 55 | // setBoxShape(60, 60); 56 | } 57 | 58 | 59 | /** 60 | * Circle as a brush 61 | */ 62 | public void setCircleShape(float screen_radius){ 63 | CircleShape shape = new CircleShape(); 64 | shape.m_radius = screen_radius / transform.screen_scale; 65 | shape.m_p.setZero(); 66 | setShape(shape); 67 | } 68 | 69 | /** 70 | * Rectangle as a brush 71 | */ 72 | public void setBoxShape(float screen_box_w, float screen_box_h){ 73 | float bw = screen_box_w / transform.screen_scale; 74 | float bh = screen_box_h / transform.screen_scale; 75 | System.out.println(bw); 76 | PolygonShape shape = new PolygonShape(); 77 | shape.setAsBox(bw * 0.5f, bh * 0.5f); 78 | setShape(shape); 79 | } 80 | 81 | 82 | /** 83 | * Any Shape given as a brush. Use (0,0) as center. 84 | * only ShapeType.CIRCLE and ShapeType.POLYGON can be used 85 | * 86 | */ 87 | public void setShape(Shape shape){ 88 | boolean is_circle = ShapeType.CIRCLE == shape.getType(); 89 | boolean is_polygon = ShapeType.POLYGON == shape.getType(); 90 | 91 | if(is_circle || is_polygon){ 92 | this.shape = shape; 93 | } 94 | } 95 | 96 | 97 | 98 | // protected void applyShapeTransform(){ 99 | // if(shape.getType() == ShapeType.CIRCLE){ 100 | // CircleShape shp = (CircleShape) shape; 101 | // Transform.mulToOut(shape_transform, shp.m_p, shp.m_p); 102 | // } 103 | // else if(shape.getType() == ShapeType.POLYGON){ 104 | // PolygonShape shp = (PolygonShape) shape; 105 | // for(int i = 0; i < shp.m_count; i++){ 106 | // Transform.mulToOut(shape_transform, shp.m_vertices[i], shp.m_vertices[i]); 107 | // } 108 | // } 109 | // } 110 | // 111 | // protected void revertShapeTransform(){ 112 | // if(shape.getType() == ShapeType.CIRCLE){ 113 | // CircleShape shp = (CircleShape) shape; 114 | // Transform.mulTransToOut(shape_transform, shp.m_p, shp.m_p); 115 | // } 116 | // else if(shape.getType() == ShapeType.POLYGON){ 117 | // PolygonShape shp = (PolygonShape) shape; 118 | // for(int i = 0; i < shp.m_count; i++){ 119 | // Transform.mulTransToOut(shape_transform, shp.m_vertices[i], shp.m_vertices[i]); 120 | // } 121 | // } 122 | // } 123 | 124 | 125 | public void begin(float screen_x, float screen_y){ 126 | transform.getScreen2box(screen_x, screen_y, shape_transform.p); 127 | // applyShapeTransform(); 128 | destroyParticles(shape); 129 | // revertShapeTransform(); 130 | shape_transform.setIdentity(); 131 | is_active = true; 132 | } 133 | 134 | public void update(float screen_x, float screen_y){ 135 | if(is_active){ 136 | transform.getScreen2box(screen_x, screen_y, shape_transform.p); 137 | // applyShapeTransform(); 138 | destroyParticles(shape); 139 | // revertShapeTransform(); 140 | shape_transform.setIdentity(); 141 | } 142 | } 143 | 144 | public void end(float screen_x, float screen_y){ 145 | is_active = false; 146 | } 147 | 148 | 149 | public void destroyParticles(Shape shape){ 150 | // push PDL 151 | ParticleDestructionListener pdl = world.getParticleDestructionListener(); 152 | if(enable_callback){ 153 | world.setParticleDestructionListener(this); 154 | } 155 | // destroy particles 156 | world.destroyParticlesInShape(shape, shape_transform, enable_callback); 157 | // pop PDL 158 | world.setParticleDestructionListener(pdl); 159 | } 160 | 161 | 162 | public boolean is_enabled = true; 163 | 164 | @Override 165 | public void enable(boolean enable) { 166 | is_enabled = enable; 167 | } 168 | 169 | @Override 170 | public boolean isEnabled() { 171 | return is_enabled; 172 | } 173 | 174 | @Override 175 | public boolean isActive() { 176 | return is_active; 177 | } 178 | 179 | @Override 180 | public void setMouseButton(int button) { 181 | this.button = button; 182 | } 183 | 184 | @Override 185 | public int getMouseButton() { 186 | return button; 187 | } 188 | 189 | 190 | public int button = PConstants.RIGHT; 191 | public boolean is_active = false; 192 | 193 | int mouseX; 194 | int mouseY; 195 | int mouseX_off = 0; 196 | int mouseY_off = 0; 197 | 198 | @Override 199 | public void mouseEvent(MouseEvent event){ 200 | if(!is_enabled){ 201 | return; 202 | } 203 | mouseX = mouseX_off + event.getX(); 204 | mouseY = mouseY_off + event.getY(); 205 | if(event.getButton() == this.button){ 206 | switch(event.getAction()){ 207 | case MouseEvent.PRESS: 208 | case MouseEvent.DRAG: 209 | if(key_combi_enabled == key_combi_active){ 210 | begin(mouseX, mouseY); 211 | } 212 | break; 213 | case MouseEvent.RELEASE: 214 | end(mouseX, mouseY); 215 | break; 216 | } 217 | } 218 | } 219 | 220 | public int key_combi = 0; 221 | public boolean key_combi_active = false; 222 | public boolean key_combi_enabled = false; 223 | 224 | @Override 225 | public void keyEvent(KeyEvent event){ 226 | switch(event.getAction()){ 227 | case KeyEvent.PRESS: 228 | key_combi_active = ((key_combi ^ event.getModifiers()) == 0); 229 | break; 230 | case KeyEvent.RELEASE: 231 | key_combi_active = false; 232 | break; 233 | } 234 | 235 | } 236 | 237 | 238 | @Override 239 | public void updateEvent() { 240 | update(mouseX, mouseY); 241 | } 242 | 243 | 244 | @Override 245 | public void setMouseOffset(int mouseX_off, int mouseY_off){ 246 | this.mouseX_off = mouseX_off; 247 | this.mouseY_off = mouseY_off; 248 | } 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | @Override 257 | public void sayGoodbye(ParticleGroup group) { 258 | } 259 | 260 | @Override 261 | public void sayGoodbye(int index) { 262 | } 263 | 264 | 265 | 266 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/interaction/DwParticleSpawn.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.interaction; 14 | 15 | import org.jbox2d.collision.shapes.CircleShape; 16 | import org.jbox2d.collision.shapes.PolygonShape; 17 | import org.jbox2d.collision.shapes.Shape; 18 | import org.jbox2d.collision.shapes.ShapeType; 19 | import org.jbox2d.common.Color3f; 20 | import org.jbox2d.common.Transform; 21 | import org.jbox2d.dynamics.World; 22 | import org.jbox2d.particle.ParticleGroup; 23 | import org.jbox2d.particle.ParticleGroupDef; 24 | import org.jbox2d.particle.ParticleType; 25 | 26 | import com.thomasdiewald.liquidfun.java.DwViewportTransform; 27 | 28 | import processing.core.PConstants; 29 | import processing.event.KeyEvent; 30 | import processing.event.MouseEvent; 31 | 32 | 33 | /** 34 | * 35 | * Class that handles mouse-interaction with Box2D/LiquidFun Particles.
36 | * 37 | * 38 | * @author Thomas Diewald 39 | * 40 | */ 41 | public class DwParticleSpawn implements DwInteractionEvent{ 42 | 43 | public World world; 44 | public DwViewportTransform transform; 45 | 46 | public boolean is_active = false; 47 | public int button = PConstants.CENTER; 48 | 49 | public DwParticleDestroyer pdestroyer; 50 | public ParticleGroupDef group_def; 51 | 52 | public ParticleGroup group_new; 53 | public ParticleGroup group_old; 54 | 55 | public Transform shape_transform = new Transform(); 56 | 57 | public int spawn_count = 0; // number of new created particles 58 | public int spawn_begin = 0; // idx of first new particle 59 | public int spawn_end = 0; // spawn_begin + spawn_count 60 | 61 | public boolean join_groups = true; 62 | public boolean destroy_inplace_before_spawn = true; 63 | 64 | 65 | public DwParticleSpawn(World world, DwViewportTransform transform){ 66 | this.world = world; 67 | this.transform = transform; 68 | this.pdestroyer = new DwParticleDestroyer(world, transform); 69 | this.group_def = new ParticleGroupDef(); 70 | 71 | this.group_def.setColor(new Color3f(1,0.35f, 0.15f)); 72 | this.group_def.flags = ParticleType.b2_waterParticle | ParticleType.b2_viscousParticle; 73 | this.group_def.groupFlags = 0; 74 | 75 | setCircleShape(30); 76 | } 77 | 78 | 79 | /** 80 | * Circle as a brush 81 | */ 82 | public void setCircleShape(float screen_radius){ 83 | CircleShape shape = new CircleShape(); 84 | shape.m_radius = screen_radius / transform.screen_scale; 85 | shape.m_p.setZero(); 86 | setShape(shape); 87 | } 88 | 89 | /** 90 | * Rectangle as a brush 91 | */ 92 | public void setBoxShape(float screen_box_w, float screen_box_h){ 93 | float bw = screen_box_w / transform.screen_scale; 94 | float bh = screen_box_h / transform.screen_scale; 95 | PolygonShape shape = new PolygonShape(); 96 | shape.setAsBox(bw * 0.5f, bh * 0.5f); 97 | setShape(shape); 98 | } 99 | 100 | /** 101 | * Any Shape given as a brush. Use (0,0) as center. 102 | * only ShapeType.CIRCLE and ShapeType.POLYGON can be used 103 | * 104 | */ 105 | public void setShape(Shape shape){ 106 | boolean is_circle = ShapeType.CIRCLE == shape.getType(); 107 | boolean is_polygon = ShapeType.POLYGON == shape.getType(); 108 | 109 | if(is_circle || is_polygon){ 110 | group_def.shape = shape; 111 | } 112 | } 113 | 114 | 115 | 116 | protected void applyShapeTransform(){ 117 | if(group_def.shape.getType() == ShapeType.CIRCLE){ 118 | CircleShape shp = (CircleShape) group_def.shape; 119 | Transform.mulToOut(shape_transform, shp.m_p, shp.m_p); 120 | } 121 | else if(group_def.shape.getType() == ShapeType.POLYGON){ 122 | PolygonShape shp = (PolygonShape) group_def.shape; 123 | 124 | for(int i = 0; i < shp.m_count; i++){ 125 | Transform.mulToOut(shape_transform, shp.m_vertices[i], shp.m_vertices[i]); 126 | } 127 | } 128 | } 129 | 130 | protected void revertShapeTransform(){ 131 | if(group_def.shape.getType() == ShapeType.CIRCLE){ 132 | CircleShape shp = (CircleShape) group_def.shape; 133 | Transform.mulTransToOut(shape_transform, shp.m_p, shp.m_p); 134 | } 135 | else if(group_def.shape.getType() == ShapeType.POLYGON){ 136 | PolygonShape shp = (PolygonShape) group_def.shape; 137 | for(int i = 0; i < shp.m_count; i++){ 138 | Transform.mulTransToOut(shape_transform, shp.m_vertices[i], shp.m_vertices[i]); 139 | } 140 | } 141 | } 142 | 143 | 144 | public ParticleGroup spawn(float screen_x, float screen_y){ 145 | transform.getScreen2box(screen_x, screen_y, shape_transform.p); 146 | 147 | applyShapeTransform(); 148 | 149 | // destroy particles in group_def.shape 150 | if(destroy_inplace_before_spawn){ 151 | pdestroyer.destroyParticles(group_def.shape); 152 | } 153 | 154 | // spawn particles in group_def.shape 155 | group_old = group_new; 156 | group_new = world.createParticleGroup(group_def); 157 | 158 | revertShapeTransform(); 159 | 160 | // result stats 161 | spawn_count = group_new.getParticleCount(); 162 | spawn_begin = group_new.getBufferIndex(); 163 | spawn_end = spawn_begin + spawn_count; 164 | 165 | // join groups if its a good idea 166 | if(join_groups){ 167 | if (group_old != null && group_new.getGroupFlags() == group_old.getGroupFlags()) { 168 | world.joinParticleGroups(group_old, group_new); 169 | group_new = group_old; 170 | } 171 | } 172 | is_active = true; 173 | return group_new; 174 | } 175 | 176 | 177 | public void end(float screen_x, float screen_y){ 178 | group_new = null; 179 | group_old = null; 180 | is_active = false; 181 | } 182 | 183 | 184 | public boolean is_enabled = true; 185 | 186 | @Override 187 | public void enable(boolean enable) { 188 | is_enabled = enable; 189 | } 190 | 191 | @Override 192 | public boolean isEnabled() { 193 | return is_enabled; 194 | } 195 | 196 | @Override 197 | public boolean isActive() { 198 | return is_active; 199 | } 200 | 201 | @Override 202 | public void setMouseButton(int button) { 203 | this.button = button; 204 | } 205 | 206 | @Override 207 | public int getMouseButton() { 208 | // TODO Auto-generated method stub 209 | return button; 210 | } 211 | 212 | 213 | int mouseX; 214 | int mouseY; 215 | int mouseX_off = 0; 216 | int mouseY_off = 0; 217 | 218 | @Override 219 | public void mouseEvent(MouseEvent event){ 220 | if(!is_enabled){ 221 | return; 222 | } 223 | mouseX = mouseX_off + event.getX(); 224 | mouseY = mouseY_off + event.getY(); 225 | if(event.getButton() == this.button){ 226 | switch(event.getAction()){ 227 | case MouseEvent.PRESS: 228 | case MouseEvent.DRAG: 229 | if(key_combi_enabled == key_combi_active){ 230 | spawn(mouseX, mouseY); 231 | } 232 | break; 233 | case MouseEvent.RELEASE: 234 | end(mouseX, mouseY); 235 | break; 236 | } 237 | } 238 | } 239 | 240 | public int key_combi = 0; 241 | public boolean key_combi_active = false; 242 | public boolean key_combi_enabled = false; 243 | 244 | @Override 245 | public void keyEvent(KeyEvent event){ 246 | switch(event.getAction()){ 247 | case KeyEvent.PRESS: 248 | key_combi_active = ((key_combi ^ event.getModifiers()) == 0); 249 | break; 250 | case KeyEvent.RELEASE: 251 | key_combi_active = false; 252 | break; 253 | } 254 | 255 | } 256 | 257 | 258 | @Override 259 | public void updateEvent() { 260 | } 261 | 262 | @Override 263 | public void setMouseOffset(int mouseX_off, int mouseY_off){ 264 | this.mouseX_off = mouseX_off; 265 | this.mouseY_off = mouseY_off; 266 | } 267 | 268 | 269 | 270 | 271 | 272 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/render/DwBody.java: -------------------------------------------------------------------------------- 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 | 15 | 16 | package com.thomasdiewald.liquidfun.java.render; 17 | 18 | import java.util.ArrayList; 19 | import org.jbox2d.dynamics.Body; 20 | import org.jbox2d.dynamics.Fixture; 21 | 22 | import com.thomasdiewald.liquidfun.java.DwWorld; 23 | 24 | import processing.core.PConstants; 25 | import processing.core.PShape; 26 | 27 | 28 | 29 | /** 30 | * 31 | * Hierarchical PShape SceneGraph, built from all Box2D-World Body/Fixture shapes.
32 | * 33 | * @author Thomas Diewald 34 | * 35 | */ 36 | public class DwBody{ 37 | 38 | public DwBodyGroup parent; 39 | 40 | public Body body; 41 | public PShape shape; 42 | 43 | public ArrayList children = new ArrayList(); 44 | 45 | public ShapeStyle style = new ShapeStyle(); 46 | 47 | // use m_userData here, instead of body.m_userData 48 | public Object m_userData = null; 49 | 50 | public DwBody(DwBodyGroup parent, Body body){ 51 | this.parent = parent; 52 | this.body = body; 53 | 54 | // create PShape 55 | this.shape = parent.papplet.createShape(PConstants.GROUP); 56 | // link PShapes 57 | parent.shape.addChild(shape); 58 | 59 | body.setUserData(this); 60 | 61 | // create children 62 | for (Fixture fixture = body.getFixtureList(); fixture != null; fixture = fixture.getNext()) { 63 | add(fixture); 64 | } 65 | } 66 | 67 | 68 | public DwFixture add(Fixture fixture){ 69 | DwFixture dwfixture = DwWorld.getShape(fixture); 70 | if(dwfixture != null){ 71 | dwfixture.release(); 72 | } 73 | dwfixture = new DwFixture(this, fixture); 74 | children.add(dwfixture); 75 | return dwfixture; 76 | } 77 | 78 | 79 | 80 | public void release(){ 81 | for(int i = children.size()-1; i>= 0; i--){ 82 | children.get(i).release(); 83 | } 84 | // for(DwFixture child : children){ 85 | // child.release(); 86 | // } 87 | children.clear(); // should already be cleared 88 | children = null; 89 | 90 | int idx = parent.shape.getChildIndex(shape); 91 | parent.shape.removeChild(idx); 92 | 93 | parent.childrenB.remove(this); 94 | 95 | shape = null; 96 | parent = null; 97 | body.setUserData(null); 98 | body = null; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/render/DwFixture.java: -------------------------------------------------------------------------------- 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 | 15 | 16 | package com.thomasdiewald.liquidfun.java.render; 17 | 18 | import org.jbox2d.collision.shapes.ChainShape; 19 | import org.jbox2d.collision.shapes.CircleShape; 20 | import org.jbox2d.collision.shapes.EdgeShape; 21 | import org.jbox2d.collision.shapes.PolygonShape; 22 | import org.jbox2d.collision.shapes.ShapeType; 23 | import org.jbox2d.common.Vec2; 24 | import org.jbox2d.dynamics.Fixture; 25 | import processing.core.PApplet; 26 | import processing.core.PConstants; 27 | import processing.core.PShape; 28 | 29 | 30 | 31 | /** 32 | * 33 | * Hierarchical PShape SceneGraph, built from all Box2D-World Body/Fixture shapes.
34 | * 35 | * 36 | * @author Thomas Diewald 37 | * 38 | */ 39 | public class DwFixture { 40 | 41 | public DwBody parent; 42 | 43 | public Fixture fixture; 44 | public PShape shape; 45 | 46 | // use m_userData here, instead of fixture.m_userData 47 | public Object m_userData = null; 48 | 49 | public DwFixture(DwBody parent, Fixture fixture){ 50 | this.parent = parent; 51 | this.fixture = fixture; 52 | 53 | createShape(); 54 | } 55 | 56 | 57 | protected void createShape(){ 58 | 59 | PApplet papplet = parent.parent.papplet; 60 | 61 | shape = null; 62 | 63 | final ShapeType type = fixture.getType(); 64 | 65 | if(ShapeType.POLYGON == type){ 66 | PolygonShape shp_polygon = (PolygonShape) fixture.getShape(); 67 | Vec2[] verts = shp_polygon.m_vertices; 68 | shape = papplet.createShape(); 69 | shape.beginShape(); 70 | for(int i = 0; i < shp_polygon.m_count; i++){ 71 | shape.vertex(verts[i].x, verts[i].y); 72 | } 73 | shape.endShape(PConstants.CLOSE); 74 | } 75 | else if(ShapeType.CIRCLE == type){ 76 | CircleShape shp_circle = (CircleShape) fixture.getShape(); 77 | float radius = shp_circle.m_radius; 78 | Vec2 vert = shp_circle.m_p; 79 | shape = papplet.createShape(PConstants.ELLIPSE, vert.x, vert.y, radius*2, radius*2); 80 | } 81 | else if(ShapeType.CHAIN == type){ 82 | ChainShape shp_chain = (ChainShape) fixture.getShape(); 83 | Vec2[] verts = shp_chain.m_vertices; 84 | shape = papplet.createShape(); 85 | shape.beginShape(); 86 | shape.noFill(); 87 | for(int i = 0; i < shp_chain.m_count; i++){ 88 | shape.vertex(verts[i].x, verts[i].y); 89 | } 90 | shape.endShape(PConstants.CLOSE); 91 | } 92 | else if(ShapeType.EDGE == type){ 93 | EdgeShape shp_edge = (EdgeShape) fixture.getShape(); 94 | Vec2 vert1 = shp_edge.m_vertex1; 95 | Vec2 vert2 = shp_edge.m_vertex2; 96 | shape = papplet.createShape(PConstants.LINE, vert1.x, vert1.y, vert2.x, vert2.y); 97 | } 98 | else { 99 | System.out.println("Error: unknown shapetype"); 100 | } 101 | 102 | 103 | if(shape != null){ 104 | parent.shape.addChild(shape); 105 | fixture.setUserData(this); 106 | } 107 | } 108 | 109 | 110 | public void replaceShape(PShape shape_new){ 111 | int idx = parent.shape.getChildIndex(shape); 112 | if(idx != -1){ 113 | parent.shape.removeChild(idx); 114 | } 115 | shape = shape_new; 116 | parent.shape.addChild(shape); 117 | } 118 | 119 | 120 | public void release(){ 121 | // remove PShape from parent shape-children 122 | int idx = parent.shape.getChildIndex(shape); 123 | parent.shape.removeChild(idx); 124 | 125 | // remove this from parent-children 126 | parent.children.remove(this); 127 | 128 | shape = null; 129 | parent = null; 130 | fixture.setUserData(null); 131 | fixture = null; 132 | } 133 | 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/render/DwJoint.java: -------------------------------------------------------------------------------- 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 | 15 | 16 | package com.thomasdiewald.liquidfun.java.render; 17 | 18 | import org.jbox2d.dynamics.joints.Joint; 19 | import org.jbox2d.dynamics.joints.JointType; 20 | 21 | import processing.core.PConstants; 22 | import processing.core.PShape; 23 | 24 | 25 | 26 | /** 27 | * 28 | * Hierarchical PShape SceneGraph, built from all Box2D-World Body/Fixture shapes.
29 | * 30 | * 31 | * @author Thomas Diewald 32 | * 33 | */ 34 | public class DwJoint{ 35 | 36 | public DwBodyGroup parent; 37 | 38 | public Joint joint; 39 | public PShape shape; 40 | 41 | // use m_userData here, instead of joint.m_userData 42 | public Object m_userData = null; 43 | 44 | 45 | public DwJoint(DwBodyGroup parent, Joint joint){ 46 | this.parent = parent; 47 | this.joint = joint; 48 | 49 | JointType type = joint.getType(); 50 | 51 | // create PShape 52 | // this.shape = parent.papplet.createShape(PConstants.LINE, 0, 0, 1, 0); 53 | // this.shape.setStrokeJoin(PConstants.ROUND); 54 | // this.shape.setStrokeCap(PConstants.ROUND); 55 | // shape = parent.papplet.createShape(); 56 | // shape.beginShape(PConstants.QUADS); 57 | // shape.fill(255); 58 | // shape.vertex(0,0); 59 | // shape.vertex(1,0); 60 | // shape.vertex(1,1); 61 | // shape.vertex(0,1); 62 | // shape.endShape(); 63 | 64 | 65 | if(type == JointType.PULLEY){ 66 | shape = parent.papplet.createShape(PConstants.GROUP); 67 | shape.addChild(parent.papplet.createShape(PConstants.LINE, 0, 0, 1, 0)); 68 | shape.addChild(parent.papplet.createShape(PConstants.LINE, 0, 0, 1, 0)); 69 | shape.addChild(parent.papplet.createShape(PConstants.LINE, 0, 0, 1, 0)); 70 | } else { 71 | shape = parent.papplet.createShape(PConstants.LINE, 0, 0, 1, 0); 72 | } 73 | 74 | 75 | 76 | // link PShapes 77 | parent.shape.addChild(shape); 78 | 79 | joint.setUserData(this); 80 | } 81 | 82 | 83 | public void replaceShape(PShape shape_new){ 84 | int idx = parent.shape.getChildIndex(shape); 85 | if(idx != -1){ 86 | parent.shape.removeChild(idx); 87 | } 88 | shape = shape_new; 89 | parent.shape.addChild(shape); 90 | } 91 | 92 | 93 | public void release(){ 94 | int idx = parent.shape.getChildIndex(shape); 95 | parent.shape.removeChild(idx); 96 | 97 | parent.childrenJ.remove(this); 98 | 99 | shape = null; 100 | parent = null; 101 | joint.setUserData(null); 102 | joint = null; 103 | } 104 | 105 | 106 | 107 | } 108 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/render/DwParticleRenderGroupCallback.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.render; 14 | 15 | import org.jbox2d.particle.ParticleGroup; 16 | 17 | /** 18 | * 19 | * @author Thomas Diewald 20 | * 21 | */ 22 | public interface DwParticleRenderGroupCallback { 23 | public int getRenderGroupIndex(int particle_idx, ParticleGroup group, int particle_flag); 24 | } -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/render/DwParticleRenderP5.java: -------------------------------------------------------------------------------- 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 | package com.thomasdiewald.liquidfun.java.render; 14 | 15 | import org.jbox2d.dynamics.World; 16 | 17 | import com.thomasdiewald.liquidfun.java.DwUtils; 18 | import com.thomasdiewald.liquidfun.java.DwViewportTransform; 19 | 20 | import processing.core.PApplet; 21 | import processing.core.PConstants; 22 | import processing.core.PMatrix2D; 23 | import processing.core.PShape; 24 | import processing.opengl.PGraphics2D; 25 | 26 | 27 | /** 28 | * 29 | * 30 | * Box2D/LiquidFun particles renderer.
31 | * Using PShape point-sprites for rendering.
32 | *
33 | * Performance is good, but DwParticleRenderGL is a lot faster.
34 | * 35 | * @author Thomas Diewald 36 | * 37 | */ 38 | public class DwParticleRenderP5 extends DwParticleRender{ 39 | 40 | public PShape shp_particles; 41 | 42 | public DwParticleRenderP5(PApplet papplet, World world, DwViewportTransform transform){ 43 | super(papplet, world, transform); 44 | shp_particles = papplet.createShape(PConstants.GROUP); 45 | } 46 | 47 | @Override 48 | public void release(){ 49 | super.release(); 50 | } 51 | 52 | 53 | @Override 54 | public void update(){ 55 | updateBuffers(); 56 | updateShapesCount(); 57 | updateShapesData(); 58 | } 59 | 60 | 61 | @Override 62 | public void display(PGraphics2D canvas){ 63 | // shp_particles.draw(canvas); 64 | canvas.shape(shp_particles); 65 | } 66 | 67 | 68 | protected void updateShapesCount(){ 69 | 70 | if(particle_num == 0){ 71 | return; 72 | } 73 | 74 | // synchronize buffer size 75 | int shp_count = shp_particles.getChildCount(); 76 | if(shp_count != particle_num){ 77 | 78 | // remove shapes, in case group is bigger than actual number 79 | for(int i = shp_count - 1; i >= particle_num; i--){ 80 | shp_particles.removeChild(i); 81 | } 82 | 83 | // add shapes, in case group is smaller then actual number 84 | for(int i = shp_count; i < particle_num; i++){ 85 | PShape shp_particle = papplet.createShape(); 86 | shp_particle.beginShape(PConstants.QUADS); 87 | shp_particle.noFill(); 88 | shp_particle.noStroke(); 89 | shp_particle.textureMode(PConstants.NORMAL); // TODO: report issue 90 | shp_particle.texture(param.tex_sprite); // TODO: report issue 91 | shp_particle.vertex(-1, -1, 0, 0); 92 | shp_particle.vertex(+1, -1, 1, 0); 93 | shp_particle.vertex(+1, +1, 1, 1); 94 | shp_particle.vertex(-1, +1, 0, 1); 95 | shp_particle.endShape(); 96 | shp_particles.addChild(shp_particle); 97 | } 98 | } 99 | } 100 | 101 | 102 | 103 | protected void updateShapesData(){ 104 | 105 | if(particle_num == 0){ 106 | return; 107 | } 108 | 109 | final PMatrix2D mat = new PMatrix2D(); 110 | 111 | for (int i = 0, ipos = 0, icol = 0; i < particle_num; i++) { 112 | // position 113 | float pos_x = buf_pos[ipos++]; 114 | float pos_y = buf_pos[ipos++]; 115 | // velocity 116 | // float vel_x = buf_vel[ivel++]; 117 | // float vel_y = buf_vel[ivel++]; 118 | // tint 119 | int tint = DwUtils.createColorARGB(buf_col, icol); icol += 4; 120 | 121 | mat.reset(); 122 | mat.translate(pos_x, pos_y); 123 | mat.scale(particle_rad_world); 124 | // mat.rotate((float)Math.atan2(vel_y, vel_x)); 125 | 126 | PShape shp = shp_particles.getChild(i); 127 | shp.resetMatrix(); 128 | // mat.translate(pos_x, pos_y); 129 | // mat.scale(particle_rad_world); 130 | shp.applyMatrix(mat); 131 | 132 | shp.setTint(tint); 133 | } 134 | 135 | } 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | } 145 | -------------------------------------------------------------------------------- /src/com/thomasdiewald/liquidfun/java/render/ShapeStyle.java: -------------------------------------------------------------------------------- 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 com.thomasdiewald.liquidfun.java.render; 15 | 16 | public class ShapeStyle { 17 | 18 | boolean fill_enabled = true; 19 | int fill_color = 0xFFC8C8C8; 20 | boolean stroke_enabled = true; 21 | int stroke_color = 0xFF000000; 22 | float stroke_weight = 1f; 23 | // TODO join, cap, etc... 24 | 25 | public ShapeStyle(){ 26 | } 27 | 28 | public ShapeStyle( 29 | boolean fill_enabled, 30 | int fill_color, 31 | boolean stroke_enabled, 32 | int stroke_color, 33 | float stroke_weight) 34 | { 35 | set(fill_enabled, fill_color, stroke_enabled, stroke_color, stroke_weight); 36 | } 37 | 38 | 39 | public ShapeStyle set( 40 | boolean fill_enabled, 41 | int fill_color, 42 | boolean stroke_enabled, 43 | int stroke_color, 44 | float stroke_weight) 45 | { 46 | this.fill_enabled = fill_enabled; 47 | this.fill_color = fill_color; 48 | this.stroke_enabled = stroke_enabled; 49 | this.stroke_color = stroke_color; 50 | this.stroke_weight = stroke_weight; 51 | return this; 52 | } 53 | 54 | 55 | 56 | 57 | } 58 | --------------------------------------------------------------------------------