/examples/advanced/physics/physicsShapes/PhysicsRectangle.java
Java | 490 lines | 300 code | 100 blank | 90 comment | 33 complexity | 4a0b35eaeab64c2630914ee9827be662 MD5 | raw file
1package advanced.physics.physicsShapes; 2 3import java.util.List; 4 5import javax.media.opengl.glu.GLU; 6 7import org.jbox2d.collision.shapes.PolygonDef; 8import org.jbox2d.common.Vec2; 9import org.jbox2d.dynamics.Body; 10import org.jbox2d.dynamics.BodyDef; 11import org.jbox2d.dynamics.World; 12import org.mt4j.MTApplication; 13import org.mt4j.components.MTComponent; 14import org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon; 15import org.mt4j.components.bounds.IBoundingShape; 16import org.mt4j.components.visibleComponents.shapes.GeometryInfo; 17import org.mt4j.components.visibleComponents.shapes.MTRectangle; 18import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor; 19import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor; 20import org.mt4j.util.math.Vector3D; 21import org.mt4j.util.math.Vertex; 22import org.mt4j.util.opengl.GluTrianglulator; 23 24import processing.core.PApplet; 25import processing.core.PGraphics; 26import processing.core.PImage; 27import advanced.physics.util.PhysicsHelper; 28 29public class PhysicsRectangle extends MTRectangle implements IPhysicsComponent{ 30 private float angle; 31 private boolean drawBounds; 32 33 private World world; 34 private Body body; 35 private float density; 36 private float friction; 37 private float restituion; 38 39 /* 40 PhysicsRectangle rect = new PhysicsRectangle(new Vector3D(400,200), 100,150, app, world, 0.6f, 0.4f, 0.2f, scale); 41 rect.setNoStroke(true); 42 PhysicsHelper.addDragJoint(world, rect, rect.getBody().isDynamic(), scale); 43 physObjGroup.addChild(rect); 44 */ 45 46 public PhysicsRectangle( 47 Vector3D centerPosition, 48 float width, float height, PApplet applet, 49 World world, float density, float friction, float restitution, float scale 50 ) { 51 super(applet, 0, 0, PhysicsHelper.scaleDown(width, scale), PhysicsHelper.scaleDown(height, scale)); 52 this.angle = 0; 53 this.drawBounds = false; 54 this.world = world; 55 this.density = density; 56 this.friction = friction; 57 this.restituion = restitution; 58 59 Vector3D scaledPos = PhysicsHelper.scaleDown(centerPosition.getCopy(), scale); 60// PhysicsHelper.scaleDown(centerPosition, scale); 61// centerPosition.scaleLocal(1f/scale); 62 63 BodyDef dymBodyDef = new BodyDef(); 64// dymBodyDef.position = new Vec2(pos.x, pos.y); 65 dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);//FIXME WORKS? 66 this.bodyDefB4CreationCallback(dymBodyDef); 67 this.body = world.createBody(dymBodyDef); 68 69 PolygonDef dymShapeDef = new PolygonDef(); 70 dymShapeDef.setAsBox( (width/2f)/scale, (height/2f)/scale); 71// dymShapeDef.setAsBox( (width/2f), (height/2f)); 72 if (density != 0.0f){ 73 dymShapeDef.density = density; 74 dymShapeDef.friction = friction; 75 dymShapeDef.restitution = restitution; 76 } 77 78 this.polyDefB4CreationCallback(dymShapeDef); //FIXME TEST 79 80 body.createShape(dymShapeDef); 81 body.setMassFromShapes(); 82 83 //TEST 84// theBody.setBullet(true); 85 86 this.setPositionGlobal(scaledPos); 87 body.setUserData(this); 88 this.setUserData("box2d", body); 89 this.setGestureAllowance(ScaleProcessor.class, false); 90 this.setGestureAllowance(RotateProcessor.class, false); 91 } 92 93 94 95 96 public PhysicsRectangle(PImage texture, 97 Vector3D pos, 98 PApplet applet, 99 Vertex[] physicsVertices, 100 World world, float density, float friction, float restitution, float scale 101 ) { 102 super(applet, texture); 103 this.angle = 0; 104 this.drawBounds = false; 105 this.world = world; 106 this.density = density; 107 this.friction = friction; 108 this.restituion = restitution; 109 110 this.setGestureAllowance(ScaleProcessor.class, false); 111 this.setGestureAllowance(RotateProcessor.class, false); 112 113 //Scale shape vertices 114// this.setGeometryInfo(new GeometryInfo(applet, Vertex.scaleVectorArray(this.getGeometryInfo().getVertices(), Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1))); 115// this.setGeometryInfo(new GeometryInfo(applet, PhysicsHelper.scaleDown(this.getGeometryInfo().getVertices(), scale))); 116 this.setGeometryInfo(new GeometryInfo(applet, PhysicsHelper.scaleDown(Vertex.getDeepVertexArrayCopy(this.getGeometryInfo().getVertices()), scale))); 117 118 //Scale physics vertics 119// Vertex.scaleVectorArray(bodyVerts, Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1); 120 PhysicsHelper.scaleDown(physicsVertices, scale); 121 122 Vector3D scaledPos = PhysicsHelper.scaleDown(pos.getCopy(), scale); 123 //Scale position 124// pos.scaleLocal(1f/scale); //FIXME REALLY? 125// PhysicsHelper.scaleDown(pos, scale); 126 127 this.setGestureAllowance(ScaleProcessor.class, false); 128 this.setGestureAllowance(RotateProcessor.class, false); 129 130 //Temporarily move the mesh so that we know where the calculated center of the body 131 //would be (the body takes the body.position as the center reference instead of a calculated center) 132// //FIXME welchen centerpoint nehmen? -> kommt auch drauf an ob shape schon auf canvas war!? 133 //We have to do this because the anchor point ("position") of the pyhsics shape is the body.position 134 //but the anchor point of our shapes is the point returned from getCenterpoint..() 135 this.translate(scaledPos); 136 Vector3D realBodyCenter = this.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter? 137 //Reset position 138 this.translate(scaledPos.getScaled(-1)); 139 140 //Now get the position where the global center will be after setting the shape at the desired position 141 this.setPositionGlobal(scaledPos); 142 Vector3D meshCenterAtPosition = this.getCenterPointGlobal(); 143 144 //Compute the distance we would have to move the vertices for the body creation 145 //so that the body.position(center) is at the same position as our mesh center 146 Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter); 147 //System.out.println("Diff:" + realBodyCenterToMeshCenter); 148 149 //FIXME TEST Needed for level saving the local vertices at the right position 150 this.setUserData("realBodyCenterToMeshCenter", realBodyCenterToMeshCenter); 151 152 //Move the vertices so the body position is at the center of the shape 153 Vertex.translateVectorArray(physicsVertices, realBodyCenterToMeshCenter); 154 155 //Create vertex structure for creation of decomposition polygon (use the translated vertices) 156 float xArr[] = new float[physicsVertices.length]; 157 float yArr[] = new float[physicsVertices.length]; 158 for (int i = 0; i < physicsVertices.length; i++) { 159 Vertex v = physicsVertices[i]; 160 xArr[i] = v.x; 161 yArr[i] = v.y; 162 } 163 164 //Create a polygon too see if its simple and eventually decompose it 165 org.jbox2d.util.nonconvex.Polygon myPoly = new org.jbox2d.util.nonconvex.Polygon(xArr, yArr); 166 167 //System.out.println("Polygon is simple! -> Using convex decomposition for physics shape and glu triangulated mesh for display!"); 168 PolygonDef pd = new PolygonDef(); 169 if (density != 0.0f){ 170 pd.density = density; 171 pd.friction = friction; 172 pd.restitution = restituion; 173 } 174 175 //Create polygon body 176 BodyDef dymBodyDef = new BodyDef(); 177 dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y); 178 this.bodyDefB4CreationCallback(dymBodyDef); 179 this.body = world.createBody(dymBodyDef); 180 181 this.polyDefB4CreationCallback(pd); //FIXME TEST 182 183 int success = org.jbox2d.util.nonconvex.Polygon.decomposeConvexAndAddTo(myPoly, body, pd); 184 if (success != -1){ 185 System.out.println("-> Ear clipping SUCCESSFUL -> Using triangulated and polygonized shape for b2d."); 186 body.setMassFromShapes(); 187 body.setUserData(this); 188 this.setUserData("box2d", body); 189 //Performance hit! but prevents object from sticking to another sometimes 190// theBody.setBullet(true); 191 }else{ 192 System.out.println("-> Ear clipping had an ERROR - trying again by triangulating shape for b2d with GLU-Triangulator"); 193 GluTrianglulator triangulator = new GluTrianglulator(applet); 194 List<Vertex> physicsTris = triangulator.tesselate(physicsVertices, GLU.GLU_TESS_WINDING_NONZERO); 195 Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]); 196 //System.out.println("GLU tris created: " + triangulatedBodyVerts.length); 197 198 //Cap the max triangles - dont use anymore triangles for the physics body.. 199 int cap = 400; 200 if (triangulatedBodyVerts.length > cap){ 201 //System.err.println("OVER cap! -> capping!"); 202 Vertex[] tmp = new Vertex[cap]; 203 System.arraycopy(triangulatedBodyVerts, 0, tmp, 0, cap); 204 triangulatedBodyVerts = tmp; 205 } 206 207 //Create polygon body 208 world.destroyBody(body); 209 dymBodyDef = new BodyDef(); 210 dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y); 211 this.bodyDefB4CreationCallback(dymBodyDef); 212 body = world.createBody(dymBodyDef); 213 for (int i = 0; i < triangulatedBodyVerts.length/3; i++) { 214 //Create polygon definition 215 PolygonDef polyDef = new PolygonDef(); 216 if (density != 0.0f){ 217 polyDef.density = density; 218 polyDef.friction = friction; 219 polyDef.restitution = restituion; 220 } 221 //Add triangle vertices 222 Vertex vertex1 = triangulatedBodyVerts[i*3]; 223 Vertex vertex2 = triangulatedBodyVerts[i*3+1]; 224 Vertex vertex3 = triangulatedBodyVerts[i*3+2]; 225 polyDef.addVertex(new Vec2(vertex1.x, vertex1.y)); 226 polyDef.addVertex(new Vec2(vertex2.x, vertex2.y)); 227 polyDef.addVertex(new Vec2(vertex3.x, vertex3.y)); 228 229 this.polyDefB4CreationCallback(pd); //FIXME TEST 230 231 //Add poly to body 232 body.createShape(polyDef); 233 } 234 body.setMassFromShapes(); 235 //performance hit!? 236 //theBody.setBullet(true); 237 body.setUserData(this); 238 this.setUserData("box2d", body); 239 triangulator.deleteTess(); 240 } 241 242 243 } 244 245 246 247 public void setPhysicsVertices(Vertex[] bodyVerts, 248 Vector3D pos, 249 float scale 250 ){ 251 if (this.body != null && this.world != null){ 252 world.destroyBody(this.body); 253 } 254 255 //Scale physics vertics 256// Vertex.scaleVectorArray(bodyVerts, Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1); 257 PhysicsHelper.scaleDown(bodyVerts, scale); 258 259 //Scale position 260// pos.scaleLocal(1f/scale); //FIXME REALLY? 261// PhysicsHelper.scaleDown(pos, scale); 262 Vector3D scaledPos = PhysicsHelper.scaleDown(pos.getCopy(), scale); 263 264 MTComponent parent = this.getParent(); 265 this.removeFromParent(); 266 267 //Temporarily move the mesh so that we know where the calculated center of the body 268 //would be (the body takes the body.position as the center reference instead of a calculated center) 269// //FIXME welchen centerpoint nehmen? -> kommt auch drauf an ob shape schon auf canvas war!? 270 //We have to do this because the anchor point ("position") of the pyhsics shape is the body.position 271 //but the anchor point of our shapes is the point returned from getCenterpoint..() 272 this.translate(scaledPos); 273 Vector3D realBodyCenter = this.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter? 274 //Reset position 275 this.translate(scaledPos.getScaled(-1)); 276 277 //Now get the position where the global center will be after setting the shape at the desired position 278 this.setPositionGlobal(scaledPos); 279 Vector3D meshCenterAtPosition = this.getCenterPointGlobal(); 280 281 if (parent != null){ 282 parent.addChild(this);//TODO add at same index 283 } 284 285 //Compute the distance we would have to move the vertices for the body creation 286 //so that the body.position(center) is at the same position as our mesh center 287 Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter); 288 //System.out.println("Diff:" + realBodyCenterToMeshCenter); 289 290 //Move the vertices so the body position is at the center of the shape 291 Vertex.translateVectorArray(bodyVerts, realBodyCenterToMeshCenter); 292 293 //FIXME TEST 294 this.setUserData("realBodyCenterToMeshCenter", realBodyCenterToMeshCenter); 295 296 //Create vertex structure for creation of decomposition polygon (use the translated vertices) 297 float xArr[] = new float[bodyVerts.length]; 298 float yArr[] = new float[bodyVerts.length]; 299 for (int i = 0; i < bodyVerts.length; i++) { 300 Vertex v = bodyVerts[i]; 301 xArr[i] = v.x; 302 yArr[i] = v.y; 303 } 304 305 //Create a polygon too see if its simple and eventually decompose it 306 org.jbox2d.util.nonconvex.Polygon myPoly = new org.jbox2d.util.nonconvex.Polygon(xArr, yArr); 307 308 //System.out.println("Polygon is simple! -> Using convex decomposition for physics shape and glu triangulated mesh for display!"); 309 PolygonDef pd = new PolygonDef(); 310 if (density != 0.0f){ 311 pd.density = density; 312 pd.friction = friction; 313 pd.restitution = restituion; 314 } 315 316 //Create polygon body 317 BodyDef dymBodyDef = new BodyDef(); 318 dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y); 319 this.bodyDefB4CreationCallback(dymBodyDef); 320 this.body = world.createBody(dymBodyDef); 321 322 this.polyDefB4CreationCallback(pd); //FIXME TEST 323 324 int success = org.jbox2d.util.nonconvex.Polygon.decomposeConvexAndAddTo(myPoly, body, pd); 325 if (success != -1){ 326 System.out.println("-> Ear clipping SUCCESSFUL -> Using triangulated and polygonized shape for b2d."); 327 body.setMassFromShapes(); 328 body.setUserData(this); 329 this.setUserData("box2d", body); 330 //Performance hit! but prevents object from sticking to another sometimes 331// theBody.setBullet(true); 332 }else{ 333 System.out.println("-> Ear clipping had an ERROR - trying again by triangulating shape for b2d with GLU-Triangulator"); 334 GluTrianglulator triangulator = new GluTrianglulator(this.getRenderer()); 335 List<Vertex> physicsTris = triangulator.tesselate(bodyVerts, GLU.GLU_TESS_WINDING_NONZERO); 336 Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]); 337 //System.out.println("GLU tris created: " + triangulatedBodyVerts.length); 338 339 //Cap the max triangles - dont use anymore triangles for the physics body.. 340 int cap = 400; 341 if (triangulatedBodyVerts.length > cap){ 342 //System.err.println("OVER cap! -> capping!"); 343 Vertex[] tmp = new Vertex[cap]; 344 System.arraycopy(triangulatedBodyVerts, 0, tmp, 0, cap); 345 triangulatedBodyVerts = tmp; 346 } 347 348 //Create polygon body 349 world.destroyBody(body); 350 dymBodyDef = new BodyDef(); 351 dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y); 352 this.bodyDefB4CreationCallback(dymBodyDef); 353 body = world.createBody(dymBodyDef); 354 for (int i = 0; i < triangulatedBodyVerts.length/3; i++) { 355 //Create polygon definition 356 PolygonDef polyDef = new PolygonDef(); 357 if (density != 0.0f){ 358 polyDef.density = density; 359 polyDef.friction = friction; 360 polyDef.restitution = restituion; 361 } 362 //Add triangle vertices 363 Vertex vertex1 = triangulatedBodyVerts[i*3]; 364 Vertex vertex2 = triangulatedBodyVerts[i*3+1]; 365 Vertex vertex3 = triangulatedBodyVerts[i*3+2]; 366 polyDef.addVertex(new Vec2(vertex1.x, vertex1.y)); 367 polyDef.addVertex(new Vec2(vertex2.x, vertex2.y)); 368 polyDef.addVertex(new Vec2(vertex3.x, vertex3.y)); 369 370 this.polyDefB4CreationCallback(polyDef); //FIXME TEST 371 //Add poly to body 372 body.createShape(polyDef); 373 } 374 body.setMassFromShapes(); 375 //FIXME TEST - performance hit!? 376 //theBody.setBullet(true); 377 body.setUserData(this); 378 this.setUserData("box2d", body); 379 triangulator.deleteTess(); 380 } 381 } 382 383 protected void polyDefB4CreationCallback(PolygonDef def){ 384 385 } 386 387 protected void bodyDefB4CreationCallback(BodyDef def){ 388 389 } 390 391// private Vertex[] physicsVertices; 392// 393// private Vertex[] getPhysicsVertices(){ 394// return this.physicsVertices; 395// } 396 397 398 399 400 //@Override 401 public void drawComponent(PGraphics g) { 402 super.drawComponent(g); 403 404 if (drawBounds){ 405 IBoundingShape bounds = this.getBounds(); 406 if (bounds instanceof BoundsArbitraryPlanarPolygon){ 407 BoundsArbitraryPlanarPolygon bound = (BoundsArbitraryPlanarPolygon)bounds; 408 409 Vector3D[] boundVecs = bound.getVectorsLocal(); 410// app.noFill(); 411 g.fill(100); 412 g.stroke(50); 413 g.beginShape(); 414 for (Vector3D v : boundVecs) { 415 // app.vertex(v.x*scale, v.y*scale, v.z); 416 g.vertex(v.x, v.y, v.z); 417 } 418 g.endShape(); 419 } 420 } 421 } 422 423 //@Override 424 public void rotateZGlobal(Vector3D rotationPoint, float degree) { 425 angle += degree; 426 super.rotateZGlobal(rotationPoint, degree); 427 } 428 429 public float getAngle() { 430 return angle; 431 } 432 433 public void setCenterRotation(float angle){ 434 float degreeAngle = MTApplication.degrees(angle); 435 float oldAngle = this.getAngle(); 436 float diff = degreeAngle-oldAngle; 437 //System.out.println("Old angle: " + oldAngle + " new angle:" + degreeAngle + " diff->" + diff); 438 this.rotateZGlobal(this.getCenterPointGlobal(), diff); 439 } 440 441 //@Override 442 protected void destroyComponent() { 443 super.destroyComponent(); 444 boolean exists = false; 445 for (Body body = world.getBodyList(); body != null; body = body.getNext()) { 446 if (body.equals(this.body)) 447 exists = true;//Delete later to avoid concurrent modification 448 } 449 if (exists) 450 world.destroyBody(body); 451 } 452 453 454 455 456 public World getWorld() { 457 return world; 458 } 459 460 461 462 463 public Body getBody() { 464 return body; 465 } 466 467 468 469 470 public float getDensity() { 471 return density; 472 } 473 474 475 476 477 public float getFriction() { 478 return friction; 479 } 480 481 482 483 484 public float getRestituion() { 485 return restituion; 486 } 487 488 489 490}